跳转到内容

模板方法

25% developed
来自维基教科书,开放的书籍,开放的世界

策略 计算机科学设计模式
模板方法
访问者

定义一个算法的骨架,将一些步骤延迟到子类中。模板方法允许子类在不改变算法结构的情况下,重新定义算法的某些步骤。

C# 实现
using System;

  class MainApp
  {
    static void Main()
    {
      AbstractClass c;
 
      c = new ConcreteClassA();
      c.TemplateMethod();

      c = new ConcreteClassB();
      c.TemplateMethod();

      // Wait for user
      Console.Read();
    }
  }

  // "AbstractClass"
  abstract class AbstractClass
  {
    public abstract void PrimitiveOperation1();
    public abstract void PrimitiveOperation2();
    // The "Template method"
    public void TemplateMethod()
    {
      PrimitiveOperation1();
      PrimitiveOperation2();
      Console.WriteLine("");
    }
  }

  // "ConcreteClass"
  class ConcreteClassA : AbstractClass
  {
    public override void PrimitiveOperation1()
    {
      Console.WriteLine("ConcreteClassA.PrimitiveOperation1()");
    }
    public override void PrimitiveOperation2()
    {
      Console.WriteLine("ConcreteClassA.PrimitiveOperation2()");
    }
  }

  class ConcreteClassB : AbstractClass
  {
    public override void PrimitiveOperation1()
    {
      Console.WriteLine("ConcreteClassB.PrimitiveOperation1()");
    }
    public override void PrimitiveOperation2()
    {
      Console.WriteLine("ConcreteClassB.PrimitiveOperation2()");
    }
  }
Java 实现
/**
 * 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.
 */
abstract class Game {

    protected int playersCount;
    abstract void initializeGame();
    abstract void makePlay(int player);
    abstract boolean endOfGame();
    abstract void printWinner();

    /* A template method : */
    public final void playOneGame(int playersCount) {
        this.playersCount = playersCount;
        initializeGame();
        int j = 0;
        while (!endOfGame()) {
            makePlay(j);
            j = (j + 1) % playersCount;
        }
        printWinner();
    }
}
// Now we can extend this class in order
// to implement actual games:

class Monopoly extends Game {

    /* Implementation of necessary concrete methods */
    void initializeGame() {
        // Initialize players
        // Initialize money
    }

    void makePlay(int player) {
        // Process one turn of player
    }

    boolean endOfGame() {
        // Return true if game is over
        // according to Monopoly rules
    }

    void printWinner() {
        // Display who won
    }

    /* Specific declarations for the Monopoly game. */

    // ...
}
import java.util.Random;

class SnakesAndLadders extends Game {

    /* Implementation of necessary concrete methods */
    void initializeGame() {
        // Initialize players
        playerPositions = new int[playersCount];
        for (int i = 0; i < playersCount; i++) {
           playerPositions[i] = 0;
        }

        die = new Random();

        winnerId = -1;
    }

    void makePlay(int player) {
        // Roll the die
        int dieRoll = die.nextInt(6) + 1;

        // Move the token
        playerPositions[player] += dieRoll;

        // Move up or down because of the ladders or the snakes
        int penaltyOrBonus = board[playerPositions[player]];
        playerPositions[player] += penaltyOrBonus;

        if (playerPositions[player] > 8) {
           // Has reached the top square
           winnerId = player;
        }
    }

    boolean endOfGame() {
        // The game is over when a winner exists
        return (winnerId != -1);
    }

    void printWinner() {
        System.out.println("Player #" + winnerId + " has won!");
    }

    /* Specific declarations for the Snakes and Ladders game. */

    // The board from the bottom square to the top square
    // Each integer is a square
    // Negative values are snake heads with their lengths
    // Positive values are ladder bottoms with their heights
    private static final int[] board = {0, 0, -1, 0, 3, 0, 0, 0, -5, 0};

    // The player positions
    // Each integer represents one player
    // The integer is the position of the player (index) on the board
    private int[] playerPositions = null;

    private Random die = null;

    private int winnerId = -1;
}
Java 8 使用函数接口的实现
/**
 * The same example from above but with Java 8 
 * functional interfaces. Note that now Game
 * class doesn't have to be abstract.
 */
class Game {
    protected int playersCount;

    /*
     * Note that abstract methods are now replaced
     * with functional interface instances. It gives you a lot
     * more of flexibility: you can require all of them to be set
     * via constructor, you can wrap them or you can set default
     * implementations.
     */
    private final Runnable initializeGame;
    private final Consumer<Integer> makePlay;
    private final Supplier<Boolean> endOfGame;
    private final Runnable printWinner;

    /*
     * Constructor with parameters initialization.
     * Note that you can define multiple constructors
     * with different sets of parameters or define
     * default values for null values. Subclasses
     * are required to call at least one of constructors
     * if you don't define a default one.
     */
    protected Game(Consumer<Integer> makePlay, Supplier<Boolean> endOfGame) {
        // you can set default if omitted
        this.makePlay = Optional.ofNullable(makePlay).orElseGet((i)->{});
        // you can require non-null param
        this.endOfGame = Objects.requireNonNull(endOfGame);
        // ... and set defaults for optional parameters
        this.initializeGame = ()->{};
        this.printWinner = ()->{};
    }

    /*
     * Provide setters for customization if you don't provide
     * constructor for every combination of parameters.
     */
     protected void setGameInitializer(Runnable initializeGame) {
        this.initializeGame = Objects.requireNonNull(initializeGame);
     }

     protected void setWinnerPrinter(Runnable printWinner) {
        this.printWinner = Objects.requireNonNull(printWinner);
     }

    /* A template method calling functional interfaces: */
    public final void playOneGame(int playersCount) {
        this.playersCount = playersCount;
        initializeGame.run();
        int j = 0;
        while (!endOfGame.get()) {
            makePlay.accept(j);
            j = (j + 1) % playersCount;
        }
        printWinner.run();
    }
}
// Now we can extend this class in order
// to implement an actual game.
// Note that there's no need to define methods
// that you don't want to override. For methods
// you'd like to override you can either supply
// a functional reference or a lambda:
class Monopoly extends Game {

    public Monopoly() {
        //Initialize parent with functional references
        super(this::makePlay, this::endOfGame);
        // make additional tweaking if you need to.
        // you can even change it in runtime if you want!
        setGameInitializer(this::startGame);
    }

    /*
     * Implementation of concrete method. Note that names
     * can be different now!
     */
    void startGame() {
        // Initialize players
        // Initialize money
    }

    void makePlay(int player) {
        // Process one turn of player
    }

    boolean endOfGame() {
        // Return true if game is over
        // according to Monopoly rules
    }

    /* Specific declarations for the Monopoly game. */

    // ...
}
PHP 实现
abstract class Game
{
    abstract protected void initialize();
    abstract protected void startPlay();
    abstract protected void endPlay();

    /** Template method */
    public final void play()
    {
        /** Primitive */
        initialize();

        /** Primitive */
        startPlay();

        /** Primitive */
        endPlay();
    }
}

class Mario extends Game
{
    protected void initialize()
    {
        echo "Mario Game Initialized! Start playing.", PHP_EOL;
    }

    protected void startPlay()
    {
        echo "Mario Game Started. Enjoy the game!", PHP_EOL;
    }

    protected void endPlay()
    {
        echo "Mario Game Finished!", PHP_EOL;
    }
}

class Tankfight extends Game
{
    protected void initialize()
    {
        echo "Tankfight Game Initialized! Start playing.", PHP_EOL;
    }

    protected void startPlay()
    {
        echo "Tankfight Game Started. Enjoy the game!", PHP_EOL;
    }

    protected void endPlay()
    {
        echo "Tankfight Game Finished!", PHP_EOL;
    }
}

$game = new Tankfight();
$game->play();

$game = new Mario();
$game->play();
Scala 实现
case class Song(name: String, lyrics: String, music: String)

trait ConcertPlayer {
  def specialEffectsStart()

  def greetTheAudience()

  def introduceYourSelf()

  def songsIterator(): Iterable[Song]

  def sayGoodbye()

  final def playConcert() {
    specialEffectsStart()
    greetTheAudience()
    introduceYourSelf()
    songsIterator() foreach { song =>
      println(s"Now we will play the song named ${song.name}")
      println(song.music)
      println(song.lyrics)
    }
    sayGoodbye()
  }
}

class Artist1 extends ConcertPlayer {
  def sayGoodbye() {
    println("See you!")
  }

  def songsIterator(): Iterable[Song] =
    1 to 10 map { index =>
      Song(s"song $index", s"lyrics $index", s"music $index")
    }

  def introduceYourSelf() {
    println("I'm the Artist1!")
  }

  def greetTheAudience() {
    println("Hey!")
  }

  def specialEffectsStart() {
    println("Pyrotechnics...")
  }
}

class Artist2 extends ConcertPlayer {
  def sayGoodbye() {
    println("Bye-Bye")
  }

  def songsIterator(): Iterable[Song] =
    11 to 21 map { index =>
      Song(s"song $index", s"lyrics $index", s"music $index")
    }

  def introduceYourSelf() {
    println("I'm the Artist2!")
  }

  def greetTheAudience() {
    println("Hi!")
  }

  def specialEffectsStart() {
    println("Flames...")
  }
}

object TemplateMethodTest extends App {
  val artist1 = new Artist1
  val artist2 = new Artist2
  artist1.playConcert()
  artist2.playConcert()
}


Clipboard

待办事项
添加更多插图。


策略 计算机科学设计模式
模板方法
访问者


您对此页面有任何疑问吗?
在此提问


在本图书上创建新页面


华夏公益教科书