7

私はデザインパターンの初心者です。

開発チームのさまざまなメンバーが行った開発作業を追跡する C# アプリケーション (つまり、プロジェクト トラッカー) を開発しているとします。

私は戦略パターンに触発されようとしています。

したがって、次のようにクラスとインターフェイスを設計しています。

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
{
}

このデザインを改善するにはどうすればよいですか?

4

4 に答える 4

10

まず最初に、そこにあるのは戦略パターンのインスタンスではありません。戦略パターンでは、物事を成し遂げるための方法を動的に指定できます。ここにあるのは、インターフェイスの継承によって責任と能力を割り当てる、より標準的なインターフェイス設計です。

編集:例を使用しましょう。ワーカーのグループがあるとしましょう。一連のタスクもあります。各ワーカーはタスクを実行できます。これらのタスクは、DoFoo() や DoBar() など、複数の場合に構成できます。各ワーカーは、実行するタスクを知りません。彼らは、タスクを実行することをいつ表示するかを知っているだけです。

そのため、実行するタスクを持つものとしてワーカーをモデル化する必要があります。Task は大きく異なるため、Task をインターフェイスとして実装します。

したがって、次のようになります。

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();
      }
   }
}

つまり、 をインスタンス化するJobと、Jobは 2 つの を作成しますWorker。最初のものWorkerにはTask1タスクがあります。2番目WorkerにはTask2タスクがあります。Workers に sを実行させるには、クラスのメソッドTaskを呼び出します。このメソッドは、各 s のメソッドを呼び出すだけで、 s が設定され た各s のメソッドを呼び出します。DoJob()JobDoWork()WorkerDoTask()TaskWorker

Workers を all doに変更したい場合はTask1、 メソッドを呼び出します。このメソッドは、 ;に含まれるすべてのオブジェクトに対してtoChangeJobsToTask1()を設定します。その時点でオブジェクトの を呼び出すと、すべての がタスクを実行します。同様に、 s をに変更したい場合は、単にメソッドを呼び出します。すべての は、メソッドが呼び出されたときにを実行します。TaskTask1WorkerJobDoJob()JobWorkerTask1TaskTask2ChangeJobsToTask2()WorkerTask2.DoTask()DoWork()

ここでの抽象化の重要な点は、Workers がメソッドを公開するDoWork()ことですが、実行されている作業が何であるかを必ずしも知っているわけではありません。つまりTaskWorkerの は交換可能です。sはWorker、自分が を実行することを知っているだけですTaskが、それが何であるかの詳細は s にとって重要ではありませんWorker

于 2009-06-19T16:45:52.020 に答える
2

あなたの例には戦略パターンがありません。ストラテジーパターンは「strategy」クラス(通常は「DoJob()」などの論理メソッドを持つインターフェースから継承)をパラメータに取り、メソッドが呼び出されると、それが何であるかを知らずに先に渡されたストラテジーを適用して操作を行います。具体的に行います。

あなたの例では、すべての人が継承し、SetJob(IJobStrategy) を持ち、インターフェース DoJob() (IJobStrategy から) を呼び出す DoJob() メソッドを持つクラスを持つことができます。それよりも、IJobStrategy を継承する具体的なジョブを複数持つことができます。このようにして、あなたの人々は仕事を知らず、人のクラスを変更することなく仕事を変えることができます.

例と詳細については、こちらを参照してください。

于 2009-06-19T16:44:37.777 に答える
0

これは、インターフェイス分離の原則によく似ています。さて、それは戦略とうまく機能しますが、ここで私が違うものにします.

Tester は Concrete クラスではなく、TesterCompletesJobStrategy が CompletesJobStrategy として構成された TeamMember になります。結局のところ、私をテストから遠ざけているのは、チームで現在割り当てられているタスクだけです。

話のポイントとして、戦略をターゲットにしている場合は、このようなものから始めます。

interface ICompleteJobStrategy {
   void CompleteJob(IResponsible responsibleParty);
}
class TesterCompletJobStrategy : ICompleteJobStrategy {
    ...
}
class TeamMember : IResponsible {
   TeamMember(ICompleteJobStrategy strat){ .. };
   void CompleteJob() { _completeJobStrategy.CompleteJob(this) ; }
}
于 2009-06-19T16:53:04.027 に答える
0

次のように、代わりにC#で「動的」を使用できます。

メソッド(動的入力)

メソッド(DTO1入力) メソッド(DTO2入力) メソッド(DTO3入力)

コンプライタイムエラーなし

于 2020-08-07T14:40:03.173 に答える