一 设计模式简介
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
二 设计模式分类
总体来说设计模式分为三类
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
意义:创建对象时,不再直接实例化对象,而是根据特定场景,有程序确定创建对象的方式,从而保证更大的性能、更好的性能优势。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
意义:用于帮助将多个对象组织成更大的结构。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
其实还有两类:并发型模式和线程池模式。
意义:用于帮助系统间各对象的通信,如何控制复杂系统的流程。
三 设计模式的六大原则
1 单一职责原则:不要存在多于一个导致类变更的原因,即一个类只需实现一项职责,主要可以实现高内聚、低耦合。
2 开放封闭原则:对于扩展是开放的,对于修改是关闭的。(目的)
3 里氏替换原则:任何基类可以出现的地方,子类一定可以出现。(实现)
4 依赖倒置原则:高层次的模块、低层次的模块与具体实现都应该依赖于抽象,也可以说应该依赖于接口编程。(方法)
5 接口隔离原则:接口应该只处理一类定制的方法。
6 迪米特法则:又叫最少知道原则,就是说一个对象应当对其他对象有尽可能少的了解,也可以说一个类应该对自己需要耦合或调用的类知道得最少。
四 单例模式介绍
1 单例模式概念:单例模式确保某一个类有且仅有有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
2 常见实现方法:
- 懒汉式,线程不安全
- 懒汉式,线程安全
- 饿汉式
- 饿汉式,变种
- 静态内部类
- 双重检验锁
- 登记式
public classSingleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance(){
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
public classSingleton { private static Singleton instance; private Singleton(){ } public static synchronized Singleton getInstance() {//同步锁 if (instance== null) {#1 instance = new Singleton();#2 } return instance;#3 } }
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){ } public static Singleton getInstance() { return instance; } }
上述代码在类一加载便实例化instance,因此称为饿汉式
public class Singleton { private Singleton instance = null; static { instance = new Singleton(); } private Singleton (){} public static Singleton getInstance() { return this.instance; } }
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = newSingleton(); } private Singleton (){} public static final Singleton getInstance(){ return SingletonHolder.INSTANCE; } }
相对于第三种方式,这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显式通过调用getInstance方法时,才会显式装载SingletonHolder类,从而实例化instance。例如,如果实例化instance很消耗资源,我想让其延迟加载,另一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。
6)双重校验锁:“双重检查加锁”的方式可以既实现线程安全,又能够使性能不受到很大的影响。
所谓双重检查加锁机制指的是:并不是每次进getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。
重检查加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。(对于volatile修饰的变量,系统内的线程所有的write都将先行发生于read)
说明:由于volatile关键字可能会屏蔽掉虚拟机中的一些必要的代码优化,所以运行效率并不是很高。因此一般建议,没有特别的需要,不要使用。也就是说,虽然可以使用“双重检查加锁”机制来实现线程安全的单例,但并不建议大量采用,可以根据情况来选用。
public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getInstance() { if (singleton == null) {#2 synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
注:很显然上述代码是线程安全的,然而细心的朋友可以发现,如果把去掉第一重判断#2,此时的代码也是线程安全的,与单例第二种实现方式没有本质的区别,那么为什么加上#2呢,好处有:提高代码运行效率,当线程1实例了singleton后,此时线程2判断singleton不为空,那么synchronized同步代码并需要执行,因为加锁、解锁很大的影响系统性能,尽量少用。
public abstract class Singleton<T> { private T mInstance; protected abstract T create(); public final T get() { synchronized (this) { if (mInstance == null) { mInstance = create(); } return mInstance; } } }
public class AManager { private static final Singleton<AManager> sInstance = new Singleton<AManager>() @Override protected AManager create() { return new AManager(); } }; public static AManager getInstance(){ return sInstance.get(); }
private AManager(){ System.out.println("AManager created!"); } }
参考:http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html
http://blog.csdn.net/u014539776/article/details/50775470