模式
1. 策略模式⚓
定义:定义了算法族,分别封装起来,让他们可以互相替换,此模式让算法的变换独立于使用算法的客户。
- 将可以互换的行为封装起来,然后使用委托的方法,决定使用哪一个行为。
2. 观察者模式⚓
定义:定义了对象之间一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。
- java内置的观察者模式:Observer(观察者)与Observable(观察对象),setChanges(),notifyObservers()(拉取),notifyObservers(Object arg)(推送)。
3. 装饰者模式⚓
定义:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更具有弹性的替代方案。
- 装饰者与被装饰者有相同的超类型,以此达到类型匹配,而不是利用继承获得行为。
- 装饰者可以在所委托被装饰者的行为之前或之后,加上自己的行为,已达到特定的目的。
- java.io包
4. 简单工厂、工厂方法与抽象工厂模式⚓
简单工厂:使用另一个对象来作为创建对象的工厂。
工厂方法模式定义:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
抽象工厂模式定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
简单工厂与工厂方法之间的差异:
简单工厂在一个地方把所有东西都做完了;工厂方法却创建一个框架,让子类决定要如何实现。
工厂方法与抽象工厂之间的差异:
工厂方法 | 抽象工厂 |
---|---|
使用继承创建对象 | 使用对象的组合创建对象 |
通过子类创建对象,由子类负责决定具体的类型;把客户代码从需要实例化的具体类中解耦 | 提供一个用于创建一个产品家族的抽象类型,该类型的子类定义了产品被产生的方法 |
只创建一个产品 | 可以将一群相关的产品组合起来;加入新产品就必须改变接口 |
抽象工厂的方法经常以工厂方法的方式实现。
5. 单例模式⚓
定义:确保一个类只有一个实例,并提供一个全局访问点。
- 解决线程不安全问题:1. 使用synchronized;2. 类加载时立即实例化单个实例;3. 双重检查加锁。
- 程序有多个类加载器时,需要自行指定类加载器,并指定同一个类加载器。
6. 命令模式⚓
定义:将请求封装成对象,这可以让你使用不同的请求、队列或日志请求来参数化其它对象。支持撤销操作。
当需要发出请求的对象和执行请求的对象解耦时使用此模式。两者是通过命令对象来沟通的。
空对象(null object),不想处理null时可用空对象代替,do nothing。
- client,command,concreteCommand,receiver,invoker
- 宏命令
- 队列,日志
7. 适配器模式⚓
定义:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
- 类适配器,对象适配器,双向适配器
模式之间的区别:
模式 | 目的 |
---|---|
装饰者 | 不改变接口,但加入责任 |
适配器 | 将接口转变为另一个接口 |
外观 | 让接口更简单 |
8. 外观模式⚓
定义:提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。让客户与子系统之间避免紧耦合。
9. 模板方法模式⚓
定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下重新定义算法中的某些步骤。
- 保持好抽象方法的数目,在子类实现方法的数目与步骤数量之间折中。
- 为了防止子类改变模板方法中的算法,可以将模板方法声明为final。
- 模板方法模式与策略模式都封装算法,前者用继承,后者用组合。
- 工厂方法时模板方法的一种特殊版本。
钩子的几种用法:
- 让子类实现算法中的可选部分
- 在钩子对于子类的实现步重要的时候,子类可对钩子置之不理
- 让子类能够有机会对模板方法中某些即将发生(或刚发生)的步骤做出反应
10. 迭代器模式⚓
定义:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
- 把遍历的任务放在迭代器上,而不是聚合上。简化了聚合的接口和实现,也让责任各得其所。
- 迭代器意味着无序的。
- 迭代器将遍历聚合的工作封装进一个对象中。
11. 组合模式⚓
定义:允许你将对象组合成树形结构来表现整体/部分
层次结构。组合能让客户以一致的方式处理个别对象及对象组合。
- 能把相同的操作应用在组合和个别的对象上。
- 在实现该模式时,有很多设计上的折中。要根据需求平衡透明性和安全性。
12. 状态模式⚓
定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
- 封装基于状态的行为,并将行为委托到当前状态。
- 状态转换可以由state类或context类控制。
- 如果有多个context实例,就需要将状态的实例转移到静态的实例变量中共享。
- 该模式会导致设计中类的数量大量增加。
13. 代理模式⚓
定义:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
- 使用该模式创建代表对象,让代表对象控制某对象的访问。
- 控制访问方式:
- 远程代理控制访问远程对象
- 虚拟代理控制访问创建开销大的资源
- 保护代理基于权限控制对资源的访问
- java内置的代理支持:java.lang.reflect
- 动态代理的含义是在运行时才将它的类创建出来
- 变种:
- 防火墙代理,控制网络资源的访问,保护主题免于“坏客户”的侵害。
- 智能引用代理,当主题被引用时,进行额外的动作,例如计算一个对象被引用的次数。
- 缓存代理,为开销大的运算结果提供暂时的存储。它也允许多个客户共享结果,以减少计算或网络延迟。
- 同步代理,在多线程的情况下为主题提供安全的访问。
- 复杂隐藏代理,用来隐藏一个类的复杂集合的复杂度,并进行访问控制。也称外观代理。代理控制访问,而外观模式只提供另一组接口。
- 写入时复制代理,用来控制对象的复制,方法是延迟对象的复制,直到客户真的需要为止。是虚拟代理的变体。
14. 复合模式⚓
定义:结合多个模式,组成一个解决方案,解决一再发生的一般性问题。
15. 生成器模式(建造者模式)⚓
定义:讲一个复杂的对象地构造与它的表示分离,使同样的构建过程可以创建不同的表示。
- 将一个复杂对象的创建过程封装起来
- 允许对象通过多个步骤来创建,并且可改变过程(工厂方法只有一个步骤)
- 结构:
- 产品:包含多个组成部件的复制对象
- 抽象建造者:包含创建产品各个部件的接口,包含返回产品的方法
- 具体建造者:实现抽象建造者的接口
- 指挥者:调用建造者的部件构造并装配,完成产品的组装
- 适用场景:
- 创建的对象较复杂,由多个部件构成,各部件面临着复杂的变化,但构件间的建造顺序是稳定的。
- 创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表示是独立的。
- 可以根据需要省略掉抽象建造者、指挥者
16. 桥接模式⚓
定义:将抽象与实现分离,使它们可以独立变化。
- 将抽象化部分与实现化部分分开,取消二者的继承关系,改用组合关系
17. 责任链模式⚓
定义:为了避免请求发送者与多个请求处理者的耦合,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止,或不处理。
- 将请求的发送者与接受者解耦
- 通过改变链内的成员或调动他们的顺序,允许动态地新增或删除接受者
- 每个类都负责自己的工作,符合类的单一职责原则
- 满足开闭原则
18. 享元模式(蝇量模式)⚓
定义:利用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
- 减少运行时对象的实例个数,节省内存
- 将许多虚拟对象的状态集中管理
- 需要将不能共享的状态外部化
- 单个逻辑实例将无法拥有独立而不同的行为
- 两种状态:
- 内部状态:不会随着环境变化而发生变化的可共享部分
- 外部状态:会因环境的改变而发生变化的可变部分
- 单纯享元模式,这种享元模式中的所有的具体享元类都是可以共享的,不存在非共享的具体享元类
- 复合享元模式,这种享元模式中的有些享元对象是由一些单纯享元对象组合而成的,它们就是复合享元对象。虽然复合享元对象本身不能共享,但它们可以分解成单纯享元对象再被共享。
---------------------------------------以下模式未详细了解------------------------------------
19. 解释器模式⚓
20. 中介者模式⚓
定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象松耦合,且可以独立地改变它们之间的交互。
- 迪米特法则的典型应用
- 降低了对象之间的耦合性
- 将对象之间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展
- 同事类太多时,中介者的职责很大,难以维护
- 适用场景
- 当对象之间存在复杂的网状结构关系而导致依赖关系混乱且难以复用时。
- 当想创建一个运行于多个类之间的对象,又不想生成新的子类时。
21. 备忘录模式⚓
定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后在需要时恢复该状态。
- 将被存储的状态放在外面,不要和关键对象放在一起,可以帮助维护内聚
- 保持关键对象的数据封装
- 提供了容易实现的恢复能力
- 储存和恢复过程可能会很耗时
- java可以考虑使用序列化机制储存系统的状态
22. 原型模式⚓
定义:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
-
潜克隆:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
-
深克隆:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。
-
Cloneable 潜克隆
-
Serializable 深克隆,采用流的形式读入当前对象的二进制输入,再写出二进制数据对应的对象。
-
适用场景:
- 对象之间相同或相似的时候
- 对象的创建过程比较麻烦,但复制比较简单的时候
-
克隆困难的场景:
一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
-
经常与工厂方法一起使用
23. 访问者模式⚓
定义:将作用于某种数据结构的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的情况下可以添加作用于这些元素的新操作,为每个数据结构中的每个元素提供多种访问方式。
- 将数据结构及其操作分离
- 优点:
- 扩展性好。能够在不修改对象结构中的元素的情况下,为元素添加新功能。
- 复用性好。可以通过定义访问者来定义整个对象结构通用的功能。
- 符合单一职责原则。
- 缺点:
- 增加新的元素类很困难。每增加一个元素,就要在每一个具体的访问者类中增加相应的具体操作,违背了
开闭原则
。 - 破坏封装。具体元素对访问者公布细节,破坏了对象的
封装性
,违反了迪米特法则
。 - 违反了
依赖倒置原则
。依赖了具体类,而没有依赖抽象类。
- 增加新的元素类很困难。每增加一个元素,就要在每一个具体的访问者类中增加相应的具体操作,违背了
- 与迭代器联用,与组合模式联用