Thursday, August 27, 2009

Working with Strategy in AS3/Flex

Strategy tells us to
• Define and encapsulate a family of algorithms.
• Make encapsulated algorithms interchangeable.
• Allow algorithms to change independently from the clients that use it.

HRAgency

For illustration purposes,in this sample application, a Strategy pattern is used to implement a solution for an HR employment agency.
• The agency has a number of consultants it represents. Clients call for different consultant job types targeted at either- employer or jobseeker. They want either a particular consultant or particular support tasks or main tasks they can perform.
• To create a flexible program for the HR agency, each of the specific support related and main tasks has been created in separate algorithms. The algorithms are encapsulated, and the consultants delegate their performance skills to the encapsulated algorithms—strategies.

The base Consultant context class


The first step is to create a context class and concrete contexts that will use the different tasks and support jobs.
Consultant class is the base class, establishing the references to the strategy methods.
The main tasks and support operations are delegated to the strategy classes.

The concrete Consultant classes
• EmployeeConsultant extends the context Consultant
• JobSeekerConsultant extends the context Consultant

Each is assigned a different task and support that are delegated to concrete strategy instances.




package
{
class Consultant
{
protected var mytasks:ITasks;
protected var mysupport:ISupport;
public function doManagementTasks( ):void
{
mytasks.task( );
}
public function doSupportTasks( ):void
{
mysupport.support( );
}
}
}

package
{
class EmployeeConsultant extends Consultant
{
public function EmployeeConsultant( )
{
tasks = new NewHireInduction( );
support = new FileRecord( );
}
}
}

package
{
class JobSeekerConsultant extends Consultant
{
public function JobSeekerConsultant( )
{
tasks = new Close( );
support = new CallUp( );
}
}
}


The Tasks Interface and Implementations

All the algorithms for doing tasks are encapsulated in the concrete strategy subclasses.
The TASKS interface provides the abstract method, and the subclasses add detail to the operations. A total of three TASK algorithms are implemented.
• Manage.as
• Close.as
• NewHireInduction.as




package
{
interface ITasks
{
function task( ):void;
}

}

package
{
//Manage Multiple Projects
public class Manage implements Tasks
{
public function tasks( ):void
{
trace("Look at me juggle! Whoops!\n")
}
}
}

package
{
//Make Open Files Close
public class Close implements ITasks
{
public function task( ):void
{
trace("Now close the open tasks. Successfully found the job!\n")
}
}
}



The Support Interface and Implementations

All the algorithms for doing tasks are encapsulated in the concrete strategy subclasses.
The SUPPORT interface provides the abstract method, and the subclasses add detail to the operations.
A total of two SUPPORT algorithms are implemented.
• Callup.as
• FileRecord.as




package
{
//Support Tasks Interface
interface ISupport
{
function support( ):void;
}
}

package
{
//Consultants chase each other
public class CallUp implements ISupport
{
public function support( ):void
{
trace("Status Call - I'm going to talk to you!");
}
}
}

package
{
public class FileRecord implements ISupport
{
public function support( ):void
{
trace("I'm adding this client in the records!")

}
}
}


The HRManager Sprite

The HRManager class instantiates two different consultant classes, through their interfaces rather than implementations by instantiating through the Consultant subclasses.
All are delegated from the Consultant context class and implemented in the concrete consultant classes.
The output represents the algorithms set up in the strategy classes.

package {
import flash.display.Sprite;

public class HRManager extends Sprite
{
public function HRManager()
{
var jobseeker:Consultant=new JobSeekerConsultant();
jobseeker.doManagementTasks();
jobseeker.doSupportTasks();

var employer:Consultant=new EmployeeConsultant();
employer.doManagementTasks();
employer.doSupportTasks();
}
}
}