设计模式的作用:

        在实际开发过程中,会遇到很多各种各样的问题。需要用某些特定的套路去解决一类问题。保证代码的稳定。同时可以避免重复的工作。个人认为,类似于盖房子的设计图。

一、模版方法:

        使用场景:某个品牌动物园,有一套固定流程,但是其中有若干个表演子流程可以创新替换,以尝试迭代更新表演流程。

要点:

        1.最常用的设计模式,子类可以复写父类子流程,是父类骨架流程丰富。

        2.反向控制流程的典型应用

        3.父类proted保护子类需要复写的子流程,这样子类的子流程只能父类来调用。

本质:通过固定算法框架来约束子类的行为。

 说人话:

        父类把框架定好。在内部用protected关键字和虚函数来定义一个功能,也就是表演节目。但是不写具体表演什么。protected保证只有子类能复写,并且只能由父类来调用。虚函数保证了子类能重载该函数。

        然后用子类继承父类。通过重载的方式把父类当中的虚函数做出具体的实现。就是爹说表演节目,儿子知道了以后,由儿子自己具体确定表演什么节目。其他儿子都通过继承加重载的方式来确定各自都要表演什么节目。这样弄后,父类就不需要改变了,让儿子改变就行。

        每个儿子都写好后,通过父类指针,指向子类对象,就可以调用各个儿子准备的节目了。如果有新儿子表演新节目,直接继续创建儿子类,重载爹定下的表演节目即可。再创建爹指针,指向新儿子对象。

二、观察者模式

        一对多,一变化,多也要变化。

场景举例:气象站发数据给数据中心,数据中心经过处理,将气象信息更新到多个不同的显示终端。

要点:

        1.观察者模式使得我们可以独立地改变目标与观察者,从而使二者之间的关系送耦合。

        2.观察者自己巨鼎是否订阅通知,目标对象并不关注有谁订阅。

        3.观察者不要依赖通知顺序,目标对象也不知道通知顺序。

        4。常用在基于事件的ui框架中,也是mvc的组成部分。

        5.常用在分布式系统中、actor框架中。

代码:

        

#include <vector>

一如vector容器,用来存储所有终端。

//
class IDisplay {

        定义出终端类,只定义显示功能(虚函数),不写具体的实现,由子类,也就是各种终端设备来实现。
public:
    virtual void Show(float temperature) = 0;
    virtual ~IDisplay() {}
};

定义子类终端A。负责自身功能的具体实现

class DisplayA : public IDisplay {
public:
    virtual void Show(float temperature);
private:
    void jianyi();
};

终端B

class DisplayB : public IDisplay{
public:
    virtual void Show(float temperature);
};

终端C

class DisplayC : public IDisplay{
public:
    virtual void Show(float temperature);
};

气象中心

class WeatherData {
};



数据中心

class DataCenter {
public:

定义出添加和删除终端的功能。public,用户可以使用这两个功能来添加活删除终端。
    void Attach(IDisplay * ob);
    void Detach(IDisplay * ob);

     定义出显示功能。把所有添加的终端设备都加入到vector容器里面。当用户调用notify时,notify调用CalcTemperature();函数。从气象中心得到数据,计算数据并返回。然后依次把vector容器里的所有终端的show功能全部调用,把计算的数据(temper)输入进去。
    void Notify() {
        float temper = CalcTemperature();
        for (auto iter = obs.begin(); iter != obs.end(); iter++) {
            (*iter)->Show(temper);
        }
    }

// 接口隔离

从气象中心得到数据,然后计算数据。并且定义出vector容器
private:
    virtual WeatherData * GetWeatherData();

    virtual float CalcTemperature() {
        WeatherData * data = GetWeatherData();
        // ...
        float temper/* = */;
        return temper;
    }
    std::vector<IDisplay*> obs;
};

int main() {

        创建数据中心。
    DataCenter *center = new DataCenter;

        创建终端A,b、c,用父类指针指向子类对象。
    IDisplay *da = new DisplayA();
    IDisplay *db = new DisplayB();
    IDisplay *dc = new DisplayC();

abc加入数据中心
    center->Attach(da);
    center->Attach(db);
    center->Attach(dc);


    数据中心调用notify函数,把气象数据输入vector容器里的每个终端中。
    center->Notify();
    
    //-----

        移除终端b
    center->Detach(db);

在调用notify函数,此时终端b已经不存在。
    center->Notify();
    return 0;
}

三、策略模式

 定义: 定义一系列算法,把它们封装起来,并且使它们可以互相替换。该模式使得算法独立于使用它的客户程序而变化。

背景:某商场节假日有固定促销活动,加大了促销力度,现在提升国庆节促销活动规格。

要点:

        1.策略模式提供了一些列可重用的算法,从而使得类型在运行时方便地根据需要在各个算法之间进行切换。

        2.策略模式消除了条件判断语句,也就是在解耦合

代码:

     

   学会运用抽象 活动---活动策略----具体活动

定义出具体活动

class Context {

};

活动策略。可以把具体活动传进来。

class ProStategy {
public:
    virtual double CalcPro(const Context &ctx) = 0;
    virtual ~ProStategy(); 
};


// cpp
class VAC_Spring : public ProStategy {
public:
    virtual double CalcPro(const Context &ctx){}
};
// cpp
class VAC_QiXi : public ProStategy {
public:
    virtual double CalcPro(const Context &ctx){}
};
class VAC_QiXi1  : public VAC_QiXi {
public:
    virtual double CalcPro(const Context &ctx){}
};



各种定义出各种节假日的活动,继承活动策略,各自重载具体的打折策略
// cpp
class VAC_Wuyi : public ProStategy {
public:
    virtual double CalcPro(const Context &ctx){}
};
// cpp
class VAC_GuoQing : public ProStategy {
public:
    virtual double CalcPro(const Context &ctx){}
};

class VAC_Shengdan : public ProStategy {
public:
    virtual double CalcPro(const Context &ctx){}
};

活动类

把活动策略传进来,活动策略内部绑定着具体活动。

class Promotion {
public:
    Promotion(ProStategy *sss) : s(sss){}
    ~Promotion(){}
    double CalcPromotion(const Context &ctx){

(核心)*******活动调用活动策略,活动策略调用具体折扣。实现活动与折扣的分离******
        return s->CalcPro(ctx);
    }
private:
    ProStategy *s; 定义出活动策略指针
};

int main () {

创建折扣
    Context ctx;

活动策略指向具体活动
    ProStategy *s = new VAC_QiXi1();

活动指向活动策略
    Promotion *p = new Promotion(s);

把折扣传入活动,活动调用相应的活动策略,活动策略调用具体折扣
    p->CalcPromotion(ctx);
    return 0;
}



身为新手,不能机械性的记忆这些知识。应该了解一个大概,混个脸熟。然后在后面真的开发项目时使用这些设计模式,逐渐掌握。用的多了才能真正理解这些模式。个人认为

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐