zoukankan      html  css  js  c++  java
  • 装饰者模式和观察者模式

    一、装饰者模式

    1、装饰者模式(Decorator Pattern):指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能)。(属于结构型模式)

    2、适用场景

    • 用于扩展一个类的功能或给一个类增加附加职责
    • 动态的给一个对象添加功能,这些功能可以再动态的撤销

    3、优点

    • 装饰者是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用
    • 通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果
    • 装饰者完全遵循开闭原则

    4、缺点

    • 会出现更多的代码、更多的类,增加程序复杂性
    • 动态装饰时,多层装饰时会更复杂

    5、应用场景举例

    例子1:早上买个煎饼去公司吃,卖煎饼的大姐可以给你的煎饼加鸡蛋、也可以加热狗等。

    定义一个煎饼Cake类:

    定义一个加鸡蛋的煎饼CakeWithEgg类:

    再定义一个既加鸡蛋又加热狗的煎饼CakeWithEggAndHotdog类:

    客户端测试代码:

     

    运行结果:

    类结构图:

    运行结果没有问题。但如果用户需要一个加2个鸡蛋、加1根热狗的煎饼,那么用现在的类结构是创建不出来的,也无法自动计算出价格,除非再创建一个类做定制,如果需求再变,一直加定制显然是不科学的。下面用装饰者模式来解决上面的问题。

    首先定义一个制作煎饼的抽象类Cake:

    定义一个基本的煎饼(基础套餐)BaseCake类:

    定义一个扩展套餐的抽象装饰者CakeDecorator类:

    定义一个鸡蛋装饰者EggDecorator类:

    定义一个热狗装饰者HotdogDecorator类:

    客户端测试代码:

    运行结果:

    类结构图:

    例子2:上次讲的适配器模式,为了实现新功能与老功能兼容,定义一个新的类继承已有的类来实现功能扩展,遵循开闭原则。今天再用装饰者模式再升级一次代码,同时也做一个更好的对比。

    先看原来的代码,User类:

    Result类:

    ISignInService接口:

    SignInServiceImpl实现类:

    来看升级以后的代码,定义一个新的接口ISignInForThirdService继承原来的接口:

    定义一个新的逻辑处理类SignInForThirdServiceImpl,实现第三方登录自由适配:

    客户端测试代码:

    装饰者模式最本质的特征是将原有类的附加功能抽离出来,简化原有类的逻辑。其实抽象的装饰者是可有可无的,具体可以根据业务模型来选择。

    6、装饰者模式和适配器模式的对比

    装饰者和适配器模式都是包装模式(Wrapper Pattern),装饰者也是一种特殊的代理模式。

    7、装饰者模式在源码中的应用

    ① 在JDK中体现最明显的类就是IO相关的类,如BufferedReader、InputStream、OutputStream,看一下常用的InputStream类结构图:

    ② 在Spring中的TransactionAwareCacheDecorator类也有用到,该类主要是用来处理事务缓存相关,如下代码:

    ③ TransactionAwareCacheDecorator就是对Cache的一个包装。再如MVC中的装饰者模式HttpHeadResponseDecorator类:

    二、观察者模式

    1、观察者模式(Observer Pattern):指定义了对象之间的一对多依赖,让多个观察者对象同时监听一个主体对象,当主体对象发生变化时,它的所有依赖者(观察者)都会收到通知并更新。(属于行为型模式,观察者模式有时也叫做发布订阅模式)

    2、优点

    • 观察者和被观察者之间建立了一个抽象的耦合
    • 观察者模式支持广播通信

    3、缺点

    • 观察者之间有过多的细节依赖、提高时间消耗及程序的复杂度
    • 使用要得当,要避免循环调用 

    4、应用场景举例

    观察者模式主要用于在关联行为之间建立一套触发机制的场景。比如微信朋友圈动态通知、群消息通知、邮件通知、广播通知、桌面程序的事件响应等。如下:

    例子:生产者与消费者模型。使用JDK提供的一种观察者的实现方式来实现。

    先定义一个消息Message类:

    定义一个生产者Productor类:

    定义一个消费者Consumer类:

    客户端测试代码:

    运行结果:

    5、基于Guava API轻松落地观察者模式

    先引入Guava框架的Maven依赖包:

    定义一个监听事件GuavaEvent类:

    客户端测试代码:

    运行结果:

  • 相关阅读:
    sniffer 和 debug flow
    如何认识TOS----DSCP 对照表
    NAT alg 和 ASPF
    使用refind引导多系统
    Backdooring a OS VM
    exit(0)与exit(1),return三者区别(详解)
    Codeforces Round #301 (Div. 2)(A,【模拟】B,【贪心构造】C,【DFS】)
    2017年中国大学生程序设计竞赛-中南地区赛暨第八届湘潭市大学生计算机程序设计大赛题解&源码(A.高斯消元,D,模拟,E,前缀和,F,LCS,H,Prim算法,I,胡搞,J,树状数组)
    高斯消元法(Gauss Elimination)【超详解&模板】
    2015 计蒜之道 初赛(4)爱奇艺的自制节目(枚举 贪心)
  • 原文地址:https://www.cnblogs.com/ZekiChen/p/12588893.html
Copyright © 2011-2022 走看看