模版方法模式

Template Method

组建协作: (晚绑定,运行时绑定)

    Template Method (模板方法)

    Strategy (策略模式)

    Observer/ Event  (观察者/事件)

面向对象设计模式是“好的面向对象设计”,所谓“好的面向对象设计”指是那些可以满足
“应对变化,提高复用”的设计 。

现代软件设计的特征是“需求的频繁变化”。设计模式的要点是“寻找变化点,然后在变化
点处应用设计模式,从而来更好地应对需求的变化”.“什么时候、什么地点应用设计模式”
比“理解设计模式结构本身”更为重要。

设计模式的应用不宜先入为主,一上来就使用设计模式是对设计模式的最大误用。没有
一步到位的设计模式。敏捷软件开发实践提倡的“Refactoring to Patterns”是目前普遍公认的最好的使用设计模式的方法。

动机 (Motivation)

  • 在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务
  • 的整体结构同时实现。

定义

定义一个操作中的算法的骨架 (稳定),而将一些步骤延迟(变化)到子类中。Template
Method使得子类可以不改变(复用)一个算法的结构即可重定义(override 重写)该算法的
某些特定步骤。
                              ——《设计模式》GoF

我们可以看到应用程序开发人员既要负责自己的任务,同时还需要负责程序的运行。这对
于应用程序开发人员来说负担太重。另一方面,再以后需求变化的时候,应用程序开发人员需要对所有的程序流程进行更改,这里的工作量是很大的。

1.1 制作汽车

class Car
{
public:
    // 汽车启动
   virtual void start() = 0;
   // 汽车停止
   virtual void stop() = 0;
   // 汽车喇叭
   virtual void alarm() = 0;
};

class BMW : public Car
{
public:
    void start()
    {
        cout << "宝马车启动了..." << endl;
    }
    // 汽车停止
    void stop()
    {
        cout << "宝马停止了" << endl;
    }
    // 汽车喇叭
    void alarm()
    {
        cout << "宝马鸣笛,屌丝让道" << endl;
    }
    void run()
    {
        this->start();

        this->alarm();

        this->stop();
    }
};

class Alto : public Car
{
public:
    void start()
    {
        cout << "二手破烂Alto启动好久终于动了..." << endl;
    }
    // 汽车停止
    void stop()
    {
        cout << "Alto靠脚刹停止了" << endl;
    }
    // 汽车喇叭
    void alarm()
    {
        cout << "Alto鸣笛,发现喇叭坏了" << endl;
    }

    void run()
    {
        this->start();

        this->alarm();

        this->stop();
    }
};
// ... 各种汽车型号
class Benz : public Car 
{
    // ...功能类似
    void run()
    {
        this->start();

        this->alarm();

        this->stop();
    }
};

我们可以清楚的看到,对于run的函数,我们好像是一直在复制粘贴,代码都是一样的。
当一段代码重复使用多次,我们就需要警惕了。这说明我们需要重构了。

注意 在软件开发过程中,如果相同的一段代码拷贝过两次,就需要对设计产生怀疑,
架构师要明确的说明为什么相同的逻辑要出现两次或更多次。

class Car
{
public:
    // 汽车启动
   virtual void start() = 0;
   // 汽车停止
   virtual void stop() = 0;
   // 汽车喇叭
   virtual void alarm() = 0;

   void run() 
   {
       start();

       alarm();

       stop();
   }
};

class BMW : public Car
{
public:
    void start()
    {
        cout << "宝马车启动了..." << endl;
    }
    // 汽车停止
    void stop()
    {
        cout << "宝马停止了" << endl;
    }
    // 汽车喇叭
    void alarm()
    {
        cout << "宝马鸣笛,屌丝让道" << endl;
    }
};

class Alto : public Car
{
public:
    void start()
    {
        cout << "二手破烂Alto启动好久终于动了..." << endl;
    }
    // 汽车停止
    void stop()
    {
        cout << "Alto靠脚刹停止了" << endl;
    }
    // 汽车喇叭
    void alarm()
    {
        cout << "Alto鸣笛,发现喇叭坏了" << endl;
    }

};
// ... 各种汽车型号
class Benz : public Car 
{
    // ...功能类似
};

这样改了之后,代码确实能够重用。但是如果现在要生产一种汽车,这种汽车启动时不需要
鸣笛的(奇怪,竟然有这么奇怪的要求。难道做的是遥控车?),面对这种需求我们该怎么
处理呢?

class Car
{
public:
    // 汽车启动
   virtual void start() = 0;
   // 汽车停止
   virtual void stop() = 0;
   // 汽车喇叭
   virtual void alarm() = 0;

   virtual bool isAlarm() 
   {
       return true;
   };
   void run() 
   {
       start();

       if(isAlarm()){
            alarm();
       }

       stop();
   }
};

class Alto : public Car
{
public:
    void start()
    {
        cout << "二手破烂Alto启动好久终于动了..." << endl;
    }
    // 汽车停止
    void stop()
    {
        cout << "Alto靠脚刹停止了" << endl;
    }
    // 汽车喇叭
    void alarm()
    {
        cout << "Alto鸣笛,发现喇叭坏了" << endl;
    }

    bool isAlarm() { return false; }
};

posted @ 2017-07-26 14:21  龙猫不是猫  阅读(194)  评论(0)    收藏  举报