Декоратор (шаблон проектирования)
- 1 year ago
- 0
- 0
Шаблонный метод ( англ. Template method) — поведенческий шаблон проектирования , определяющий основу алгоритма и позволяющий наследникам переопределять некоторые шаги алгоритма, не изменяя его структуру в целом.
Abstract class (абстрактный класс) — определяет абстрактные операции, замещаемые в наследниках для реализации шагов алгоритма; реализует шаблонный метод, определяющий скелет алгоритма. Шаблонный метод вызывает замещаемые и другие, определенные в Abstract class, операции.
Concrete class (конкретный класс) — реализует замещаемые операции необходимым для данной реализации способом.
Concrete class предполагает, что инвариантные шаги алгоритма будут выполнены в AbstractClass .
В примерах шаблонный метод реализуется для игр.
/** * An abstract class that is common to several games in * which players play against the оthers, but only one is * playing at a given time. */ class GameObject { protected: int PlayersCount; virtual bool EndOfGame() = 0; virtual void InitializeGame() = 0; virtual void MakePlay(int player) = 0; virtual void PrintWinner() = 0; public: /* A template method: */ void PlayOneGame(int playersCount) { PlayersCount = playersCount; InitializeGame(); int j = 0; while (!EndOfGame()) { MakePlay(j); j = (j + 1) % playersCount; } PrintWinner(); } }; class Monopoly : public GameObject { protected: /* Implementation of necessary concrete methods */ void InitializeGame() override { // Initialize money } void MakePlay(int player) override { // Process one turn of player } bool EndOfGame() override { return true; } void PrintWinner() override { // Display who won } }; class Chess : public GameObject { protected: /* Implementation of necessary concrete methods */ void InitializeGame() override { // Put the pieces on the board } void MakePlay(int player) override { // Process a turn for the player } bool EndOfGame() override { // Return true if in Checkmate or Stalemate has been reached return true; } void PrintWinner() override { // Display the winning player } }; int main() { GameObject* game = new Monopoly(); game->PlayOneGame(2); return 0; }
package com.designpatterns.templatemethod; /* Коды разновидностей игр. * * Файл GameCode.java * */ public enum GameCode { CHESS, MONOPOLY } /* Абстрактный класс, реализация абстрактных методов которого будет специфичной для каждого вида игры. * * Файл Game.java * */ public abstract class Game { private int playersAmount; protected abstract void initializeGame(); protected abstract void playGame(); protected abstract void endGame(); protected abstract void printWinner(); public final void playOneGame(int playersAmount){ setPlayersAmount(playersAmount); initializeGame(); playGame(); endGame(); printWinner(); } public void setPlayersAmount(int playersAmount){ this.playersAmount = playersAmount; } } package com.designpatterns.templatemethod; /* Игра "Шахматы". Специфически только для шахмат реализует методы класса Game. * * Файл Chess.java * */ public class Chess extends Game { @Override protected void initializeGame() { // chess specific initialization actions } @Override protected void playGame() { // chess specific play actions } @Override protected void endGame() { // chess specific actions to end a game } @Override protected void printWinner() { // chess specific actions to print winner } } package com.designpatterns.templatemethod; /* Игра "Монополия". Специфически только для монополии реализует методы класса Game. * * Файл Monopoly.java * */ public class Monopoly extends Game{ @Override protected void initializeGame() { // monopoly specific initialization actions } @Override protected void playGame() { // monopoly specific play actions } @Override protected void endGame() { // monopoly specific actions to end a game } @Override protected void printWinner() { // monopoly specific actions to print winner } } package com.designpatterns.templatemethod; /* Класс, показывающий работу шаблона проектирования "Шаблонный метод". * * Файл GamesManager.java * */ public class GamesManager { public static void main (String [] args){ final GameCode gameCode = GameCode.CHESS; Game game; switch (gameCode){ case CHESS : game = new Chess(); break; case MONOPOLY : game = new Monopoly(); break; default : throw new IllegalStateException(); } game.playOneGame(2); } }
/** * An abstract class that is common to several games in * which players play against the others, but only one is * playing at a given time. */ namespace Design_Patterns { class TemplateMethodPattern { internal abstract class GameObject { protected int PlayersCount; abstract protected bool EndOfGame(); abstract protected void InitializeGame(); abstract protected void MakePlay(int player); abstract protected void PrintWinner(); /* A template method : */ public void PlayOneGame(int playersCount) { PlayersCount = playersCount; InitializeGame(); var j = 0; while (!EndOfGame()) { MakePlay(j); j = (j + 1) % playersCount; } PrintWinner(); } } //Now we can extend this class in order to implement actual games: public class Monopoly : GameObject { /* Implementation of necessary concrete methods */ protected override void InitializeGame() { // Initialize money } protected override void MakePlay(int player) { // Process one turn of player } protected override bool EndOfGame() { return true; } protected override void PrintWinner() { // Display who won } /* Specific declarations for the Monopoly game. */ // ... } public class Chess : GameObject { /* Implementation of necessary concrete methods */ protected override void InitializeGame() { // Put the pieces on the board } protected override void MakePlay(int player) { // Process a turn for the player } protected override bool EndOfGame() { return true; // Return true if in Checkmate or Stalemate has been reached } protected override void PrintWinner() { // Display the winning player } /* Specific declarations for the chess game. */ // ... } public static void Test() { GameObject game = new Monopoly(); game.PlayOneGame(2); } } }
from abc import ABCMeta, abstractmethod class Unit(metaclass=ABCMeta): """ Абстрактный отряд. Атрибуты класса, начинающиеся с подчеркивания в python являются protected """ def __init__(self, speed: int) -> None: """ Constructor. :param speed: скорость отряда """ self._speed = speed def hit_and_run(self) -> None: """ Шаблонный метод """ self._move('вперед') self._stop() self._attack() self._move('назад') @abstractmethod def _attack(self) -> None: pass @abstractmethod def _stop(self) -> None: pass def _move(self, direction: str) -> None: """ Передвижение - у всех отрядов одинаковое, в шаблон не входит :param direction: направление движения """ self._output('движется {} со скоростью {}'.format(direction, self._speed)) def _output(self, message: str) -> None: """ Вспомогательный метод вывода сообщений, в шаблон не входит :param message: выводимое сообщение """ print('Отряд типа {} {}'.format(self.__class__.__name__, message)) class Archers(Unit): """ Лучники """ def _attack(self) -> None: self._output('обстреливает врага') def _stop(self) -> None: self._output('останавливается в 100 шагах от врага') class Cavalrymen(Unit): """ Кавалеристы """ def _attack(self) -> None: self._output('на полном скаку врезается во вражеский строй') def _stop(self) -> None: self._output('летит вперед, не останавливаясь') if __name__ == '__main__': print('OUTPUT:') archers = Archers(4) archers.hit_and_run() cavalrymen = Cavalrymen(8) cavalrymen.hit_and_run() ''' OUTPUT: Отряд типа Archers движется вперед со скоростью 4 Отряд типа Archers останавливается в 100 шагах от врага Отряд типа Archers обстреливает врага Отряд типа Archers движется назад со скоростью 4 Отряд типа Cavalrymen движется вперед со скоростью 8 Отряд типа Cavalrymen летит вперед, не останавливаясь Отряд типа Cavalrymen на полном скаку врезается во вражеский строй Отряд типа Cavalrymen движется назад со скоростью 8 '''