设计模式 - 结构型

结构型

适配器模式,代理模式,桥接模式,装饰器模式,外观模式,组合模式,享元模式,

单一职责避免子类爆炸
Bridge 模式对象的实现
Decorator 模式对对象的职责,不生成子类
接口隔离
Adapter 模式针对对象的接口
Facade 模式对一个子系统的接口
Proxy 模式如何访问一个对象;该对象的位置
数据结构
Composite 模式一个对象的结构和组成
对象性能
Flyweight 模式对象的存储开销

单一职责(避免子类爆炸)

subclass explode

Bridge 桥接模式
概念

桥接模式和装饰器模式一样,解决因为没有遵循单一职责原则而导致的子类数量爆炸。

  • 装饰器模式

    • 组合且继承

      子类可能会调用其他子类的实现。

  • 桥接模式

    • 组合而不继承。

      实现类 不会调用其他子类的实现

    • 实现类对应拆分前的子类,实际上由于没有继承,所以这里叫实现类更好。

  • 核心思想都是一样的,组合优于继承,单一职责。

具体来说:1+n+n*m 个子类,变为 1 纯虚 (+ 1通用实现)+ n iml实现类 + m个应用场景

  • 1 纯虚:接口
  • n 平台实现Imp
  • m 业务抽象(特定平台不同版本) (Imp平台实现作为参数 拼装)

业务抽象不需要继承接口或者平台实现,持有的基类的指针,运行时会指向iml平台实现(实现类)。

  • 桥接模式实现了抽象化与实现化的脱耦。他们两个互相独立,不会影响到对方。
  • 对于两个独立变化的维度,使用桥接模式再适合不过了。
  • 分离抽象接口及其实现部分。提高了比继承更好的解决方案
code

bridge.h

#include <cstdio>
#include <iostream>

class AbstractionImp {
public:
    virtual void Operation_RunPythonInTerminal() = 0;
};

// ConcreteAbstractionImp
class ConcreteAbstractionImp_Python2 : public AbstractionImp {
public:
    void Operation_RunPythonInTerminal() {
        printf("start python2 \n");
    }
};

class ConcreteAbstractionImp_Python3 : public AbstractionImp {
public:
    void Operation_RunPythonInTerminal() {
        printf("start python3 \n");
    }
};

bridge.cpp

#include "bridge_Imp.h"
// class AbstractionImp;

class Abstraction {
public:
    AbstractionImp* mImp = nullptr;
    virtual void Operation_RunPythonInTerminal() = 0;
};

class RefinedAbstraction_Windows : public Abstraction{
public:
    void Operation_RunPythonInTerminal() {
        printf("windows start WSL\n");
        if (mImp)
            mImp->Operation_RunPythonInTerminal();
    }
};

class RefinedAbstraction_Linux : public Abstraction{
public:
    void Operation_RunPythonInTerminal() {
        printf("linux start cmd\n");
        if (mImp)
            mImp->Operation_RunPythonInTerminal();
    }
};


int main() {
    Abstraction* mOS = new RefinedAbstraction_Windows;
    AbstractionImp* mPython = new ConcreteAbstractionImp_Python3;
    mOS->mImp = mPython;
    mOS->Operation_RunPythonInTerminal();
    free(mPython);
    mPython = new ConcreteAbstractionImp_Python2;
    mOS->mImp = mPython;
    mOS->Operation_RunPythonInTerminal();
    free(mPython);
    free(mOS);
    return 0;
}
Decorator 装饰器
概念

单一职责,避免了子类的无限制膨胀,消除重复代码,兼具开闭选择。

  • 特征

    • 子类继承基类

      多继承,多子类衍生 时的一个解决方法

    • 子类持有基类的指针。

      根据里氏替换,可以调用基类的同名方法,并在前后加上子类的操作。组合优于继承。

  • 应用于 主体类多个方向上的扩展功能

    • 主体操作和扩展操作,应该分开分支继承。

    • 扩展操作通过持有的主体操作的指针,造成附加动作之后 调用主体操作。

code
#include <cstdio>
#include <iostream>
#include <iostream>
#include <string>

class DecoratorBase {
public:
    DecoratorBase* mImp = nullptr;
    virtual void Operation() = 0;
};

class ImpParty : public DecoratorBase {
public:
    std::string bro = "";
    ImpParty(std::string bro) {
        this->bro = bro;
    }
    void setBro(std::string name) {
        this->bro = name;
    }
    void Operation() {
        printf("Party start, hi %s\n", bro.c_str());
        if (mImp) {
            printf("lets drink!\n");
            mImp->Operation();
        }
    }
};

class ImpSoftDrink : public DecoratorBase {
public:
    std::string softdrink = "";
    ImpSoftDrink(std::string softdrink) {
        this->softdrink = softdrink;
    }
    void Operation() {
        printf("lets drink %s", softdrink.c_str());
    }
};

int main() {
    ImpParty* mParty = new ImpParty("John");
    ImpSoftDrink* mDrink = new ImpSoftDrink("cola");
    mParty->mImp = mDrink;
    mParty->Operation();
    delete mDrink;
    delete mParty;
    return 0;
}

数据结构

composite 组合模式
概念

将对象组合成树状结构,树形结构不暴露给外界。

Compoment

树节点 composite 子类

  • 持有 一个子类的链表

  • add remove方法修改 其中的子类的链表

  • process方法,执行子类链表中所有子类的process函数。直到叶子节点

叶子节点 leaf 没有链表,process函数执行功能。

接口隔离

其它人的代码
Adoptor 适配器模式
概念

为了完成某项工作购买了一个第三方的库来加快开发。这就带来了一个问题:我们在应用程序中已经设计好了接口,与这个第三方提供的接口不一致,为了使得这些接口不兼容的类(不能在一起工作)可以在一起工作了,Adapter 模式提供了将一个类(第三方库)的接口转化希望的接口。

Itarget新实现的接口。adapter新实现。adaptee被适配的旧类

适配器模式分为类模式和对象模式。

  • 常用做法。对象模式:对象适配器 adapter,采用组合原有接口类的方式

    • 持有adaptee,组合用于实现。

    • public继承Itarget 接口。

  • 不常用做法。类模式:类适配器 adapter,采用继承原有接口类的方式

    • protect继承adaptee,用于实现。

    • public继承Itarget接口。(不灵活 继承的方案不灵活 类的多继承在cpp之外的语言压根就不支持)

code 继承
#include <cstdio>
class Target_rob {
public:
    virtual int giveMeYrMoney() = 0;
};

class Adaptee_robInFrance {
public:
    int doRob() {
        printf("Levez les mains, donnez moi votre argent!\n");
        return 1000;
    }
};

class Adaptor_rob : public Target_rob, Adaptee_robInFrance {
public:
    int giveMeYrMoney() {
        return doRob();
    }
};

int main() {
    Target_rob* mClinet = dynamic_cast<Target_rob*>(new Adaptor_rob());
    int money = mClinet->giveMeYrMoney();
    printf("we got %d RMB!", money);
}

code 组合
#include <cstdio>
#include <cstdlib>
class Adaptee_rob {
public:
    virtual int doRob() = 0;
};
class Adaptee_robInFrance : public Adaptee_rob {
public:
    int doRob() {
        printf("Levez les mains, donnez moi votre argent!\n");
        return 1000;
    }
};

class Target_rob {
public:
    Adaptee_rob* mAdaptee = nullptr;
    virtual int giveMeYrMoney() = 0;
};

class Adaptor_rob : public Target_rob {
public:

    int giveMeYrMoney() {
        int money = 0;
        if (mAdaptee) {
            money = mAdaptee->doRob();
        } else {
            printf("we got nothing \n");
        }
        return money;
    }
};

int main() {
    Target_rob* mClinet = dynamic_cast<Target_rob*>(new Adaptor_rob());
    Adaptee_rob* mRobber = dynamic_cast<Adaptee_rob*>(new Adaptee_robInFrance());
    mClinet->mAdaptee = mRobber;
    int money = mClinet->giveMeYrMoney();
    printf("we got %d RMB!", money);
    return 0;
}
facade 门面模式

facad 门面模式 解欧系统见的交互

框架层面,没有具体的实例代码。对内 高内聚 对外应该松耦合。

封装内部可能高度复杂 高度耦合的盒子。例如安卓的vendor hal。数据访问相关sql等等。

Proxy 代理模式

在不失去透明操作对象的同时,控制管理这些对象内部特有的复杂性

对其他对象特供一种代理,以控制 (隔离 使用接口)对这个接口的访问。

  • 对象创建开销大
  • 某些操作需要安全控制
  • 需要进程外的访问(分布式等)

对象性能

Flyweight 享元模式

内存池,每个字的字体,单例模式从容器中取出。

实现 右值引用 复制,clone原型模式

––– 接口隔离 –––

  • List item
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值