常用设计模式
具体可见链接 Click Here.本文使用中文且稍微有所扩展,前面的链接包含了23种设计模式,这里说常用的10个.
-
单例:不同的写法,
-
懒汉式,线程不安全(最基础的单例)
-
懒汉式,线程安全(直接加
synchronized
) -
饿汉式(直接静态就加载,不延迟,利用类加载机制避免同步问题,因为虚拟机执行
<clinit>()
,即类初始化时保证线程安全) -
线程安全的DCL(1.5以后,
volatile
对内存语义有更新,限制了指令重排)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public class Singleton { private static volatile Singleton instance; public static Singleton getInstance() { if(instance == null)//Check 1 { synchronized(Singleton.class)//P(monitor) { if(instance == null)//Check 2 instance = new Singleton(); }//V(monitor) } return instance; } }
- 静态内部类(静态内部类不会因为外部类被初始化而初始化,而只会当外部类调用内部类成员时先被加载,而这里的加载也被虚拟机保证是线程安全的)
1 2 3 4 5 6 7 8 9 10 11 12
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } }
-
-
工厂方法/抽象工厂
-
工厂方法(虚构造器):先定义创建对象的接口(抽象的工厂方法),子类实现这个工厂方法.即创建过程延迟到子类进行.(也可以用泛型,在Java需要反射)
-
抽象工厂:定义一个抽象工厂,定义了一系列的创建对象的方法,然后具体的工厂就去重写它们.它适用于有多个产品族,但系统只需要创建其中一个产品族的情形.(例如某个产品需要<A,B>,但有很多产品族,如<A1,B1>,<A2,B2>等等,创建工厂时,A和B绑定在一起,一起创建的)
-
-
观察者:一个对象(
Subject
)状态改变,其所依赖的对象(Observer
)会得到通知,通知是广播/组播的.(抽象的)Subject
维护了一个(抽象)Observer
的列表,当Subject
状态改变,则遍历这个列表将通知发给所有的Observer
;而(具体的)Observer
需要知道自己所观察的Subject
,当通知到来的时候可以从Subject
中获取其状态. -
适配器(
Wrapper
):适配器适配接口,并使用了被适配的对象(通过聚合或者多继承,后者适用于C++).通常这个适配器可作为一个Wrapper
. -
策略:抽象类/接口
Strategy
定义一个算法,然后具体的不同的ConcreteStrategy
继承它并实现这个算法.外部可以通过这个抽象类/接口并赋予不同的具体策略以调用不同的策略/算法. -
责任链(本质是个链表,链式反应):定义一个
Handler
,定义了处理请求的方法,并在里面包含它的后继者,用于将请求转发给后继者处理.而具体的ConcreteHandler
实现这个接口/抽象类,在处理自己的请求后选择是否将请求转发给下一个Handler
.应用:Servlet
中的Filter
. -
装饰器:装饰者实现/继承接口/抽象类,并聚合了其他具体组件,实现了该具体组件功能的同时也同样在该功能基础上添加了新特性.具体实践有Java IO (
Input/OutputStream
). -
模板:定义一个操作算法的步骤(在父类/抽象类中),而这些步骤的实现延迟到子类里.
-
组合:组件分为单一组件和复合组件,都继承于某个接口/抽象类.而复合组件拥有一组组件(通常用列表保存).可以把单一组件看作叶节点,复合组件作为非叶节点.
-
迭代器:见Java Collections, C++ STL的迭代器(例如链表,二叉树迭代器等等).