Шаблоны разработки - стратегическая модель

У меня нет точек репортажа, чтобы отправить это в качестве комментария к отличному ответу Чиль тен Бринке, поэтому я предложу здесь более полезную версию его цветового сценария:

import curses
def main(stdscr):
    curses.start_color()
    curses.use_default_colors()
    for i in range(0, curses.COLORS):
        curses.init_pair(i + 1, i, -1)
    stdscr.addstr(0, 0, '{0} colors available'.format(curses.COLORS))
    maxy, maxx = stdscr.getmaxyx()
    maxx = maxx - maxx % 5
    x = 0
    y = 1
    try:
        for i in range(0, curses.COLORS):
            stdscr.addstr(y, x, '{0:5}'.format(i), curses.color_pair(i))
            x = (x + 5) % maxx
            if x == 0:
                y += 1
    except curses.ERR:
        pass
    stdscr.getch()
curses.wrapper(main)
6
задан cgp 19 June 2009 в 16:42
поделиться

3 ответа

Во-первых, то, что у вас есть, не является экземпляром шаблона стратегии. Шаблон стратегии позволяет динамически определять метод выполнения задач. То, что у вас здесь, действительно больше похоже на стандартный дизайн интерфейса, в котором вы распределяете обязанности и способности посредством наследования интерфейса.

Edit: Давайте воспользуемся примером. Допустим, у вас есть группа Рабочих; у вас также есть набор Задач. Каждый работник может выполнить задачу. Эти Задачи могут состоять из нескольких вещей, таких как DoFoo () и DoBar (). Каждый Рабочий не знает, какую Задачу он будет выполнять; они просто знают, когда появляются, что они будут выполнять Задачу.

Итак, мы хотим смоделировать Рабочих как имеющих Задачу, которую они будут выполнять. Поскольку Задачи сильно различаются, мы реализуем Задачу как интерфейс.

Итак, у нас будет:

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 создает два Worker s. Первый Worker имеет задачу Task1 ; у второго Worker есть задача Task2 . Чтобы заставить Worker выполнять свои Task s, мы вызываем метод DoJob () класса Job , который просто вызывает DoWork () метод для каждого из Worker s, который, в свою очередь, вызывает метод DoTask () для каждого из Task s которые были установлены для рабочих .

Если мы хотим изменить Worker на все do Task1 , мы вызываем метод ChangeJobsToTask1 () , который устанавливает Task в Task1 для всех объектов Worker , содержащихся в Job ; если в этот момент мы вызовем DoJob () для объекта Job , все Worker s будут выполнять задачу Task1 . Точно так же, если мы хотим изменить Task s на Task2 , просто вызовите метод ChangeJobsToTask2 () ; все Worker будут затем выполнять Task2.DoTask () , когда вызывается их метод DoWork () .

Важным моментом абстракции здесь является что Worker предоставляют метод DoWork () , но они не обязательно знают, какая работа выполняется. То есть, задачи для рабочих взаимозаменяемы; Worker просто знают, что они собираются выполнить Task , но детали того, что это такое, не важны для Worker s.

9
ответ дан 9 December 2019 в 22:39
поделиться

Я не вижу шаблон стратегии в вашем примере. Шаблон стратегии принимает класс «стратегии» (обычно наследуется от интерфейса с логическим методом, например, «DoJob ()») в параметре, и когда метод вызывается, он будет выполнять операцию, применяя стратегию, переданную ранее, не зная, что это конкретно сделаю.

В вашем примере у вас может быть класс, унаследованный всеми вашими людьми, который имеет SetJob (IJobStrategy) и метод DoJob (), который будет вызывать интерфейс DoJob () (из IJobStrategy). Затем у вас может быть несколько конкретных заданий, наследующих IJobStrategy. Таким образом, ваши люди не знают работу, и вы можете изменить работу, не изменяя класс сотрудников.

Вы можете увидеть пример и дополнительную информацию здесь .

2
ответ дан 9 December 2019 в 22:39
поделиться

Это больше похоже на принцип разделения интерфейса. Это хорошо сочетается со стратегией, но вот что я бы сделал по-другому.

Tester не будет классом Concrete, это будет TeamMember с TesterCompletesJobStrategy, настроенным как CompletesJobStrategy. В конце концов, единственное, что удерживает меня от тестирования, - это моя текущая задача в команде.

В качестве темы для разговора я бы начал с чего-то вроде этого, если бы я был нацелен на Стратегию.

interface ICompleteJobStrategy {
   void CompleteJob(IResponsible responsibleParty);
}
class TesterCompletJobStrategy : ICompleteJobStrategy {
    ...
}
class TeamMember : IResponsible {
   TeamMember(ICompleteJobStrategy strat){ .. };
   void CompleteJob() { _completeJobStrategy.CompleteJob(this) ; }
}
0
ответ дан 9 December 2019 в 22:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: