设计模式(四)--结构类模式

1.设计之禅:第10章 模板方法模式 · 设计模式之禅(第2版) · 看云

2.本文引用博客:https://blog.csdn.net/zhengzhb/article/category/926691

3.图解设计模式;结构型模式 — Graphic Design Patterns

1.总结

结构类模式包括适配器模式、桥梁模式、组合模式、装饰模式、门面模式、享元模式和代理模式。为什么叫结构类模式呢?因为它们都是通过组合类或对象产生更大结构以适应更高层次的逻辑需求。
结构型模式的实现上基本上遵循优先使用对象组合,而不是类继承原则
对比装饰模式就是代理模式的一个特殊应用,不同点则是代理模式着重对代理过程的控制,而装饰模式则是对类的功能进行加强或减弱,它着重类的功能变化,代理的一个功能:在不改变接口的前提下,对过程进行控制,装饰模式是在要保证接口不变的情况下加强类的功能,它保证的是被修饰的对象功能比原始对象丰富(当然,也可以减弱)
装饰模式包装的是自己的兄弟类,隶属于同一个家族(相同接口或父类),适配器模式则修饰非血缘关系类,把一个非本家族的对象伪装成本家族的对象,注意是伪装,因此它的本质还是非相同接口的对象。

适配器模式:消除由于接口不匹配所造成的类的兼容性问题
桥接模式:分离接口(抽象)与其实现,当某个类型具有两个或两个以上的纬度变化(或者说是变化点),通过以继承接口的方式隔离变化,以减少因变化带来的代码的修改量。
装饰模式:在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
享元模式:主要是解决由于相同对象数量过大而造成系统内存开销过大的问题。实际上是相同的对象引用指向同一个对象空间
代理模式:解决直接访问某些对象是出现的问题
组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
门面(外观模式):为了解决类与类之间的依赖关系的,将他们的关系放在一个Facade类中,降低了类类之间的耦合度,该模式中没有涉及到接口

2.代理模式

定义:为其他对象提供一种代理以控制对这个对象的访问
扩展

  • 普通模式:客户端只能访问代理角色,而不能访问真实角色:代理类里调用方法
  • 强制代理:有通过真实角色指定的代理类才可以访问,也就是说由真实角色管理代理角色:必须用代理。getPorxy()
  • 定制代理:代理多继承一个代理类。
  • 动态代理:AOP(Aspect Oriented Programming)两条独立发展的线路,不改变我们已有代码结构的情况下增强或控制对象的行为。没有创建代理类,也没有实现IGamePlayer接口,这就是动态代理,看消息的传递:client->DynamicProxy ->Handler->subject

3.适配器模式

定义:将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作
例子:实际系统中只是增加了一个业务类的继承,就实现了可以查本公司的员工信息,也可以查人力资源公司的员工信息,尽量少的修改,通过扩展的方式解决了该问题;ABC拼图关系。
做法:通过继承或是类关联的方式。补救”模式,通常用来解决接口不相容的问题,

 4.桥接模式

定义:抽象和实现解耦,使得两者可以独立地变化
例子:集团增加工厂。类的继承有N层时,可以考虑使用桥梁模式
组成

  • 抽象化角色,修正抽象化角色,实现化角色,具体实现化角色

5.组合模式

定义:来描述部分与整体的关系
组成

  • Component抽象构件角色, 定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性
  • 树枝对象,它的作用是组合树枝节点和叶子节点形成一个树形结构。
  • Leaf叶子构件:叶子对象,其下再也没有其他的分支,也就是遍历的最小单位。

使用:只要是树形结构,就要考虑使用组合模式,这个一定要记住,只要是要体现局部和整体的关系的时候,而且这种关系还可能比较深,考虑一下组合模式吧,上下结构,上面放系统的Logo,下边分为两部分:左边是导航菜单,右边是展示区,左边的导航菜单一般都是树形的结构

6.装饰模式

定义:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
组成:Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象,如上面的成绩单;ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是它。Decorator装饰角色,在它的属性里必然有一个private变量指向Component抽象构件;你要把你最核心的、最原始的、最基本的东西装饰成其他东西,上面的例子就是把一个比较平庸的成绩单装饰成家长认可的成绩单
使用:装饰模式可以替代继承,解决我们类膨胀的问题
写一个类当装饰器,用来替换新加的逻辑。

class Phone
{
public:
    virtual void call();
};

// 电话前听彩铃
class musicPhone : public Phone
{
private:
    /* data */
public:
    virtual void call()
    {
        listenMusic();
        Phone::call();
    }
};

// 电话前听彩铃
class showTimePhone : public Phone
{
private:
    /* data */
public:
    virtual void call()
    {
        Phone::call();
        showCallTime();
    }
};
class Phone
{
public:
    virtual void call() = 0;
};

class IPhoneX : public Phone
{
public:
    virtual void call()
    {
        std::cout << "call" << std::endl;
    }
};

class PhoneDecorate : public Phone
{
private:
    Phone mPhone;

public:
    void PhoneDecorate(Phone phone)
    {
        mPhone = phone;
    }

    virtual void call()
    {
        mPhone.call();
    }
};

class MusicPhoneDecorate : public PhoneDecorate
{
private:
    /* data */
public:
    MusicPhoneDecorate(Phone p)
        : PhoneDecorate(p)
    {
    }
    void listenMusic()
    {
    }
    virtual void call()
    {
        listenMusic();
        PhoneDecorate::call();
    }
};

class TimerPhoneDecorate : public PhoneDecorate
{
private:
    /* data */
public:
    TimerPhoneDecorate(Phone p)
        : PhoneDecorate(p)
    {
    }
    void listenMusic()
    {
    }
    virtual void call()
    {
        listenMusic();
        PhoneDecorate::call();
    }
};

int main ()
{
    Phone p = new IPhoneX();
    // 顺序可以改变,实现不同功能
    p = new MusicPhoneDecorate(p);
    p = new TimerPhoneDecorate(p);

    p.call();
    return 0;
}

7.门面模式: 

定义:不改变子系统对外暴露的接口、方法,只改变内部的处理逻辑,其他兄弟模块的调用产生了不同的结果,要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用;门面对象是外界访问子系统内部的唯一通道
要素:

  • Facade门面角色:客户端可以调用这个角色的方法。此角色知晓子系统的所有功能和责任。一般情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去,也就说该角色没有实际的业务逻辑,只是一个委托类。
  • subsystem子系统角色: 可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。子系统并不知道门面的存在。对于子系统而言,门面仅仅是另外一个客户端而已。

优点:外界访问直接深入到子系统内部,相互之间是一种强耦合关系

8.享元模式

定义:使用共享对象可有效地支持大量的细粒度的对象,享元对象之所以能做到共享,关键是区分了内部状态和外部状态
要素

  • Flyweight——抽象享元角色:它简单地说就是一个产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现。
  • ConcreteFlyweight——具体享元角色:具体的一个产品类,实现抽象角色定义的业务。该角色中需要注意的是内部状态处理应该与环境无关,不应该出现一个操作改变了内部状态,同时修改了外部状态,这是绝对不允许的。
  • unsharedConcreteFlyweight——不可共享的享元角色:不存在外部状态或者安全要求(如线程安全)不能够使用共享技术的对象,该对象一般不会出现在享元工厂中。
  • FlyweightFactory——享元工厂:职责非常简单,就是构造一个池容器,同时提供从池中获得对象的方法。

场景

  • 系统中存在大量的相似对象。
  • 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份。
  • 需要缓冲池的场景。

例子: n 个玩 CS 的玩家,如果创建 n 个对象(每个玩家一个),这势必会占用大量内存C++ 享元模式_青春不老,奋斗不止!-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值