设计模式是什么?
“它是一套理论,由软件界的先辈们(The Gang of Four:包括Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides)总结出的一套可以反复使用的经验,它可以提高代码的可重用性,增强系统的可维护性,以及解决一系列的复杂问题。”——摘自《设计模式之禅》
设计模式不是工具,不能为了设计模式而使用设计模式,它理解为是一种可以指导你如何去设计一个优秀的架构、编写一段健壮的代码、解决一个复杂的需求的哲学。
6大设计原则
6大设计原则包括:单一指责原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特法则、开闭原则。
23种设计模式
23种设计模式包括:单例模式、工厂方法模式、抽象工厂模式、模版方法模式、构造者模式、代理模式、原型模式、中介者模式、命令模式、责任链模式、装饰模式、策略模式、适配器模式、迭代器模式、组合模式、观察者模式、门面模式、备忘录模式、访问者模式、状态模式、解释器模式、享元模式、桥梁模式。
常见设计模式
单例模式
定义
Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)
实现方式
工厂方法模式
定义
Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)
通用类图
举个例子:
org.slf4j.LoggerFactory#getLogger(java.lang.Class)
就是一个工厂方法,只不过里边还用了其他模式。
抽象工厂模式
定义
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.(为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。)
通用类图
举个例子:还是
org.slf4j.LoggerFactory#getLogger(java.lang.String)
,它的实现就是一个抽象工厂模式。
模版方法模式
定义
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’sstructure.(定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。)
通用类图
使用场景
- 多个子类有公有的方法,并且逻辑基本相同时。
- 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
- 重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为。
举个例子:
org.springframework.web.servlet.view.AbstractTemplateView
中将最终渲染视图交给了子类。
构造者模式
定义
Separate the construction of a complex object from its representation so that the same construction process can create different representations.(将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。)
通用类图
使用场景
- 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式。
- 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式。
- 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适。
- 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时,也可以采用建造者模式封装该对象的创建过程。该种场景只能是一个补偿方法,因为一个对象不容易获得,而在设计阶段竟然没有发觉,而要通过创建者模式柔化创建过程,本身已经违反设计的最初目标。
注意:
虽然与工厂模式都是创建实例,但构造者模式更侧重于属性和执行顺序。
代理模式
定义
Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供一种代理以控制对这个对象的访问。)
通用类图
装饰模式
定义
Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.(动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。)
通用类图
使用场景
- 需要扩展一个类的功能,或给一个类增加附加功能。
- 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
- 需要为一批的兄弟类进行改装或加装功能,当然是首选装饰模式。
举个例子:
java.io.Reader
策略模式
定义
Define a family of algorithms, encapsulate each one, and make them interchangeable.(定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。)
通用类图
使用场景
- 多个类只有在算法或行为上稍有不同的场景。
- 算法需要自由切换的场景。
- 需要屏蔽算法规则的场景。
适配器模式
定义
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t other wise because of incompatible interfaces.(将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。)
通用类图
使用场景
- 你有动机修改一个已经投产中的接口时,适配器模式可能是最适合你的模式。
举个例子:搜索
*Adapter
,基本都是。
迭代器模式
定义
Provide a way to access the elements of anaggregate object sequentially without exposing its underlying representation.(它提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。)
通用类图
举个例子:
java.lang.Iterable#iterator
观察者模式
定义
Define a one to many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.(定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。)
通用类图
使用场景
- 关联行为场景。需要注意的是,关联行为是可拆分的,而不是“组合”关系。
- 事件多级触发场景。
- 跨系统的消息交换场景,如消息队列的处理机制。
举个例子:
org.springframework.context.event.ApplicationContextEvent
可以监听Spring容器事件。