菜鸟教程 -- 学的不仅是技术,更是梦想!

设计模式
(追記) (追記ここまで)

模板模式

在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

介绍

意图

在父类中定义了算法的骨架,并允许子类在不改变算法结构的前提下重定义算法的某些特定步骤。

主要解决的问题

  • 解决在多个子类中重复实现相同的方法的问题,通过将通用方法抽象到父类中来避免代码重复。

使用场景

  • 当存在一些通用的方法,可以在多个子类中共用时。

实现方式

  • 定义抽象父类:包含模板方法和一些抽象方法或具体方法。
  • 实现子类:继承抽象父类并实现抽象方法,不改变算法结构。

关键代码

  • 模板方法:在抽象父类中定义,调用抽象方法和具体方法。
  • 抽象方法:由子类实现,代表算法的可变部分。
  • 具体方法:在抽象父类中实现,代表算法的不变部分。

应用实例

  • 建筑流程:地基、走线、水管等步骤相同,后期建筑如加壁橱、栅栏等步骤不同。
  • 西游记的81难:菩萨定好的81难代表一个顶层逻辑骨架。
  • Spring对Hibernate的支持:封装了如开启事务、获取Session、关闭Session等通用方法。

优点

  • 封装不变部分:算法的不变部分被封装在父类中。
  • 扩展可变部分:子类可以扩展或修改算法的可变部分。
  • 提取公共代码:减少代码重复,便于维护。

缺点

  • 类数目增加:每个不同的实现都需要一个子类,可能导致系统庞大。

使用建议

  • 当有多个子类共有的方法且逻辑相同时,考虑使用模板方法模式。
  • 对于重要或复杂的方法,可以考虑作为模板方法定义在父类中。

注意事项

  • 为了防止恶意修改,模板方法通常使用final关键字修饰,避免被子类重写。

包含的几个主要角色

  • 抽象父类(Abstract Class):

    • 定义了模板方法和一些抽象方法或具体方法。
  • 具体子类(Concrete Classes):

    • 继承自抽象父类,并实现抽象方法。
  • 钩子方法(Hook Method)(可选):

    • 在抽象父类中定义,可以被子类重写,以影响模板方法的行为。
  • 客户端(Client)(可选):

    • 使用抽象父类和具体子类,无需关心模板方法的细节。

实现

我们将创建一个定义操作的 Game 抽象类,其中,模板方法设置为 final,这样它就不会被重写。CricketFootball 是扩展了 Game 的实体类,它们重写了抽象类的方法。

TemplatePatternDemo,我们的演示类使用 Game 来演示模板模式的用法。

模板模式的 UML 图

步骤 1

创建一个抽象类,它的模板方法被设置为 final。

Game.java

publicabstractclassGame{abstractvoidinitialize(); abstractvoidstartPlay(); abstractvoidendPlay(); //模板publicfinalvoidplay(){//初始化游戏initialize(); //开始游戏startPlay(); //结束游戏endPlay(); }}

步骤 2

创建扩展了上述类的实体类。

Cricket.java

publicclassCricketextendsGame{ @OverridevoidendPlay(){System.out.println("Cricket Game Finished!"); } @Overridevoidinitialize(){System.out.println("Cricket Game Initialized! Start playing."); } @OverridevoidstartPlay(){System.out.println("Cricket Game Started. Enjoy the game!"); }}

Football.java

publicclassFootballextendsGame{ @OverridevoidendPlay(){System.out.println("Football Game Finished!"); } @Overridevoidinitialize(){System.out.println("Football Game Initialized! Start playing."); } @OverridevoidstartPlay(){System.out.println("Football Game Started. Enjoy the game!"); }}

步骤 3

使用 Game 的模板方法 play() 来演示游戏的定义方式。

TemplatePatternDemo.java

publicclassTemplatePatternDemo{publicstaticvoidmain(String[]args){Gamegame = newCricket(); game.play(); System.out.println(); game = newFootball(); game.play(); }}

步骤 4

执行程序,输出结果:

Cricket Game Initialized! Start playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished!
Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!
AI 思考中...

3 篇笔记 写笔记

  1. #0

    Siskin.xu

    sis***@sohu.com

    27

    Python 方式:

    # Template Pattern code with Python
    from abc import abstractmethod,ABCMeta
    # 创建一个game父类
    class Game(metaclass=ABCMeta):
     # 把几乎不变的公共部分代码集中在父亲类,比如showcopyright
     # 此例子中,初始化、开始、结束三个方法,除了游戏名以外,都一样,所以把共性部分放在父类
     def initialize(self):
     print("%s Game Initialized! Start Playing." %self.setGameName())
     def startPlay(self):
     print("%s Game Started. Enjoy the game!" % self.setGameName())
     def endPlay(self):
     print("%s Game Finished! \n" % self.setGameName())
     def play(self):
     self.initialize()
     self.startPlay()
     self.endPlay()
     # 每个游戏子类的抽象部分仅仅是游戏名称的设定
     @abstractmethod
     def setGameName(self):
     pass
    class Cricket(Game):
     def setGameName(self):
     return "Cricket"
    class Football(Game):
     def setGameName(self):
     return "Football"
    # 调用输出
    if __name__ == '__main__':
     game1 = Cricket()
     game1.play()
     game2 = Football()
     game2.play()

    Siskin.xu

    sis***@sohu.com

    6年前 (2020年02月28日)
  2. #0

    chpeagle

    chp***[email protected]

    9

    C++ 方式:

    Game.h

    #include <iostream>
    class Game
    {
    protected:
     virtual void initialize() = 0;
     virtual void startPlay() = 0;
     virtual void endPlay() = 0;
    public:
     virtual void play() {
     initialize();
     startPlay();
     endPlay();
     }
    };

    Cricket.h

    #include "Game.h"
    class Cricket :
     public Game
    {
    protected:
     virtual void initialize() {
     std::cout << "Cricket Game Finished!" << std::endl;
     }
     virtual void startPlay() {
     std::cout << "Cricket Game Initialized! Start playing." << std::endl;
     }
     virtual void endPlay() {
     std::cout << "Cricket Game Started. Enjoy the game!" << std::endl;
     }
    };

    Football.h

    #include "Game.h"
    class Football :
     public Game
    {
    protected:
     virtual void initialize() {
     std::cout << "Football Game Finished!" << std::endl;
     }
     virtual void startPlay() {
     std::cout << "Football Game Initialized! Start playing." << std::endl;
     }
     virtual void endPlay() {
     std::cout << "Football Game Started. Enjoy the game!" << std::endl;
     }
    };

    Main.cpp

    #include <iostream>
    #include "Cricket.h"
    #include "Football.h"
    int main(int argc, char* argv[]) {
     Game *game = new Cricket();
     game->play();
     std::cout << std::endl;
     game = new Football();
     game->play();
    }

    chpeagle

    chp***[email protected]

    6年前 (2020年08月17日)
  3. #0

    liangfang

    lia***[email protected]

    2

    PHP 实现:

    <?php
    abstract class Game{ 
     abstract function initialize(); 
     abstract function startPlay(); 
     abstract function endPlay(); 
     //模板 
     public final function play(){ 
     //初始化游戏 
     $this->initialize(); 
     //开始游戏 
     $this->startPlay(); 
     //结束游戏 
     $this->endPlay(); 
     }
    }
    class Cricket extends Game { 
     public function endPlay() { 
     echo "Cricket Game Finished!".PHP_EOL; 
     } 
     public function initialize() { 
     echo "Cricket Game Initialized! Start playing.".PHP_EOL; 
     } 
     public function startPlay() { 
     echo "Cricket Game Started. Enjoy the game!".PHP_EOL; 
     }
    }
    class Football extends Game { 
     public function endPlay() { 
     echo "Football Game Finished!"; 
     } 
     public function initialize() { 
     echo "Football Game Initialized! Start playing.".PHP_EOL; 
     } 
     public function startPlay() { 
     echo "Football Game Started. Enjoy the game!".PHP_EOL; 
     }
    }
    class TemplatePatternDemo { 
     public static function main() { 
     $game = new Cricket(); 
     $game->play(); 
     echo PHP_EOL; 
     $game = new Football(); 
     $game->play(); 
     }
    }
    TemplatePatternDemo::main();
    ?>

    liangfang

    lia***[email protected]

    5年前 (2021年03月30日)

点我分享笔记

  • 昵称 (必填)
  • 邮箱 (必填)
  • 引用地址

AltStyle によって変換されたページ (->オリジナル) /