23种设计模式

本文详细解读了23种设计模式,包括简单工厂、工厂方法、单例、原型、建造者、门面、装饰器、享元、组合、适配器、桥接、委派、模板方法、策略、责任链、迭代器、命令、状态、备忘、中介者、解释器、观察者和访问者模式,帮助理解其核心理念和应用场景。

23种设计模式

0.简单工厂模式(Simple Factory Pattern)

简单工厂模式(Simple Factory Pattern)是指由一个工厂对象决定创建出哪一种产品类的实例,但它不属于GOF 23 种设计模式。简单工厂适用于工厂类负责创建的对象较少的场景,且客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心。

1. 工厂模式(Fatory Method Pattern)

工厂方法模式(Fatory Method Pattern)是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。在工厂方法模式中用户只需要关心所需产品对应的工厂,无须关心创建细节 ,而且加入新的产品符合开闭原则。

工厂方法模式主要解决产品扩展的问题,在简单工厂中,随着产品链的丰富,如果每个课程的创建逻辑有区别的话,工厂的职责会变得越来越多,有点像万能工厂,并不便于维护。根据单一职责原则我们将职能继续拆分,专人干专事。Java课程由Java 工厂创建,Python课程由Python工厂创建,对工厂本身也做一个抽象

工厂方法适用于以下场景
1、创建对象需要大量重复的代码。
2、客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
3、一个类通过其子类来指定创建哪个对象。

工厂方法也有缺点 ∶
1、类的个数容易过多,增加复杂度。 2、增加了系统的抽象性和理解难度。

2. 单例模式(Singleton Pattern)

单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。单例模式是创建型模式。单例模式在现实生活中应用也非常广泛,例如,公司CEO、部门经理等。J2EE 标准中的 ServletContext、ServletContextConfig 等、Spring 框架应用中的 ApplicationContext、数据库的连接池等也都是单例形式。

2.1 饿汉式

饿汉式单例模式在类加载的时候就立即初始化,并且创建单例对象。它绝对线程安全,在线程还没出现以前就实例化了,不可能存在访问安全问题。

这两种写法都非常简单,也非常好理解,饿汉式单例模式适用于单例对象较少的情况。这样写可以保证绝对线程安全、执行效率比较高。但是它的缺点也很明显,就是所有对象类加载的时候就实例化。这样一来,如果系统中有大批量的单例对象存在,那系统初始化是就会导致大量的内存浪费。也就是说,不管对象用与不用都占着空间,浪费了内存,有可能"占着茅坑不拉屎"。

2.2 饱汉式

为了解决饿汉式单例可能带来的内存浪费问题,于是就出现了懒汉式单例的写法,懒汉式单例模式的特点是 ,单例对象要在被使用时才会初始化

缺点
线程安全性问题

解决方法:
1、加sychronized关键字
2、双重检查锁机制
3、静态内部类方式

避免反射破坏单例的方法
1、在静态内部类的写法上,加一层判空,如果实例已经存在,直接抛出异常

避免序列化破坏单例
1、在类中增加readResolve() 方法

注册式单例模式

注册式单例模式又称为登记式单例模式,就是将每一个实例都登记到某一个地方,使用唯一的标识获取实例。注册式单例模式有两种∶

  • 一种为枚举式单例模式《effective java》书中推荐的方式
  • 另一种为容器式单例模式。

3. 原型模式

原型模式(Prototype Pattern)是指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象,属于创建型模式。

原型模式的核心在于拷贝原型对象。以系统中已存在的一个对象为原型,直接基于内存二进制流进行拷贝,无需再经历耗时的对象初始化过程(不调用构造函数),性能提升许多。当对象的构建过程比较耗时时,可以利用当前系统中已存在的对象作为原型,对其进行克隆(一般是基于二进制流的复制),躲避初始化过程,使得新对象的创建时间大大减少。

原型模式的优缺点
优点∶
1、性能优良,Java 自带的 原型模式 是基于内存二进制流的拷贝,比直接 new一个对象性能上提升了许多。
2、可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
缺点∶
1、需要为每一个类配置一个克隆方法。
2、克隆方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反了开闭原则。 3、在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深拷贝、浅拷贝需要运用得

4. 建造者模式

建造者模式(Builder Pattern)是将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示,属于创建型模式。使用建造者模式对于用户而言只需指定需要建造的类型就可以获得对象,建造过程及细节不需要了解。

建造者模式适用于创建对象需要很多步骤,但是步骤的顺序不一定固定。如果一个对象有非常复杂的内部结构(很多属性),可以将复杂对象的创建和使用进行分离。

建造者模式的设计中主要有四个角色∶ 1、产品 (Product )∶要创建的产品类对象
2、建造者抽象(Builder)∶建造者的抽象类,规范产品对象的各个组成部分的建造,一般由子类实现具体的建造过程。
3、建造者(ConcreteBuilder)∶具体的Builder 类,根据不同的业务逻辑,具体化对象的各个组成部分的创建。
4、调用者(Director)∶调用具体的建造者,来创建对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。建造者模式的应用场景
建造者模式适用于一个具有较多的零件的复杂产品的创建过程,由于需求的变化,组成这个复杂产品的各个零件经常猛烈变化,但是它们的组合方式却相对稳定。
建造者模式适用于以下几种场景 ∶
1 相同的方法,不同的执行顺序,产生不同的结果时
2 多个部件或零件,都可以装配到一个对象中,但是产生的结果又不相同。

3 产品类非常复杂,或者产品类中的调用顺序不同产生不同的作用。 4 当初始化一个对象特别复杂,参数多,而且很多参数都具有默认值时。

建造者模式应用案例
下面我们再来看一个实战案例,这个案例参考了开源框架 JPA的SQL构造模式。是否记得

我们在构造 SQL 查询条件的时候,需要根据不同的条件来拼接 SQL字符串。如果查询条件复杂的时候,我们SQL拼接的过程也会变得非常复杂,从而给我们的代码维护带来非常大的困难。因此,我们用建造者类QueryRuleSqIBuilder 将复杂的构造 SQL过程进行封装,用QueryRule 对象专门保存SQL查询时的条件,最后根据查询条件,自动生成 SQL语句。来看代码,

先创建QueryRule类∶主要是用于保存sql查询的条件
在创建QueryRuleSqlBuilder类 用于构造sql

建造者模式的优缺点
建造者模式的优点∶
1、封装性好,创建和使用分离;
2、扩展性好,建造类之间独立、一定程度上解耦。、
建造者模式的缺点 ∶
1、产生多余的 Builder 对象;
2、产品内部发生变化,建造者都要修改,成本较大。

建造者模式和工厂模式的区别
我们已经了解建造者模式,那么它和工厂模式有什么区别你? 1、建造者模式更加注重方法的调用顺序,工厂模式注重于创建对象。

2、创建对象的力度不同,建造者模式创建复杂的对象,由各种复杂的部件组成,工厂模式创建出来的都一样。
3、关注重点不一样,工厂模式模式只需要把对象创建出来就可以了,而建造者模式中不仅要创建出这个对象 ,还要知道这个对象由哪些部件组成。
4、建造者模式根据建造过程中的顺序不一样,最终的对象部件组成也不一样。

5. 代理模式

6. 门面模式

门面模式(Facade Pattern)又叫外观模式,提供了一个统一的接口,用来访问子系统中的一群接口。
特征:其主要特征是定义了一个高层接口,让子系统更容易使用。
属于结构性模式。

其实门面模式在好多时候我们也用到过,只是不知道而已,比如说pms中查询房型信息,前端只需要调用一个接口,后端我其实调用了很多个微服务的接口,然后把所有数据整合到一起,返回给前端页面。

collection也是门面模式的体现。

门面模式的适用场景
1、子系统越来越复杂,增加门面模式提供简单接口
2、构建多层系统结构,利用门面对象作为每层的入口,简化层间调用

类图:
在这里插入图片描述
门面模式在源码中的应用

jdbcUtils

门面模式与代理模式
门面模式就是特殊的静态代理模式

门面模式:重点是在于封装
静态代理:重点是在增强

不做增强的静态代理就是门面模式

代理:结构型模式
委派:行为型模式 不属于GOF 23种模式

门面模式和单例模式
很多时候,我们会做成单例模式,

门面模式的有点:
1、简化了调用过程,无需升入了解子系统,以防给子系统带来风险
2、减少系统依赖,松散耦合
3、更好的划分访问层次,提高了安全性
4、遵循迪米特法则,即最少知道原则

门面模式的缺点:
1、当增加子系统和扩展子系统行为时,可能容易来带未知风险
2、不符合开闭原则
3、某些情况下可能违背单一职责原则。

7. 装饰器模式

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

解释∶ 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。装饰器模式的核心是功能扩展。使用装饰器模式可以透明且动态地扩展类的功能。
装饰器模式主要用于透明且动态地扩展类的功能。其实现原理为 ∶让装饰器实现被包装类( Concrete Component )相同的接口(Component)(使得装饰器与被扩展类类型一致),并在构造函数中传入该接口(Component )对象,然后就可以在接口需要实现的方法中在被包装类对象的现有功能上添加新功能了。而且由于装饰器与被包装类属于同一类型(均为Component),且构造函数的参数为其实现接口类(Component),因此装饰器模式具备嵌套扩展功能,这样我们就能使用装饰器模式一层一层的对最底层被包装类进行功能扩展了。

包含的角色:

  • 抽象组件(Component):可以是一个接口或者抽象类,充当被装饰类的原始对象,规定了被装饰对象的行为;
  • 具体组件(ConcreteComponent):实现/继承Component 的一个具体对象,即被装饰对象
  • 抽象装饰器(Decorator):其内部必然有一个属性指向Component ,其实现一般是一个抽象类,主要是为了让其子类按照其构造形式传入一个Component ,这是强制的通用行为
  • 具体装饰器(ConcreteDecorator):Decorator的具体实现类

装饰器模式的适用场景

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

装饰者设计模式类图
在这里插入图片描述
装饰器模式最大的特征是实现一个构造方法,带一个参数,这个参数一定是抽象组件(类图中的Component)

装饰器模式,没有改变父类的任何功能,但是又扩展了父类的功能。

装饰器模式在JDK源码中的应用

public class Client {
    public static void main(String[] args) throws IOException {
        InputStream in = new FileInputStream("");
        BufferedInputStream bis = new BufferedInputStream(in);
        bis.read();
        bis.close();
    }
}

装饰器模式和dialing模式对比
1、装饰器模式就是一种特殊的代理模式
2、装饰器模式强调自身的功能扩展(业务层面)
3、代理模式强调代理过程的控制(比如加一个日志,权限之类的)

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

装饰器模式的缺点
1、会出现更多的代码,更多的类。增加程序的复杂性
2、动态装饰时,多层装饰时会更复杂

8. 享元模式

面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和
对象的个数。当对象数量太多时,将导致运行代价过高,带来性能下降等问题。享元模式正是为解决这
一类问题而诞生的。

享元模式(Flyweight Pattern)又称为轻量级模式,是对象池的一种实现。类似于线程池,线程池
可以避免不停的创建和销毁多个对象,消耗性能。提供了减少对象数量从而改善应用所需的对象结构的
方式。其宗旨是共享细粒度对象,将多个对同一对象的访问集中起来,不必为每个访问者创建一个单独
的对象,以此来降低内存的消耗,属于结构型模式。

原文∶ Use sharing to support large numbers of fine-grained objects efficiently.
解释∶ 使用共享对象可有效地支持大量的细粒度的对象。

享元模式把一个对象的状态分成内部状态和外部状态,内部状态即是不变的,外部状态是变化的;
然后通过共享不变的部分,减少对象数量并节约内存的目的

享元模式的本质是缓存共享对象,降低内存消耗

从类图上看,享元模式有三个参与角色 ∶

- 抽象享元角色∶享元对象抽象基类或者接口,同时定义出对象的外部状态和内部状态
的接口或实现;


- 具体享元角色∶实现抽象角色定义的业务。该角色的内部状态处理应该与
环境无关,不能出现会有一个操作改变内部状态,同时修改了外部状态;


- 享元工厂∶ 负责管理享元对象池和创建享元对象。

享元模式的应用场景

当系统中多处需要同一组信息时,可以把这些信息封装到一个对象中,然后对该对象进行缓存,这
样,一个对象就可以提供给多处需要使用的地方,避免大量同一对象的多次创建 ,消耗大量内存空间。

享元模式其实就是工厂模式的一个改进机制,享元模式同样要求创建一个或一组对象,并且就是通
过工厂方法生成对象的 ,只不过享元模式中为工厂方法增加了缓存这一功能

主要总结为以下应用场景;

1、常常应用于系统底层的开发,以便解决系统的性能问题。

2、系统有大量相似对象、需要缓冲池的场景。

在生活中的享元模式也很常见:比如各中介房源共享

代码中常用的享元模式案例
1、jdbc连接池 conn
2、String 定义为final的变量,一般在常量池中

享元模式的内部状态和外部状态

享元模式的定义为我们提出了两个要求∶细粒度和共享对象。因为要求细粒度对象,所以不可避免
地会使对象数量多且性质相近,此时我们就将这些对象的信息分为两个部分∶内部状态和外部状态。
内部状态指对象共享出来的信息,存储在享元对象内部并且不会随环境的改变而改变;外部状态指
对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态。
比如,连接池中的连接对象,保存在连接对象中的用户名、密码、连接 url 等信息,在创建对象的
时候就设置好了,不会随环境的改变而改变,这些为内部状态。而每个连接要回收利用时,我们需要给
它标记为可用状态,这些为外部状态。

享元模式的优点∶
1、减少对象的创建,降低内存中对象的数量,降低系统的内存,提高效率;

2、减少内存之外的其他资源占用。

享元模式的缺点∶
1、关注内、外部状态、关注线程安全问题 ;

2、使系统、程序的逻辑复杂化。

9. 组合模式

我们知道古代的皇帝想要管理国家,是不可能直接管理到具体每一个老百姓的,因此设置了很多机
构,比如说三省六部,这些机构下面又有很多小的组织。他们共同管理着这个国家。再比如说,一个大
公司,下面有很多小的部门,每一个部门下面又有很多个部门。说到底这就是组合模式。

组合模式(Composite Pattern)也称为整体-部分(Part-Whole)模式,它的宗旨是通过将单个
对象(叶子节点)和组合对象(树枝节点)用相同的接口进行表示,使得客户对单个对象和组合对象的使用具有一致性,属于结构型模式。

原文∶ Compose objectsintotree structures torepresent part-wholehierarchies.Compositelets clients treat individual objects and compositions of objects uniformly.
解释∶将对象组合成树形结构以表示 "部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

组合关系与聚合关系的区别 ∶

1、组合关系∶在古代皇帝三宫六院 ,贵妃很多,但是每一个贵妃只属于皇帝( 具有相同的生命周期)。


2、聚合关系∶一个老师有很多学生,但是每一个学生又属于多个老师(具有不同的生命周期)。
组合模式一般用来描述整体与部分的关系,它将对象组织到树形结构中,最顶层的节点称为根节点,
根节点下面可以包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点。

组合模式包含3个角色∶

1、抽象根节点(Component)∶定义系统各层次对象的共有方法和属性,可以预先定义一些默认
行为和属性 ;


2、树枝节点(Composite)∶定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成
一个树形结构;


3、叶子节点(Leaf)∶叶子节点对象,其下再无分支,是系统层次遍历的最小单位。

组合模式 在代码具体实现上,有两种不同的方式,分别是透明组合模式和安全组合模式。

组合模式的应用场景

当子系统与其内各个对象层次呈现树形结构时,可以使用组合模式让子系统内各个对象层次的行为
操作具备一致性。客户端使用该子系统内任意一个层次对象时,无须进行区分,直接使用通用操作即可,为客户端的使用带来了便捷

注∶ 如果树形结构系统不使用组合模式进行架构,那么按照正常的思维逻辑,对该系统进行职责分析,按上文树形结构图所示,该系统具备两种对象层次类型∶ 树枝节点和叶子节点。那么我们就需要构造两种对应的类型,然后由于树枝节点具备容器功能,因此树枝节点类内部需维护多个集合存储其他对象层次(如∶List,List),如果当前系统对象层次更复杂时,那么树枝节点内就又要增加对应的层次集合,这对树枝节点的构建带来了巨大的复杂性,臃肿性以及不可扩展性。同时客户端访问该系统层次时,还需进行层次区分,这样才能使用对应的行为,给客户端的使用也带来了巨大的复杂性。而如果使用组合模式构建该系统,由于组合模式抽取了系统各个层次的共性行为,具体层次只需按需实现所需行为即可,这样子系统各个层次就都属于同一种类型,所以树枝节点只需维护一个集合(List)即可存储系统所有层次内容,并且客户端也无需区分该系统各个层次对象,对内系统架构简洁优雅,对外接口精简易用。

组合模式主要总结为以下应用场景∶
1、希望客户端可以忽略组合对象与单个对象的差异时;
2、对象层次具备整体和部分,呈树形结构。

在我们生活中的组合模式也非常常见 ,比如树形菜单,操作系统目录结构,公司组织架构等。

透明组合模式的写法
透明组合模式是把所有公共方法都定义在 Component 中,这样做的好处是客户端无需分辨是叶子
节点(Leaf)和树枝节点(Composite),它们具备完全一致的接口。缺点是叶子节点(Leaf )会继承得到一些它所不需要(管理子类操作的方法)的方法,这与设计模式 接口隔离原则相违背。
为了让大家更加透彻理解,

下面我们来看安全组合模式的写法。
安全组合模式的写法

安全组合模式是只规定系统各个层次的最基础的一致行为,而把组合(树节点)本身的方法(管理子类对象的添加,删除等)放到自身当中。

安全组合模式的好处是接口定义职责清晰,符合设计模式 单一职责原则 和 接口隔离原则;缺点是
客户需要区分树枝节点(Composite)和叶子节点(Leaf),这样才能正确处理各个层次的操作,客户
端无法依赖抽象(Component ),违背了设计模式依赖倒置原则。

组合模式的优缺点
很多小伙伴肯定还有个疑问,既然组合模式会被分为两种实现,那么肯定是不同的场合某一种会更
加适合,也即具体情况具体分析。透明组合模式将公共接口封装到抽象根节点(Component)中,那
么系统所有节点就具备一致行为,所以如果当系统绝大多数层次具备相同的公共行为时,采用透明组合
模式也许会更好(代价∶为剩下少数层次节点引入不需要的方法);而如果当系统各个层次差异性行为
较多或者树节点层次相对稳定(健壮)时,采用安全组合模式

注∶ 设计模式的出现并不是说我们要写的代码一定要遵循设计模式所要求的方方面面,这是不现实同时也是不可能的。设计模式的出现,其实只是强调好的代码所具备的一些特征(六大设计原则),这些特征对于项目开发是具备积极效应的,但不是说我们每实现一个类就一定要全部满足设计模式的要求,如果真的存在完全满足设计模式的要求,反而可能存在过度设计的嫌疑。同时,23种设计模式,其实都是严格依循设计模式六大原则进行设计,只是不同的模式在不同的场景中会更加适用。设计模式的理解应该重于意而不是形,真正编码时,经常使用的是某种设计模式的变形体,真正切合项目的模式才是正确的模式。

下面我们再来总结一下组合模式的优缺点。

优点 ∶

1、清楚地定义分层次的复杂对象,表示对象的全部或部分层次

2、让客户端忽略了层次的差异,方便对整个层次结构进行控制


3、简化客户端代码

4、符合开闭原则

缺点∶

1、限制类型时会较为复杂


2、使设计变得更加抽象

10. 适配器模式

适配器模式( Adapter Pattern)又叫做变压器模式,它的功能是将一个类的接口变成客户端所期望
的另一种接口,从而使原本因接口不匹配而导致无法在一起工作的两个类能够一起工作,属于结构型设
计模式。

原文∶ Convert the interface of a class into another interface clients expect.Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.

解释∶将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一-起工作。

也就是说,当前系统存在两种接口 A 和 B,客户只支持访问 A接口,但是当前系统没有 A 接口对象,
但是有 B 接口对象,但客户无法识别B 接口,因此需要通过一个适配器C,将B 接口内容转换成 A接
口,从而使得客户能够从 A 接口获取得到 B 接口内容。
在软件开发中,基本上任何问题都可以通过增加一个中间层进行解决。适配器模式 其实就是一个中
间层。综上,适配器模式 其实起着转化/委托的作用,将一种接口转化为另一种符合需求的接口。

适配器模式的应用场景

提供一个转换器(适配器),将当前系统存在的一个对象转化为客户端能够访问的接口对象。适配
器适用于以下几种业务场景 ∶

1、已经存在的类,它的方法和需求不匹配(方法结果相同或相似)的情况。

2、适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成
功能类似而接口不相同情况下的解决方案。有点亡羊补牢的感觉。

适配器模式的优缺点

  • 优点: 1、可以让任何两个没有关联的类一起运行。 2、提高了类的复用。 3、增加了类的透明度。 4、灵活性好。

  • 缺点:

    • 1、过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
    • 2.由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。

生活中也非常的应用场景,例如电源插转换头、手机充电转换头、显示器转接头。
显示器转接头
两脚插转三角插手机充电接口

适配器模式一般包含三种角色∶

  • 目标角色(Target)∶也就是我们期望的接口;
  • 源角色(Adaptee)∶存在于系统中,内容满足客户需求(需转换),但接口不匹配的接口实例;
  • 适配器(Adapter)∶将源角色(Adaptee)转化为目标角色(Target)的类实例;

适配器模式各角色之间的关系如下∶
假设当前系统中,客户端需要访问的是 Target 接口,但 Target 接口没有一个实例符合需求,而
Adaptee 实例符合需求; 但是客户端无法直接使用 Adaptee(接口不兼容);因此,我们需要一个适
配器( Adapter )来进行中转,让 Adaptee 能转化为 Target 接口形式;

适配器模式有 2 种形式∶

  • 类适配器:
    类适配器的原理就是通过继承来实现适配器功能。具体做法∶让 Adapter 实现 Target 接口,并且
继承 Adaptee,这样 Adapter 就具备 Target和 Adaptee 的特性,就可以将两者进行转化。

    图例:
    在这里插入图片描述

  • 对象适配器:
    对象适配器的原理就是通过组合来实现适配器功能。具体做法∶让 Adapter 实现 Target 接口,然
后内部持有 Adaptee 实例,然后再 Target 接口规定的方法内转换 Adaptee。

    图例:
    在这里插入图片描述

在这里插入图片描述

11. 桥接模式

桥接模式 ( Bridge Pattern)也称为桥梁模式、接口(Interfce)模式或柄体(Handle and Body)模式 ,是将抽象部分与它的具体实现部分分离 ,使它们都可以独立地变化,属于结构型模式。

原文∶ Decouple an abstraction from its implementation so that the two can vary independently.解释∶解耦抽象和实现,使得两者可以独立的变化。

桥接模式主要目的是通过组合的方式建立两个类之间的联系,而不是继承。但又类似于多重继承方案,但是多重继承方案往往违背了类得单一职责原则,其复用性比较差,桥接模式是比多重继承更好的替代方案。桥接模式的核心在于解耦抽象和实现。

注∶此处的抽象并不是指抽象类或接口这种高层概念,实现也不是继承或接口实现 。抽象与实现其实指的是两种独立变化的维度。其中,抽象包含实现,因此,一个抽象类的变化可能涉及到多种维度的变化导致的。

桥接模式主要包含四种角色∶

抽象(Abstraction)∶该类持有一个对实现角色的引用,抽象角色中的方法需要实现角色来实现。
抽象角色一般为抽象类(构造函数规定子类要传入一个实现对象);

修正抽象(RefinedAbstraction)∶ Abstraction 的具体实现,对 Abstraction 的方法进行完善和
扩展;


实现(Implementor)∶确定实现维度的基本操作,提供给 Abstraction 使用。该类一般为接口或抽象类;


具体实现 ( Concretelmplementor)∶ Implementor 的具体实现。

12. 委派模式

13. 模板方法模式

14. 策略模式

14.1 策略模式的定义

策略模式(Strategy Pattern)又叫也叫政策模式(Policy Pattern),它是将定义的算法家族、分别封装起来,让它们之间可以互相替换,从而让算法的变化不会影响到使用算法的用户。属于行为型模式。

策略模式使用的就是面向对象的继承和多态机制,从而实现同一行为在不同场景下具备不同实现。

14.2 策略模式的应用场景

策略模式在生活场景中应用也非常多。比如一个人的交税比率与他的工资有关,不同的工资水平对应不同的税率。再比如我们在互联网移动支付的大背景下,每次下单后付款前,需要选择支付方式。(只能选用一种策略)

策略模式可以解决在有多种算法相似的情况下,使用if.else或switch.case所带来的复杂性和臃肿性。在日常业务开发中,策略模式适用于以下场景∶
1、针对同一类型问题,有多种处理方式,每一种都能独立解决问题;
2、算法需要自由切换的场景 ;
3、需要屏蔽算法规则的场景。

14.3 策略模式的角色

在这里插入图片描述
从 UML 类图中,我们可以看到,策略模式主要包含三种角色∶

  • 上下文角色(Context)∶ 用来操作策略的上下文环境,屏蔽高层模块(客户端)对策略,算法的直接访问 ,封装可能存在的变化 ;
  • 抽象策略角色(Strategy)∶ 规定策略或算法的行为 ;
  • 具体策略角色(ConcreteStrategy): 具体的策略或算法实现。

注意∶策略模式中的上下文环境(Context),其职责本来是隔离客户端与策略类的耦合,让客户端完全与上下文环境沟通,无需关系具体策略。

策略类一般配合单例模式和工厂模式一起使用,一般把factory当成上下文使用

14.4 策略模式的优缺点

优点 ∶
1、策略模式符合开闭原则。
2、避免使用多重条件转移语句,如i.else.语句、switch语句 (把选择权交给用户)
3、使用策略模式可以提高算法的保密性和安全性。

缺点∶
1、客户端必须知道所有的策略,并且自行决定使用哪一个策略类。
2、代码中会产生非常多策略类,增加维护难度。

15. 责任链模式

16. 迭代器模式

17. 命令模式

18. 状态模式

19. 备忘模式

20. 中介者模式

21. 解释器模式

22. 观察者模式

23. 访问者模式

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值