快速入门设计模式Ⅱ—策略,代理,责任链,装饰器,工厂模式

策略模式

  • 定义
    定义⼀系列算法,把它们⼀个个封装起来,并且使它们可互相替换。该模式使得算法可独⽴于使⽤
    它的客户程序⽽变化。
  • 要点
    • 策略模式提供了⼀系列可重⽤的算法,从⽽可以使得类型在运⾏时⽅便地根据需要在各个算法
      之间进⾏切换;
    • 策略模式消除了条件判断语句;就是在解耦合;
    • 充分体现了开闭原则,单⼀职责;
  • 本质
    分离算法,选择实现;
  • 例子
    某商场节假⽇有固定促销活动,为了加⼤促销⼒度,现提升节日促销活动规格;
  • 代码
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_XXXXX : 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_Spring ();
    Promotion *p = new Promotion(s);
    p->CalcPromotion(ctx);
    return 0;
}

责任链模式

  • 定义
    使多个对象都有机会处理请求,从⽽避免请求的发送者和接收者之间的耦合关系。将这些对象连成
    ⼀条链,并沿着这条链传递请求,直到有⼀个对象处理它为⽌。

  • 要点

    • 解耦请求⽅和处理⽅,请求⽅不知道请求是如何被处理,处理⽅的组成是由相互独⽴的⼦处理
      构成,⼦处理流程通过链表的⽅式连接,⼦处理请求可以按任意顺序组合;
    • 责任链请求强调请求最终由⼀个⼦处理流程处理;通过了各个⼦处理条件判断;
    • 责任链扩展就是功能链,功能链强调的是,⼀个请求依次经由功能链中的⼦处理流程处理;
    • 充分体现了单⼀职责原则;将职责以及职责顺序运⾏进⾏抽象,那么职责变化可以任意扩展,
      同时职责顺序也可以任意扩展;
  • 本质
    分离职责,动态组合;

  • 例子
    请假流程,1天内需要主程序批准,3天内需要项⽬经理批准,3天以上需要⽼板批准;

  • 代码

#include <string>

class Context {
public:
    std::string name;
    int day;
};


class IHandler {
public:
    virtual ~IHandler() {}
    void SetNextHandler(IHandler *next) {
        next = next;
    }
    bool Handle(ctx) {
        if (CanHandle(ctx)) {//如果可以处理本请求
            return HandleRequest();//进行处理
        } else if (GetNextHandler()) {//否则交给下一个handler处理
            return GetNextHandler()->HandleRequest(ctx);
        } else {
            // err
        }
    }
protected:
    virtual bool HandleRequest(const Context &ctx) = 0;
    virtual bool CanHandle(const Context &ctx) =0;
    IHandler * GetNextHandler() {
        return next;
    }
private:
    IHandler *next;
};
//主程
class HandleByMainProgram : public IHandler {
protected:
    virtual bool HandleRequest(const Context &ctx){
        //
    }
    virtual bool CanHandle() {
        //
    }
};
//PM
class HandleByProjMgr : public IHandler {
protected:
    virtual bool HandleRequest(const Context &ctx){
        //
    }
    virtual bool CanHandle() {
        //
    }
};
//BOSS
class HandleByBoss : public IHandler {
public:
    virtual bool HandleRequest(const Context &ctx){
        //
    }
protected:
    virtual bool CanHandle() {
        //
    }
};

int main () {
    IHandler * h1 = new MainProgram();
    IHandler * h2 = new HandleByProjMgr();
    IHandler * h3 = new HandleByBoss();
    h1->SetNextHandler(h2);
	h2->SetNextHandler(h3)
    Context ctx;
    h1->handle(ctx);
    return 0;
}

装饰器模式

  • 定义
    动态地给⼀个对象增加⼀些额外的职责。就增加功能⽽⾔,装饰器模式⽐⽣成⼦类更为灵活。

  • 要点

    • 通过采⽤组合⽽⾮继承的⼿法, 装饰器模式实现了在运⾏时动态扩展对象功能的能⼒,⽽且
      可以根据需要扩展多个功能。 避免了使⽤继承带来的“灵活性差”和“多⼦类衍⽣问题”。
    • 不是解决“多⼦类衍⽣的多继承”问题,⽽是解决“⽗类在多个⽅向上的扩展功能”问题;
    • 装饰器模式把⼀系列复杂的功能分散到每个装饰器当中,⼀般⼀个装饰器只实现⼀个功能,实
      现复⽤装饰器的功能;
  • 本质
    动态组合

  • 例子
    普通员⼯有销售奖⾦,累计奖⾦,部⻔经理除此之外还有团队奖⾦;后⾯可能会添加环⽐增⻓奖
    ⾦,同时可能针对不同的职位产⽣不同的奖⾦组合;
    在这里插入图片描述

  • 代码

// 普通员工有销售奖金,累计奖金,部门经理除此之外还有团队奖金;后面可能会添加环比增长奖金,同时可能产生不同的奖金组合;
// 销售奖金 = 当月销售额 * 4%
// 累计奖金 = 总的回款额 * 0.2%
// 部门奖金 = 团队销售额 * 1%
// 环比奖金 = (当月销售额-上月销售额) * 1%
// 销售后面的参数可能会调整
class Context {
public:
    bool isMgr;
    // User user;
    // double groupsale;
};

// 试着从职责出发,将职责抽象出来
class CalcBonus {    
public:
    CalcBonus(CalcBonus * c = nullptr) {}
    virtual double Calc(Context &ctx) {
        return 0.0; // 基本工资
    }
    virtual ~CalcBonus() {}

protected:
    CalcBonus* cc;
};

class CalcMonthBonus : public CalcBonus {
public:
    CalcMonthBonus(CalcBonus * c) : cc(c) {}
    virtual double Calc(Context &ctx) {
        double mbonus /*= 计算流程忽略*/; 
        return mbonus + cc->Calc(ctx);
    }
};

class CalcSumBonus : public CalcBonus {
public:
    CalcSumBonus(CalcBonus * c) : cc(c) {}
    virtual double Calc(Context &ctx) {
        double sbonus /*= 计算流程忽略*/; 
        return sbonus + cc->Calc(ctx);
    }
};

class CalcGroupBonus : public CalcBonus {
public:
    CalcGroupBonus(CalcBonus * c) : cc(c) {}
    virtual double Calc(Context &ctx) {
        double gbnonus /*= 计算流程忽略*/; 
        return gbnonus + cc->Calc(ctx);
    }
};

class CalcCycleBonus : public CalcBonus {
public:
    CalcGroupBonus(CalcBonus * c) : cc(c) {}
    virtual double Calc(Context &ctx) {
        double gbnonus /*= 计算流程忽略*/; 
        return gbnonus + cc->Calc(ctx);
    }
};

int main() {
    // 1. 普通员工
    Context ctx1;
    CalcBonus *base = new CalcBonus();//基础奖金
    CalcBonus *cb1 = new CalcMonthBonus(base);//月度奖金
    CalcBonus *cb2 = new CalcSumBonus(cb1);//累计奖金
    cb2->Calc(ctx1); //基础 + 月度 + 累计
    // 2. 部门经理
    Context ctx2;
    CalcBonus *cb3 = new CalcGroupBonus(cb2);
    cb3->Calc(ctx2);
}

工厂模式

  • 定义
    定义⼀个⽤于创建对象的接⼝,让⼦类决定实例化哪⼀个类。Factory Method使得⼀个类的实例化
    延迟到⼦类。
  • 要点
    • 解决创建过程⽐较复杂,希望对外隐藏这些细节;
      • ⽐如连接池,线程池;
      • 隐藏对象真实类型;
      • 对象创建会有很多参数来决定如何创建;
      • 创建对象有复杂的依赖关系;
  • 本质
    延迟到⼦类来选择实现;
  • 例子
    实现⼀个导出数据的接⼝,让客户选择数据的导出⽅式;
  • 代码
#include <string>
// 实现导出数据的接口, 导出数据的格式包含 xml,json,文本格式txt 后面可能扩展excel格式csv
class IExport {
public:
    virtual bool Export(const std::string &data) = 0;
    virtual ~IExport(){}
};

class ExportXml : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportJson : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportTxt : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportCSV : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class IExportFactory {
public:
    IExportFactory() {
        _export = nullptr;
    }
    virtual ~IExportFactory() {
        if (_export) {
            delete _export;
            _export = nullptr;
        }
    }
    bool Export(const std::string &data) {
        if (_export == nullptr) {
            _export = NewExport();
        }
        return _export->Export(data);
    }
protected:
    virtual IExport * NewExport(/* ... */) = 0;
private:
    IExport* _export;
};

class ExportXmlFactory : public IExportFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportXml();
        // 可能之后有什么操作
        return temp;
    }
};
class ExportJsonFactory : public IExportFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportJson;
        // 可能之后有什么操作
        return temp;
    }
};
class ExportTxtFactory : public IExportFactory {
protected:
    IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportTxt;
        // 可能之后有什么操作
        return temp;
    }
};

class ExportCSVFactory : public IExportFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportCSV;
        // 可能之后有什么操作
        return temp;
    }
};

int main () {
    IExportFactory *factory = new ExportTxtFactory();
    factory->Export("hello world");
    return 0;
}

抽象工厂模式

  • 定义
    提供⼀个接⼝,让该接⼝负责创建⼀系列“相关或者相互依赖的对象”,⽆需指定它们具体的类。

  • 例子
    实现⼀个拥有导出导⼊数据的接⼝,让客户选择数据的导出导⼊⽅式;

  • 代码(只不过是把api封装在了一起而已,上面那个是只有导出操作,而这个支持导入导出等等)

#include <string>
// 实现导出数据的接口, 导出数据的格式包含 xml,json,文本格式txt 后面可能扩展excel格式csv
class IExport {
public:
    virtual bool Export(const std::string &data) = 0;
    virtual ~IExport(){}
};

class ExportXml : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportJson : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportTxt : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportCSV : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class IImport {
public:
    virtual bool Import(const std::string &data) = 0;
    virtual ~IImport(){}
};

class ImportXml : public IImport {
public:
    virtual bool Import(const std::string &data) {
        return true;
    }
};

class ImportJson : public IImport {
public:
    virtual bool Import(const std::string &data) {
        return true;
    }
};

class ImportTxt : public IImport {
public:
    virtual bool Import(const std::string &data) {
        return true;
    }
};

class ImportCSV : public IImport {
public:
    virtual bool Import(const std::string &data) {
        // ....
        return true;
    }
};

class IDataApiFactory {
public:
    IDataApiFactory() {
        _export = nullptr;
        _import = nullptr;
    }
    virtual ~IDataApiFactory() {
        if (_export) {
            delete _export;
            _export = nullptr;
        }
        if (_import) {
            delete _import;
            _import = nullptr;
        }
    }
    bool Export(const std::string &data) {
        if (_export == nullptr) {
            _export = NewExport();
        }
        return _export->Export(data);
    }
    bool Import(const std::string &data) {
        if (_import == nullptr) {
            _import = NewImport();
        }
        return _import->Import(data);
    }
protected:
    virtual IExport * NewExport(/* ... */) = 0;
    virtual IImport * NewImport(/* ... */) = 0;
private:
    IExport *_export;
    IImport *_import;
};

class XmlApiFactory : public IDataApiFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportXml;
        // 可能之后有什么操作
        return temp;
    }
    virtual IImport * NewImport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IImport * temp = new ImportXml;
        // 可能之后有什么操作
        return temp;
    }
};

class JsonApiFactory : public IDataApiFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportJson;
        // 可能之后有什么操作
        return temp;
    }
    virtual IImport * NewImport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IImport * temp = new ImportJson;
        // 可能之后有什么操作
        return temp;
    }
};
class TxtApiFactory : public IDataApiFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportTxt;
        // 可能之后有什么操作
        return temp;
    }
    virtual IImport * NewImport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IImport * temp = new ImportTxt;
        // 可能之后有什么操作
        return temp;
    }
};

class CSVApiFactory : public IDataApiFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportCSV;
        // 可能之后有什么操作
        return temp;
    }
    virtual IImport * NewImport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IImport * temp = new ImportCSV;
        // 可能之后有什么操作
        return temp;
    }
};

int main () {
    IDataApiFactory *factory = new CSVApiFactory();
    factory->Import("hello world");
    factory->Export("hello world");
    return 0;
}

代理模式

  • 定义
    为其他对象提供⼀种代理以控制对这对象的访问。
  • 应用
    • 远程代理(隐藏⼀个对象存在不同的地址空间的事实),虚代理(延迟加载lazyload),保护
      代理(在代理前后做额外操作,权限管理,引⽤计数等);
    • 在分布式系统中,actor模型(skynet)等常⽤的设计模式;
  • 本质
    控制对象访问;
  • 例子
    在有些系统中,为了某些对象的纯粹性,只进⾏了功能相关封装(稳定点),后期添加了其他功能
    需要对该对象进⾏额外操作(变化点),为了隔离变化点(也就是不直接在稳定点进⾏修改,这样
    会让稳定点也变得不稳定),可以抽象⼀层代理层;
  • 代码

class ISubject {
public:
    virtual void Handle() = 0;
    virtual ~ISubject() {}
};

// 该类在当前进程,也可能在其他进程当中
class RealSubject : public ISubject {
public:
    virtual void Handle() {
        // 只完成功能相关的操作,不做其他模块的判断
    }
};

// 在当前进程当中  只会在某个模块中使用
class Proxy1 : public ISubject {
public:
    Proxy1(ISubject *subject) : _subject(subject) {}
    virtual void Handle() {
        // 在访问 RealSubject 之前做一些处理
        //if (不满足条件)
        //    return;
        _subject->Handle();
        count++;
        // 在访问 RealSubject 之后做一些处理
    }
private:
    ISubject* _subject;
    static int count;
};
int Proxy1::count = 0;

// 在分布式系统当中  skynet actor
class Proxy2 : public ISubject {
public:
    virtual void Handle() {
        // 在访问 RealSubject 之前做一些处理
        
        // 发送到数据到远端  网络处理  
        //IResult * val = rpc->call("RealSubject", "Handle");

        // 在访问 RealSubject 之后做一些处理
    }
private:
    /*void callback(IResult * val) {
        // 在访问 RealSubject 之后做一些处理
    }*/
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值