热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【设计模式之禅第2版】读书笔记

自己练习的源码地址:https:git.oschina.netsnnhooDesignPattern.git欢迎推送第一章单一职责原则简称SRP:SingleResponsibil

自己练习的源码地址:https://git.oschina.net/snnhoo/DesignPattern.git  欢迎推送

第一章 单一职责原则

  1. 简称SRPSingle Responsibility Principle
  2. 定义:应该有且仅有一个原因引起类的变更
  3. 好处:
    1. 类复杂度降低,职责明确
    2. 可读性高
    3. 可维护性高
    4. 变更引起风险低
  4. 接口设计要单一,实现要根据情况,方法也适用单一职责

第二章 里氏替换原则

  1. 定义:父类能出现的地方就能用子类,且不会产生任何异常,但是反过来则不行,有子类出现的地方,父类未必能适应。
  2. 在类中调用其它类时务必使用父类或接口,如果不能使用则说明类的设计违背了LSP原则。
  3. 如果子类不能完整实现父类方法,或某些方法发生“畸变”,则断开继承,采用依赖、聚集、组合。
  4. 采用里氏替换原则时,尽量避免子类的“个性”,如果用父类则抹杀子类个性,如果用子类则缺乏类替换标准。
  5. 子类必须实现父类所有方法,且是需要的。
  6. 子类可以有自己独特的方法。
  7. 子类方法中的参数要与父类同方法中参数相同或更宽松。
  8. 在重写情况下同一方法子类返回值类型要小于等于父类返回值类型。
  1. 里氏替换原则是开闭原则的具体实现之一。

第三章 依赖倒置原则

  1. DIPDependence Inversion Principle
  2. 定义:
    1. 高层不应该依赖低层模块,两者都应该依赖抽象(类间不发生直接依赖关系,其依赖通过接口或抽象类产生)
    2. 抽象不应该依赖细节(接口或抽象类不依赖于实现类)
    3. 细节应该依赖抽象(实现类应该依赖接口或抽象类)
  3. 优点:减少类间耦合性,提高系统稳定性,降低并行开发引起的风险(多人用接口同时开发,便于单元测试),提高可读性维护性。
  4. 最佳实践
    1. 每个类尽量都有抽象类或接口,或者同时都有
    2. 变量的表面类型最好是接口或抽象类
    3. 任何类都不应该从具体类派生
    4. 尽量不要覆写基类的方法
    5. 结合里氏替换:接口负责定义公共方法和属性,抽象类负责公共构造部分的实现
  5. 依赖正置:面向实现编程(类间依赖实现类)

第四章 接口隔离原则

  1. 定义:客户端不应该依赖它不需要的接口,类间的依赖关系应该建立在最小的接口上。
  2. 单一职责是要求类和接口职责单一,是从业务逻辑划分。接口隔离则要求方法要少,比如几个模块就应该有几个接口,而不是一个大接口。
    1. 比如说一个类不能有吃饭方法又有制造炸弹方法这是单一职责,比如一个类有读写2个方法,但有的类只能读,有的类只能写,这就要接口隔离。
  3. 规范约束:
    1. 接口尽量小,根据接口隔离原则拆分时,首先必须满足单一职责原则。
    2. 接口要高内聚,尽量少公布public方法。
    3. 定制服务,为特殊服务新开一个接口。
    4. 接口设计有限度的。
  4. 最佳实践
    1. 一个接口只服务于一个模块或业务逻辑;
    2. 通过业务逻辑压缩接口中的public方法;
    3. 已经被污染的接口,尽量去修改,如风险大,则采用适配器模式转化处理;
    4. 了解环境,拒绝盲从。

第五章 迪米特法则

  1. LoD:Law of Demeter,也称最少知识原则LKP。
  2. 定义:一个对象应该对其他对象有最少的了解。
  3. 对类的低耦合要求:
    1. 只和朋友交流,出现在成员变量、方法的输入输出参数中的类称为朋友类,方法体内的不算。类与类之间的关系是建立在类间的,而不是方法间,因此一个方法尽量不引入一个类中不存在的对象。
    2. 朋友间也是有距离的,一个类公开的public属性或方法越多,修改时涉及的面也就越大,变更引起的风险扩散也就越大。因此设计时需要反复衡量是否可以减少public方法或属性。
    3. 是自己的就是自己的,如果一个方法放在本类中,既不增加类间关系,也对本类不产生负面影响,那就放置在本类中。
    4. 谨慎使用Serializable

第六章 开闭原则

  1. 定义一个软件实体如类、模块、和函数应该对扩展开放,对修改关闭。
  2. 前面五个原则就是指导设计的工具和方法,而开闭原则才是其精神领袖。
  3. 重要性:
    1. 扩展操作,避免修改单元测试,及回归测试;
    2. 提高代码复用性,缩小逻辑粒度,直到一个逻辑不可再拆分为止;
    3. 提高可维护性;
    4. 面向对象开发的要求。
  4. 使用
    1. 抽象约束
      1. 通过接口或抽象类约束扩展,对扩展进行限定,不允许出现在接口或抽象类不存在的public方法;
      2. 参数类型、引用对象尽量使用接口或抽象类,而不是实现类;
      3. 抽象层尽量保持稳定,一旦确定不允许修改。
    2. 元数据控制模块行为,通过扩展一个子类,修改配置文件完成业务变化,如依赖注入;
    3. 制定项目章程;
    4. 封装变化,找出预计有变化或不稳定的点,为这些变化点创建稳定的接口
      1. 将相同变化封装到一个接口或抽象类中;
      2. 不应该有两个不同的变化出现在同一个接口或抽象类中;

第七章 单例模式

  1. 定义确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
  2. 优点:
    1. 单例模式在内存中只有一个实例,减少了内存开支,特别是一个频繁操作,性能又无法优化的对象。
    2. 减少性能开销,如读取配置、产生其他依赖对象时,启动一个对象,永久驻留内存。
    3. 可以避免一个对象的多重占用,例如一个写文件动作。
    4. 可以设置系统全局访问点,优化和共享资源访问。
  3. 缺点:
    1. 单例模式一般没有接口,无法扩展。
    2. 无法测试,如果代码未完成则无法测试,且因没有接口所以无法mock
    3. 单例模式与单一职责原则有冲突,类应只关心内部实现,而不关心外部如何调用。
  4. 使用场景:
    1. 要求生成唯一序列号的环境。
    2. 整个项目中需要一个共享访问点或共享数据,如页面访问计数器。
    3. 创建消耗资源过多的对象。
    4. 需要定义大量静态常量和静态方法的环境。
  5. 扩展:有上限的多例模式,可以定义内部列表存储实例,然后根据条件返回某实例。

技术分享

第八章 工厂方法模式

  1. 定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
  2. 在工厂方法模式中, 抽象产品类Product负责定义产品的共性, 实现对事物最抽象的定义; Creator为抽象创建类, 也就是抽象工厂, 具体如何创建产品类是由具体的实现工厂ConcreteCreator完成的。

 

  1. 技术分享
  2. 优点:
    1. 良好的封装性,代码接口清晰,调用者只需要知道产品约束字符串就可以。
    2. 扩展性高,增加产品时,只需要修改工厂类或扩展一个工厂类。
    3. 屏蔽产品类,例如切换数据库。
    4. 典型的解耦框架,只知道抽象类,符合迪米特法则;只依赖产品抽象,符合依赖倒置原则;使用子类替换父类,符合里氏替换原则。
  3. 应用场景:
    1. new一个对象的地方都可以使用,尤其是复杂对象时
    2. 需要灵活、可扩展框架时可使用,如邮件,支持POP3IMAPHTTP
    3. 可用在异构项目中。
    4. 测试驱动开发的框架下,模拟一个类。
  4. 扩展:
    1. 简单工厂模式:去掉继承抽象类,并在工厂创建对象方法前增加static关键字;
    2. 多工厂模式:每个产品对应一个创建工厂,好处是职责清洗符合单一职责原则,但不宜扩展和维护,一般新增一个协调类,来封装子工厂。
    3. 替代单例模式:工厂内设置静态对象。
    4. 延迟加载:保存特定对象在工厂,需要时直接返回,如数据库最大连接数对象。

第九章 抽象工厂模式

  1. 定义:为创建一组相关或相互依赖的对象提供一个接口,而且无须指定他们的具体类。在场景类中,没有任何一个方法与实现类有关系。
    1. 产品族:指由同一个工厂生产的,位于不同产品等级结构中的一组产品,例如不同品牌的电视机。
    2. 产品等级结构:产品的继承结构,如抽象类是电视机,其子类有海尔电视机、海信电视机。
  1. 技术分享
  1. N个产品族,在抽象工厂类中就应该有N个创建方法。
  2. M个产品等级就应该有M个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务。
  1. 优点:
    1. 封装性,每个产品的实现类不需要高层模块关心,只需关心接口抽象。
    2. 产品族内的约束为非公开状态,具体约束实在工厂内实现,高层无须关心。
  2. 缺点:产品族扩展非常困难,例如新增一个品牌产品,要在所有工厂方法中新增创建产品方法。
  3. 应用场景:一个对象族或是一组没有任何关系的对象都有相同的约束,则可以使用抽象工厂模式。在很多软件系统中需要更换界面主题,要求界面中的按钮、文本框、背景色等一起发生改变时,涉及不同操作系统,可以使用抽象工厂模式进行设计

10 模板方法模式

  1. 定义:定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
    1. 基本方法:就是基本操作,是有子类实现的方法,并且在模板方法中被调用。
    2. 模板方法:可以有一个或几个,实现对基本方法的调度,完成固定逻辑。
  2. 技术分享
  1. 技术分享
  1. 优点:
    1. 封装不变部分,扩展可变部分
    2. 提取公共部分代码,便于维护
    3. 行为有父类控制,子类实现
  2. 缺点:如果具体实现过多,需要开发人员话时间去理清关系。
  3. 应用场景:
    1. 多个子类有公有方法,并且逻辑基本相同
    2. 重要、复杂的算法,可以把核心算法设计为模板方法,周边则有子类实现
    3. .NET中重写控件事件就是模板方法模式
  4. 扩展:可以设置一个钩子方法,从而使子类控制流程走向。

11 建造者模式(创建型模式)

  1. 定义:也叫生成器模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示,如制造汽车需要发动机、轮胎。
  2. 技术分享
  3. 构成角色:
    1. Product产品类:通常是实现了模板方法模式,有模板方法和基本方法。
    2. Builder抽象建造者:规范产品的组建,一般是由子类实现。
    3. ConcreteBuilder具体建造者:实现抽象类定义的所有方法,并且返回一个组建好的对象。
    4. Director导演类:负责安排已有模块的顺序,然后告诉Builder开始建造。
  4. 优点:
    1. 封装性,客户端不用关心产品内部组成的细节。
    2. 建造者独立,容易扩展。
    3. 便于控制细节风险,因为建造者是独立的,因此可对建造过程细化。
  5. 应用场景:
    1. 相同方法,不同执行顺序,产生不同的事件结果。
    2. 多个部件,都可以装配到一个对象,但产生结果不同时。
    3. 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能。
  6. 建造者模式关注的是零件类型和装配顺序,这是与工厂方法模式的最大不同地方。

 

12 代理模式(结构型模式)

  1. 定义:为其他对象提供一种代理以控制这个对象的访问,并由代理对象控制对原对象的引用。
  2. 技术分享
  3. 优点:
    1. 职责清晰,降低耦合,真实角色只关心自己业务逻辑,不用关心相关但非本职的事务,都通过后期代理完成。
    2. 高扩展性,保护目标对象,真实角色可随时发生变化,但依赖接口,所以代理类可不做任何修改。
  4. 缺点:
    1. 造成请求速度变慢。
    2. 代理类需要额外工作,增加系统复杂度。
  5. 应用场景:
    1. 动态代理:AOP面向切面编程就是通过动态代理模式实现的。
    2. 远程代理:远程调用操作。
    3. 保护代理:保护一个对象的访问,可以给不同用户提供不同权限。
    4. 缓冲代理,为莫以目标操作的结果提供临时存储空间,多个客户端共享。
    5. 防火墙代理:保护目标不让恶意用户接近。
    6. 同步代理:同步化,使几个用户能同时使用一个对象而没有冲突。
    7. 智能引用代理,当一个对象被引用时,提供额外的操作。
    8. 虚拟代理,如果要创建一个资源消耗大的对象,可以先创建一个代理表示,等需要时才真正创建。

 

13 原型模式(结构型模式)

  1. 定义:用原型实例指定创建对象的种类(自身类型),并且通过拷贝这些原型创建新的对象。
  2. 技术分享
  3. 优点:
    1. 性能优良,是在内存中二进制流的拷贝,比直接new一个对象性能好很多。
    2. 逃避构造函数约束,这是优点也是缺点。
  4. 应用场景:
    1. 资源优化场景,如类初始化需要消化非常多的资源。
    2. 性能和安全要求的场景,通过new创建需要非常繁琐的数据准备或访问权限。
    3. 一个对象多个修改者的场景。
  5. 注意:原型模式,构造函数是不会执行的。

 

14 中介者模式(行为型模式)

  1. 定义:用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,起到中转和协调作用,从而使其耦合松散,而且可独立改变他们之间的交互。
  2. 技术分享
  3. 组成角色:
    1. Mediator抽象中介者角色,定义统一的接口,用于各同事角色之间的通信。
    2. Concrete Mediator具体中介者角色,通过协调各同事角色实现协作行为,必须依赖各个同事角色。
    3. Colleague同事角色,都知道中介者角色,通过中介者协作。
  4. 优点:减少类间依赖,把原本一对多的依赖变成一对一的依赖。
  5. 缺点:中介者会膨胀的很大,而且逻辑复杂,同事类越多,中介者就越复杂。
  6. 应用场景:类图中出现了蜘蛛网状接口,使用中介者模式变成星型结构。
    1. MVC框架,Controller就是一个中介者。
    2. 聊天室
  7. 最佳实践:
    1. N个对象之间产生了相互依赖关系。
    2. 多个对象有依赖关系,但是需求不确定,采用中介者模式,可降低变更引起的风险。

 

15 命令模式(行为型模式)

  1. 定义:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
  2. 技术分享
  3. 组成角色:
    1. Receive接收者角色,最终执行的方法。
    2. Command抽象命令角色,需要执行的所有命令都在这里生命。
    3. Invoker调用者角色,接收到命令,并执行命令。
    4. Client客户角色,发出一个具体的命令并确定其接受者。
    5. ConcreteCommand具体命令角色,定义一个接受者和行为的弱耦合,负责调用接受者相应方法。
  4. 优点:
    1. 新的命令可以很容易的加入到系统中。
    2. 类间解耦,调用者和接收者之间没有任何依赖关系,调用者只需要调用Command抽象类的execute方法就可以,不需要知道具体执行者。
    3. 可扩展性,Command的子类可以非常容易的扩展,高层不产生要种的代码耦合。
    4. 可以比较容易的设计一个命令队列和组合命令,命令模式可以结合责任链模式,实现命令族解析任务;可以结合模板方法模式,则可减少Command子类的膨胀问题。
  5. 缺点:如果有N个命令,则需要创建NCommand子类。
  6. 应用场景:
    1. 系统需要支持命令的撤销。
    2. 系统需要在不同的时间指定请求、将请求排队。
    3. 如果系统需要将所有操作记录日志,以便崩溃时从日志恢复。
    4. 如果需要执行回调。

 

16 责任链模式

  1. 定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,知道有对象处理它为止。
  2. 技术分享
  3. 涉及角色:
    1. Handler抽象处理者角色,定义一个处理请求的接口。
    2. ConcreteHandler具体处理者角色,具体处理者接受到请求后,可以选择处理,或传给下一个处理者。
  4. 抽象处理者二个职责:
    1. 定义一个请求的处理方法handleMessage,是唯一对外开放的方法;
    2. 定义一个链的编排属性setNext,设置下一个处理者;
  5. 具体处理者涉及两个类:Request类负责封装请求,Response负责封装链中返回的结果。
  6. 优点:将请求和处理分开,双方可互不相识,两者解耦,提高系统灵活性。
  7. 缺点:
    1. 性能问题,每个请求都是从链头遍历到链尾。
    2. 调试不方便,采用了类似递归的方式,调试的时候逻辑可能比较复杂。
  8. 应用场景:
    1. 一个系统的审批需要多个对象才能完成处理的情况下,例如请假系统。
    2. 代码中存在多个if-else语句的情况下,可以考虑使用责任链模式来对代码进行重构。

 

17 装饰模式(结构型模式)

  1. 定义:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式相比生成子类更加灵活。
  2. 技术分享
  1.  涉及角色:
    1. Component抽象构件,是一个接口或抽象类,定义最核心的对象,也就是最原始的对象。
    2. ConcreteComponent具体构件,要装饰的对象。
    3. Decorator抽象装饰角色,有一个执行抽象构件的属性,若只有一个装饰类则无需此类。
    4. ConcreteDecorator具体装饰角色,负责对原始对象进行装饰。
  1. 优点:
    1. 装饰类和被装饰类可以独立发展,而不会互相耦合。
    2. 装饰模式是继承关系的一个替代方案。
    3. 装饰模式可以动态地扩展一个实现类的功能。
    4. 可以通过不同装饰类,创建出不同的组合。
  2. 缺点:多层装饰提高了系统的复杂度。
  3. 应用场景:
    1. 需要扩展一个类的功能,或者给一个类增加附加功能。
    2. 需要动态给一个对象增加功能,这些功能可以再动态地撤销。
    3. 需要为一批的兄弟类进行改装或加装功能,首选装饰模式。

 

18 策略模式(行为型模式)

  1. 定义:也叫政策模式,定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。
  2. 技术分享
  3. 涉及角色:
    1. Context封装角色,也叫上下文角色,承上启下,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
    2. Strategy抽象策略角色,定义每个策略或算法必须具有的方法和属性的接口。
    3. ConcreteStrategy具体策略角色,实现抽象策略的操作,含有具体算法。
  4. 和代理模式区别,在于Context封装角色和被封装的策略类不是用的同一个接口。
  5. 优点:
    1. 算法可以自由切换。
    2. 避免使用多重条件判断。
    3. 扩展性良好,如ListIComparer实现排序一样,可轻松增加一个策略,其他都不用修改。
  6. 缺点:
    1. 策略类数量增多。
    2. 所有的策略类都需要对外暴露。
  7. 应用场景:
    1. 多个类只有在算法或行为上稍有不同的场景。
    2. 算法需要自由切换的场景,如经常变化的业务场景。
    3. 需要屏蔽算法规则的场景。

 

19 适配器模式(结构型模式)

  1. 定义:将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
    1. 又叫做变压器模式,也叫做包装模式。
    2. 技术分享
  2. 涉及角色:
    1. Target目标角色,该角色定义把其他类转换为何种接口,也就是我们期望接口。
    2. Adaptee源角色,被转换的类。
    3. Adapter适配器角色,通过继承或类关联的方式,把源角色转换为目标角色。
  3. 优点:
    1. 可以让两个没有任何关系的类在一起运行。
    2. 增加了类的透明性
    3. 提高了类的复用度
    4. 灵活性好,想用就用不想用就卸载。
  4. 缺点:采用了多继承,带来了高耦合。
  5. 应用场景:有动机修改一个已经投产中的接口时,适配器模式可能就是最合适的。
  6. 适配器模式是提供给正在运行的项目使用,项目设计时不要考虑。
  7. 对象是适配器,和类适配器的区别是,类适配器是类间继承,对象适配器是对象的合成关系,也就是关联关系。

 

20 迭代器模式

  1. 定义:它提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。
    1. 技术分享
  2. 组成角色
    1. Iterator抽象迭代器:负责定义访问和遍历元素的接口。
    2. ConcreteIterator具体迭代器:实现迭代器接口,完成元素遍历。
    3. Aggregate抽象容器:容器角色负责提供创建具体迭代器角色的接口。
    4. ConcreteAggregate具体容器:实现容器接口,创建出容纳迭代器的对象。

 

21 组合模式

  1. 定义:合成模式,部分整体模式,将对象组合成树形结构表示部分整体的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
    1. 技术分享
  2. 组成角色:
    1. Component抽象构件角色,定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性。
    2. Leaf叶子构件,叶子对象,其下再也没有其他的分支,也就是遍历的最小单位。
    3. Composite树枝构件,它的作用是组合树枝节点和叶子节点形成一个树形结构。
  3. 优点,高层模块调用简单,节点自由增加。
  4. 缺点,直接使用实现类,违法依赖倒置原则。
  5. 使用场景:
    1. 维护和展示部分-整体关系的场景,如树形菜单、文件和文件夹管理。
    2. 从一个整体中能够独立出部分模块或功能的场景。
  6. 注意,只要是树形结构,就可以考虑组合模式。

 

22 观察者模式

  1. 定义:也叫发布订阅模式,定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
    1. 技术分享
  2. 组成角色:
    1. Subject抽象被观察者,定义必须实现的职责,必须能够动态增加、取消观察者。并通知观察者。
    2. Observer抽象观察者,观察者收到消息后,进行update操作,对接收到的信息进行处理。
    3. ConcreteSubject具体被观察者,定义自己的业务逻辑,同时定义对哪些事件进行通知。
    4. ConcreteObserver具体观察者,每个观察者在接收到消息后的处理反应是不同的,有各自处理方法。
  3. 优点:
    1. 观察者和被观察者之间是抽象耦合
    2. 建立一套触发机制,符合单一职责原则。
  4. 缺点:多个观察者,开发和调试负责,一个卡壳会影响整体执行效率。
  5. 应用场景:
    1. 关联行为场景,关联行为是可拆分的。
    2. 事件多级触发场景。
    3. 跨系统的消息交换场景,如消息队列的处理机制。
  6. 注意:
    1. 广播链问题,多级关联
    2. 异步处理,如果处理时间较长,可以使用异步
  7. 最佳实践:
    1. 文件系统,新增文件通知目录管理器增加该目录
    2. 广播收音机,电台是被观察者,收音机是观察者。

 

23 门面模式

  1. 定义:也叫外观模式,要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行,门面模式提供一个高层次的接口,使得子系统更易于使用。
    1. 技术分享
  2. 组成角色:
    1. Facade门面角色,客户端调用这个角色,此角色知晓子系统所有的功能和责任。无实际业务逻辑,只做跳板。
    2. SubSystem子系统角色,可以同时又一个或者多个子系统,对于子系统门面角色只是另外一个客户端而已。
  3. 优点:
    1. 减少系统的相互依赖,所有的依赖都是对门面对象的依赖,与子系统无关。
    2. 提高了灵活性,不管内部如何变化,只要不影响门面对象,任你自由活动。
    3. 提高安全性,只能访问门面角色内的方法。
  4. 缺点:不符合开闭原则
  5. 使用场景:
    1. 为一个复杂的模块或子系统提供一个供外界访问的接口
    2. 子系统相对独立的情况,外界对子系统的访问只要黑箱操作即可
  6. 一般一个系统只需要一个门面,如果超过200行建议拆成多个门面
  7. 门面角色中不能有任何分支逻辑、顺寻执行逻辑否则会引子系统必须依赖门面才能被访问的问题。

 

24 备忘录模式

  1. 定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存,使对象可恢复到原来保存的状态。
    1. 技术分享
  2. 组成角色:
    1. Originator发起人角色,负责创建和恢复备忘录数据。
    2. Memento备忘录角色,负责存储Originator发起人角色内部状态。
    3. Caretaker备忘录管理员角色,对备忘录进行保存、管理和提供备忘录。
  3. 使用场景:
    1. 需要保存和恢复数据的相关状态场景。
    2. 提供一个可回滚的操作,如CTRL+Z
  4. 扩展:
    1. 可以使用clone实现对自身状态的管理。
    2. 可以使用反射实现类下所有属性的状态管理。
    3. 使用列表管理备忘录,可实现多备份。

 

25 访问者模式

  1. 定义:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
    1. 技术分享
  2. 组成角色:
    1. Visitor抽象访问者,抽象类或接口,声明访问者可以访问哪些元素,就是方法接收的参数。
    2. ConcreteVisitor具体访问者,实现访问者访问到一个类后干什么。
    3. Element抽象元素,声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定义的。
    4. ObectStruture结构对象,元素产生者,一般容纳在多个不同类、不同接口,如ListSetMap,项目中一般很少抽象出这个角色。
  3. 优点:
    1. 符合单一职责原则
    2. 优秀扩展性
    3. 灵活性高,比如针对不同对象,不同处理,可以不适用if
  4. 缺点:
    1. 具体元素对访问者公布细节
    2. 具体元素变更比较困难
    3. 违背了依赖倒置原则,访问者依赖的是具体元素,而不是抽象元素。
  5. 应用场景:需要对一个对象结构中的对象进行很多不同并且不相关的操作。

 

26 状态模式

  1. 定义:当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了它的类。
    1. 技术分享
  2. 组成角色:
    1. State抽象状态角色:负责对状态定义,并且封装环境角色以实现状态切换。
    2. ConcreteState具体状态角色:必须有2个职责,本状态下要做的事,和本状态如何过渡到其他状态。
    3. Context环境角色:定义客户端需要的接口,并且负责具体状态的切换。
  3. 优点:结构清晰、遵循设计原则、封装性好
  4. 缺点:子类会很多。
  5. 应用场景:
    1. 行为随状态改变而改变的场景,如权限设计,不同人,不同结果。
    2. 条件、分支判断语句的替代者。

 

27 解析器模式

  1. 定义:给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
  2. 使用场景:
    1. 重复发生的问题可以使用解释器模式,如收集不同格式日志。

 

28 亨元模式

  1. 定义:使用共享对象可有效地支持大量的细粒度的对象。建立对象池。
    1. 技术分享
  2. 组成角色:
    1. Flyweight抽象亨元角色,一个产品的抽象类,定义出对象的外部状态和内部状态的接口或实现。
    2. ConcreteFlyweight具体亨元角色,产品类,不能同时修改内部状态,外部状态。
    3. unsharedConcreteFlyweight不可共享的亨元角色,一般不会出现在亨元工厂中。
    4. FlyweightFactory亨元工厂,构造一个池容器,同时提供从池中获得对象的方法。
  3. 优缺点:大大减少应用程序创建的对象,降低内存占用,增强性能,同时提高了系统复杂性,需要分离外部内部状态,且外部状态固化。
  4. 应用场景:
    1. 系统中存在大量相似对象
    2. 需要缓冲池的场景

 

29 桥梁模式

  1. 定义:也叫桥接模式,将抽象和实现解耦,使得两者可以独立地变化。
    1. 技术分享
  2. 组成角色:
    1. Abstraction抽象化角色,定义出该角色的行为,同时保存一个实现化角色的引用,一般是抽象类。
    2. Implementor实现化角色,它是接口或者抽象类,定义角色必须的行为和属性。
    3. RefinedAbstraction修正抽象化角色,引用实现化角色对抽象化角色进行修正。
    4. ConcreteImplementor具体实现化角色,它实现接口或抽象类定义的方法和属性。
  3. 抽象角色引用实现角色,或者说抽象角色的部分实现是由实现角色完成的
    1. 尽量把最可能的变化封装到最小的逻辑单元,如果有多层继承,则考虑桥梁模式。
    2. 就像遥控器不包含开机、换台功能,只包含对电视机功能描述的接口引用,实现是有电视机完成。
  4. 优点:
    1. 抽象实现分离,为了解决继承的缺点而提出的设计模式,该模式下实现可以不受抽象的约束。
    2. 优秀的扩充能力。
    3. 实现细节对客户透明,客户不用关心实现细节。
  5. 应用场景:
    1. 不希望或不适用使用继承的场景
    2. 接口或抽象类不稳定的场景
    3. 重用性要求较高的场景

【设计模式之禅 第2版】读书笔记


推荐阅读
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 本文介绍了指针的概念以及在函数调用时使用指针作为参数的情况。指针存放的是变量的地址,通过指针可以修改指针所指的变量的值。然而,如果想要修改指针的指向,就需要使用指针的引用。文章还通过一个简单的示例代码解释了指针的引用的使用方法,并思考了在修改指针的指向后,取指针的输出结果。 ... [详细]
  • 本文介绍了django中视图函数的使用方法,包括如何接收Web请求并返回Web响应,以及如何处理GET请求和POST请求。同时还介绍了urls.py和views.py文件的配置方式。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 本文介绍了一种解析GRE报文长度的方法,通过分析GRE报文头中的标志位来计算报文长度。具体实现步骤包括获取GRE报文头指针、提取标志位、计算报文长度等。该方法可以帮助用户准确地获取GRE报文的长度信息。 ... [详细]
  • PDF内容编辑的两种小方法,你知道怎么操作吗?
    本文介绍了两种PDF内容编辑的方法:迅捷PDF编辑器和Adobe Acrobat DC。使用迅捷PDF编辑器,用户可以通过选择需要更改的文字内容并设置字体形式、大小和颜色来编辑PDF文件。而使用Adobe Acrobat DC,则可以通过在软件中点击编辑来编辑PDF文件。PDF文件的编辑可以帮助办公人员进行文件内容的修改和定制。 ... [详细]
  • CentOS 6.5安装VMware Tools及共享文件夹显示问题解决方法
    本文介绍了在CentOS 6.5上安装VMware Tools及解决共享文件夹显示问题的方法。包括清空CD/DVD使用的ISO镜像文件、创建挂载目录、改变光驱设备的读写权限等步骤。最后给出了拷贝解压VMware Tools的操作。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 在编写业务代码时,常常会遇到复杂的业务逻辑导致代码冗长混乱的情况。为了解决这个问题,可以利用中间件模式来简化代码逻辑。中间件模式可以帮助我们更好地设计架构和代码,提高代码质量。本文介绍了中间件模式的基本概念和用法。 ... [详细]
  • 导出功能protectedvoidbtnExport(objectsender,EventArgse){用来打开下载窗口stringfileName中 ... [详细]
author-avatar
郭建将_683
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有