图说设计模式
软件模式是将模式的一般概念应用于软件开发领域,是软件开发的总体指导思路和参照样板。软件模式并非仅局限于设计模式,还包括:架构模式、分析模式和过程模式等。
设计模式(Design Pattern),是解决特定问题的一系列套路;是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案;是一套经验总结。
设计模式本质是面向对象设计原则的实际运用,是对类的封装性、继承性、多态性,以及类的关联关系和组合关系的充分理解。
设计模式主要有三大类型:创建型模式、结构型模式、行为型模式;
创建型设计模式:描述对象如何创建,是为了将对象的创建与使用分离。包括五种:单例、原型、工厂方法、抽象工厂、建造者。
结构型模式:描述类或对象如何组织成更大结构,包括7种:代理、适配器、桥接、装饰、外观、享元、组合。
行为型模式:描述类或对象之间如何协作完成任务,包括11种:模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器。
UML
类图和时序图
类之间的关系:
依赖关系(Dependency)、关联(A|ssociation)、聚合(Aggregation)、组合(Composition)、泛化关系(Generalization)、实现(Realization)。
七种设计原则:
耦合性、稳定性、风险、可读性、可维护性;
开闭原则(OCP):对扩展开放,对修改关闭;通过抽象约束、封装变化实现;使用接口或抽象类实现;
里氏替换原则(LSP):阐述继承复用的原则;开闭原则实现方式;子类继承父类时,尽量不要重写父类方法;(不要破坏继承关系)
依赖倒置原则(DIP):面向接口编程,不要面向实现编程;实现开闭原则的重要途径之一,降低了客户与实现模块间的耦合。
单一职责原则(SRP):类实现职责要单一;控制类的粒度、将对象解耦、提高内聚性;注重职责,主要约束类(实现和细节);
接口隔离原则(ISP):建立专用接口,提高内聚性,降低耦合性;注重对接口依赖的隔离,主要约束接口(抽象和框架);
迪米特法则(LoD):最少知识原则(LKP),降低耦合性;只和朋友交谈,不和陌生人说话;通过中介类,增加系统复杂性;
合成复用原则(CRP):组合/聚合复用原则(CARP),优先使用组合或聚合关系实现复用,少用继承关系来实现;
创建型模式
创建型模式(Creational Pattern),对类的实例化过程进行了抽象,将对象的创建和使用分离。单一职责原则;降低系统耦合度,使用者不需要关注对象创建细节,由相关工厂来完成;
单例模式(Singleton):
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,提供全局访问的方法。
![8f33195476b11bfe23c3ad8848270436.png](https://i-blog.csdnimg.cn/blog_migrate/61266672e60951ea8b3a252b79c58613.png)
![90dc8507e5f53792238d17a449a811fd.png](https://i-blog.csdnimg.cn/blog_migrate/e5b650dfebfaadaecac0057314af03e3.jpeg)
单例模式通常有两种实现方式:
饿汉式单例:类加载时就创建了单例;
懒汉式单例:类加载时不生成单例,第一次调用时才创建单例;多线程时,注意 volatile 和 synchronized 保证线程安全;
优缺点:没有抽象层,扩展困难;职责过重,违背单一职责原则;垃圾回收导致对象状态丢失; 原型模式(Prototype):
用于创建重复的对象,同时又能保证性能。提供了一种创建对象的最佳方法。
可以使用原型模式来复制一个对象自身,从而克隆出多个与原型对象一摸一样的对象;
![54fd2762a65552c6eba02e947acd6df6.png](https://i-blog.csdnimg.cn/blog_migrate/053face6679eb3d0884e0f91db0eb8b5.png)
原型模式,的克隆分为浅克隆和深克隆;Java 实现 Cloneable 接口用 Object 提供的 clone() 方法实现浅克隆;
![6e2f32dc5fd567a5b9e3df4621fe63b8.png](https://i-blog.csdnimg.cn/blog_migrate/d92719f66f0c6ac73b4c5c2e266cea59.png)
工程方法模式(FactoryMethod):
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类中。满足创建与使用相分离;
![fdc69790673191e2e5f6a5102cd62f40.png](https://i-blog.csdnimg.cn/blog_migrate/7e268be5f1392254e5490376c38afc40.png)
![06c83928649c33bf91e0ac168a44af3a.png](https://i-blog.csdnimg.cn/blog_migrate/0eb9091685afe24a1903936efaf32de4.jpeg)
抽象工厂(AbstractFactory):
抽象工厂模式,是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构;
抽象工厂模式,是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品;
![f37cec2cfdd841820f177453341edeb2.png](https://i-blog.csdnimg.cn/blog_migrate/992e4cbe85a9475118c671aa09e62cc3.png)
包含角色:抽象工厂、具体工厂、抽象产品、具体产品;
![0c7892ceae5954ebaa2a360a7d131a59.png](https://i-blog.csdnimg.cn/blog_migrate/29231bc0049dde8efaa1e592fc61aac2.jpeg)
建造者模式(Builder):
建造者模式,指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示;
![b89b4f77b50f039f60f8e840dbf21313.png](https://i-blog.csdnimg.cn/blog_migrate/f58e7e1e57a87c9da8f0913e37f2925c.png)
![53b1e92cc4fe6fd95454c382fb6d89c9.png](https://i-blog.csdnimg.cn/blog_migrate/b1d0c34a802b50110648799768c2dbfa.jpeg)
Computer computer=new Computer.Builder("因特尔","三星")
.setDisplay("三星24寸")
.setKeyboard("罗技")
.setUsbCount(2)
.build();结构型模式
结构型模式(Structural Pattern),关注如何将现有类或对象组织在一起,形成更加强大的结构;
可分为两种:类结构模式和对象结构模式;前者采用继承机制来组织接口和类,后者采用组合或聚合来组合对象;组合聚合关系比继承关系耦合度低,满足合成复用原则,所以对象结构型模式具有更大的灵活性。 适配器模式(Adaptor):
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
适配器模式分为:类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高; 典型应用场景:新旧系统兼容适配;第三方接口适配;电源转换适配器;
通过适配器模式可以将三方库的接口转换成目前系统设计的接口,而不需要大规模修改目前的系统;
通过设计适配器接口,可以兼容相同功能的不同实现方案;
类适配器模式:
![3e332b77b81f385a58be9771e231f8f8.png](https://i-blog.csdnimg.cn/blog_migrate/8befa6ca6fce961f233a3aec6aff10d0.png)
对象适配器模式
![20328b9e4faf19ce45379ae8c2049e34.png](https://i-blog.csdnimg.cn/blog_migrate/9ac51e913a0b1688c5029a1d9f38353e.png)
代理模式(Proxy):
封装目标对象,并限制外界对目标对象的访问。
在客户端和目标对象之间,引入一个代理中介,控制对目标对象的访问; 典型应用场景:AOP,面向切面编程,注入代码
注意区分装饰者模式和代理模式的区别;
![fe1aa4e2d6ed4f5381933b0067da5ef9.png](https://i-blog.csdnimg.cn/blog_migrate/6c3967c2f187ba1422d5736f8e716348.png)
应用场景:
远程代理、虚拟代理、安全代理、智能指引、延迟加载 桥接模式(Bridge):
将抽象与实现分离,使它们可以独立变化。用组合关系代替继承关系实现,从而降低抽象和实现的耦合度; 典型应用场景:解决类的多维度变化问题;(可以将继承的指数复杂度,降为组合的线性复杂度);产业分工就是典型的桥接模式,从以前的国企大包干,转变为产业协同发展,每个企业只负责产业链上某个部分;设计公司,将产业链上不同企业的产品组合式创新,形成新的产品;
桥接模式,将类的不同属性,按照属性维度拆分到不同的类中,每个类负责一个属性的变化。
![f3ed686a63ea2f2db81ee1c3a0f028a7.png](https://i-blog.csdnimg.cn/blog_migrate/ee9502ac849af7608676234736b31f64.png)
![6a436c375433ebc495b6d19aa95038a2.png](https://i-blog.csdnimg.cn/blog_migrate/8434fd252e63dd70275e2d0d94a90d72.png)
适配器、桥接模式、外观模式之间关系
桥接模式,可用于逻辑与实现的分离,一般在设计的前期;
适配器模式,用于第三方实现适配,一般在设计的后期;
![ca0162e1c510d8feb934de6fe325801d.png](https://i-blog.csdnimg.cn/blog_migrate/9cf44f612d693b9f790a8af9690bc792.png)
装饰模式(Decorator):
在不改变现有对象结构的情况下,动态地给对象增加一些额外功能(职责);
![33dde8ed71070ef6ae7b93cbe0396d41.png](https://i-blog.csdnimg.cn/blog_migrate/d27328cf4ae111ef1235685d380e2ea1.png)
![560ef9460034abce432fac36a6b3f2e4.png](https://i-blog.csdnimg.cn/blog_migrate/1c0fbccc4bb20f5cdbd1e5bef8995b9b.jpeg)
外观模式(Facade):
对外提供一个统一的接口;迪米特法则的典型应用,降低耦合度,屏蔽了子系统组建; 典型应用场景:微服务的网关,API Gateway ;
![1af040f4df31c115272296d33c8db8cc.png](https://i-blog.csdnimg.cn/blog_migrate/e8387c3d53accf59aa001655033c6a94.png)
![4737c0a4f884d083287a3c9a4996551c.png](https://i-blog.csdnimg.cn/blog_migrate/4194d1a273d879472cc30b1fbef95e8f.jpeg)
享元模式(Flyweight):
享元模式是池技术的重要实现方式;
运用共享技术来有效支持大量细粒度对象的复用;避免大量对象的创建开销,提高系统资源利用率;
![f7b94e76db85787ad7bcbc7f5d73ab99.png](https://i-blog.csdnimg.cn/blog_migrate/e35be516b9260931ddece810abf82ba0.png)
![4afbba6d13f4f8c5dbd9e1bbd5b11734.png](https://i-blog.csdnimg.cn/blog_migrate/639225835275e66e3e2fec7c62fa8aea.png)
单纯享元和复合享元模式; 组合模式(Composite):
也叫部分-整体模式,将对象组合成树状的层次结构的模式,用来表示部分-整体关系,使用户对单个对象和组合对象具有一致的访问性;
分为透明式和安全式的组合模式;
透明式:
![baa1bd8caf549852e1f50246f455119f.png](https://i-blog.csdnimg.cn/blog_migrate/8edf43c06b0b93b9ad583867e508439b.png)
安全式:
![b166004ff44355dc32f0763c4588afff.png](https://i-blog.csdnimg.cn/blog_migrate/b55e4ba991f6b230ac854819c5df072b.png)
行为型模式
行为型模式,用于描述程序在运行时复杂的流程控制;
描述多个类或对象之间,如何相互协作共同完成单个对象无法完成的任务;涉及算法与对象间职责的分配;
行为型模式可分为:类行为模式和对象行为模式,前者采用继承机制来实现类间分派行为,后者采用组合或聚合在对象间分配行为。
模板方法模式和解释器模式是类行为模式;
模板方法模式(Template Method):
定义操作的算法骨架,而将一些步骤延迟到子类,使得子类可在不改变算法结构的情况下,重定义算法的某些特定步骤;
封装固定部分,扩展可变部分;符合开闭原则;
类似可编程渲染管线;管线流程固定,着色器可编程扩展;
![0335f33d77e3a4b38e0632a7fd5dd7a5.png](https://i-blog.csdnimg.cn/blog_migrate/7a5285abd8bacedab70429bcae4f837a.png)
策略模式(Strategy):
定义策略接口,不同的实现类提供不同的具体策略算法,同时它们之间可以互相替换。
通过对算法封装,把使用算法的责任和实现分割开来,并委派给不同的对象进行管理;
使用策略模式:可以避免使用多重条件语句;通过提供可复用算法,避免重复的代码;提供相同行为的不同实现;
灵活组织算法;
![623ae67f8694cc67a5e81c81f80415f2.png](https://i-blog.csdnimg.cn/blog_migrate/3296f74db1ed13a9039048f6d8a2ef22.png)
命令模式(Command):
将一个请求封装成一个对象,使发出请求的责任和执行请求的责任分隔开。请求者和实现者,通过命令对象进行沟通,方便将命令对象进程储存、传递、调用、增加和管理;
类似于消息通信,通过消息管道(命令接口),来将消息发送给接收方处理
![9ebc097990090605aa01d77d51aa4d34.png](https://i-blog.csdnimg.cn/blog_migrate/2e9c83d612f62cee3bfba0a56d95afed.png)
![60f5246d2aefa69960735d3311fbbcb4.png](https://i-blog.csdnimg.cn/blog_migrate/121358ea2b1ba666f7878751a48a8391.jpeg)
责任链模式(Chain of Responsibility):
通过数据链表实现责任链模式;
类似Pipeline 模式实现,DAG 和Blender 节点编程
![4d260547bd116ce04d8c3c4be6310e10.png](https://i-blog.csdnimg.cn/blog_migrate/6aff3b7b43c6e75540436e2ac10cb94f.png)
![5e95dcdfedb16ff4fe0db415e7967c22.png](https://i-blog.csdnimg.cn/blog_migrate/6fce8cf77caa705de4459ff28ec43682.png)
状态模式(State):
对有状态的对象,把复杂的判断逻辑提取到不同的状态对象种,允许状态对象在其内部状态发生改变时,改变其行为;
类似状态机机制,包括有限状态机和层次状态机;线程状态切换机制;
![9803d5c0a1f8444358d5d38b9b8868fa.png](https://i-blog.csdnimg.cn/blog_migrate/f881db6306f653953a7e02de19159f9c.png)
![af525f73fd81dd12e0fa4357bde1726e.png](https://i-blog.csdnimg.cn/blog_migrate/9ec57899e6d34ca080767570d3ad775e.png)
![1956cf79e6960a038b92601fcbfe9d37.png](https://i-blog.csdnimg.cn/blog_migrate/156c1f41a801e004a9c2ebf1f1bbae9c.png)
观察者模式(Observer):
定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象,在状态发生变化时,会通知所有观察者;
接口回调,响应式编程 RxJava,订阅通知机制;
Observable 和 Observer
![30cdc3873838ed16fc06c9f97df1247d.png](https://i-blog.csdnimg.cn/blog_migrate/9e3e1cce1d1ad60532a753830e7a92dc.png)
![06ca23501831fa8d5998feb299f3fa10.png](https://i-blog.csdnimg.cn/blog_migrate/ed80d5f06b39158ef9b974cc0b4019aa.jpeg)