Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design Patterns - Strategy Pattern

I am a beginner in Design Patterns.

Suppose I am developing a C# application to track the development works performed by various members in development team (i.e. a Project Tracker).

I am trying to be inspired by Strategy Pattern.

So I am designing my classes and interfaces as follows:

interface IEmployee
{
    void Retires();
    void TakesLeave();
}

interface IResponsible
{
void AcknowledgeJobAccomplish();
void CompletesJob();
}

interface ILeader
{
    void FormsTeam();
    void RecruitsNewMember();
    void KicksOutMemberFromTheTeam();
    void AssignsJob();
void UnassignsJob();
void QueriesTheJobStatus();
void ChangesTheJobStatus();
}

interface IPersistent
{
    void Save();
    void Update();
    void Delete();  
}

abstract class TeamMember : IEmployee, IResponsible, IPersistent
{
    string Name;
}

class Programmer : TeamMember
{
}

class LeadProgrammer : Programmer, ILeader
{
    ProgrammerCollection associateProgrammers;
}

class ProjectManager :  TeamMember, ILeader
{
    TeamMemberCollection teamMembers;
}

abstract class Tester : TeamMember
{
}

class UnitTester : Tester
{
}

class QC : Tester
{
}

class SupportStaff : TeamMember
{
}

What things should I do to improve this design?

like image 943
user366312 Avatar asked Jun 19 '09 16:06

user366312


Video Answer


1 Answers

Well, first off, what you have there is not an instance of a Strategy pattern. The Strategy Pattern allows for the dynamic specification of a method for getting things done. What you have here is really more of a standard interface design, where you allocate responsibilities and abilities by interface inheritance.

Edit: Let's use an example. Let's say that you have a group of Workers; you also have a set of Tasks. Each Worker can perform a Task. These Tasks can consist if several things, such as DoFoo() and DoBar(). Each Worker does not know what Task they will perform; they just know when they show up that they will do a Task.

So we'll want to model Workers as having a Task that they will perform. Since the Tasks vary widely, we'll implement the Task as an interface.

So we'll have:

public class Worker 
{
   public Task myTask;

   public Worker(Task task)
   {
      myTask = task;
   }

   public void DoWork() 
      {
      myTask.DoTask();
      }
   }
}

Interface Task
{
   void DoTask();
}

public class Task1 : Task
{
   public void DoTask()
   {
   // Do whatever Task1 will do
   }
}

public class Task2 : Task
{
   public void DoTask()
   {
   // Do whatever Task2 will do
   }
}

public class Job
{
   public List<Worker> workers;

   public void Job()
   {
      workers.Add(new Worker(new Task1()));
      workers.Add(new Worker(new Task2()));
   }

   public void DoJob()
   {
      foreach (Worker worker in workers)
      {
      worker.DoWork();
      }
   }

   public void ChangeJobsToTask1()
   {
      foreach (Worker worker in workers)
      {
         worker.myTask = new Task1();
      }
   }

   public void ChangeJobsToTask2()
   {
      foreach (Worker worker in workers)
      {
         worker.myTask = new Task2();
      }
   }
}

So what happens is that when we instantiate a Job, the Job creates two Workers. The first Worker has a Task1 task; the second Worker has a Task2 task. To make the Workers do their Tasks, we call the DoJob() method on the Job class, which just calls the DoWork() method on each of the Workers, which in turn calls the DoTask() method on each of the Tasks that the Workers were set with.

If we want to change the Workers to all do Task1, we call the ChangeJobsToTask1() method, which sets the Task to Task1 for all of the Worker objects contained by the Job; if, at that point, we call the DoJob() on the Job object, all the Workers will perform the Task1 task. Similarly, if we want to change the Tasks to Task2, just call the ChangeJobsToTask2() method; all the Workers will then execute the Task2.DoTask() when their DoWork() method is called.

The important point of abstraction here is that the Workers expose a DoWork() method, but they do not necessarily know what work it is that is being done. That is, the Tasks for the Workers are interchangeable; the Workers just know that they're going to do a Task, but the specifics of what it is are unimportant to the Workers.

like image 121
Paul Sonier Avatar answered Nov 15 '22 21:11

Paul Sonier