设计模式概览
1、创建型模式(Creational Patterns)
2、结构型模式(Structural Patterns)
3、行为型模式(Behavioral Patterns)
创建性模式:
(1)工厂方法模式(Factory Method Pattern)
(1.1)简单工厂模式(Simple Factory Pattern)
(2)抽象工厂模式(Abstract Factory Pattern)
(3)建造者模式(Builder Pattern)
(4)原型模式(Prototype Pattern)
(5)单例模式(Singleton Pattern)
结构型模式:
(6)适配器模式(Adapter Pattern)
(7)桥接模式(Bridge Pattern)
(8)组合模式(Composite Pattern)
(9)装饰者模式(Decorator Pattern)
(10)外观模式(Facade Pattern)
(11)享元模式(Flyweight Pattern)
(12)代理模式(Proxy Pattern)
行为型模式:
(13) 责任链模式(Chain of Responsibility Pattern)
(14)命令模式(Command Pattern)
(15)解释器模式(Interpreter Pattern)
(16)迭代器模式(Iterator Pattern)
(17)中介者模式(Mediator Pattern)
(18)备忘录模式(Memento Pattern)
(19)观察者模式(Observer Pattern)
(20)状态模式(State Pattern)
(21)策略模式(Strategy Pattern)
(22)模板方法模式(Template Method Pattern)
(23)访问者模式(Visitor Pattern)
设计模式(Design Pattern)是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结。使用设计模式是为了可重用性代码,让代码更容易被他人理解,保证代码可靠性。
23中设计模式虽然每一种都有其独特的使用场景和作用,但在实际项目开发中常用到的还是其中几种,之后会依次介绍常用到的几种方式。本篇先从单例模式开始。
创建型模式之单例模式介绍
单例模式的优点:
1. 在内存中只有一个实例,减少了内存开销。
2. 可以避免对资源的多重占用。
3. 设置全局访问点,严格控制访问。
单例模式的缺点:
1. 没有接口,扩展困难。
2. 如果要扩展单例对象,只有修改代码,没有其他途径。
单例模式含义:
单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。
单例模式实现方式
1、饿汉式
随着类加载而初始化,并且创建单例对象
优点:
绝对线程安全,在线程还没出现以前就是实例化了,不可能存在访问安全问题。
没有加任何的锁、执行效率比较高,在用户体验上来说,比懒汉式更好
缺点:
类加载的时候就初始化,不管用与不用都占着空间,浪费内存。
举例说明:
public class MkjHungrySingleton {
/** 类的加载顺序:先静态、后动态、先属性、后方法。*/
private static MkjHungrySingleton mkjHungrySingleton = new MkjHungrySingleton();
/**私有构造器,防止其他类new */
private MkjHungrySingleton(){}
/**
* 获取实例
* @author: mkj
* @return com.rhjt.mkjtest.singleton.MkjHungrySingleton
*/
public static MkjHungrySingleton getInstance(){
return mkjHungrySingleton;
}
}
2、懒汉式
什么时候调用什么时候实例化,线程不安全
优点:
节省内存
缺点:
延时创建,需要时才创建实例效率慢,线程不安全。
下面我给出的例子是直接生产环境可以使用的
(1)双重锁检查模式
public class MkjIdlerSingleton {
/**
* 使用volatile防止指定重新排序
*/
private static volatile MkjIdlerSingleton mkjIdlerSingleton = null;
/**
* 私有构造器,防止利用构造方法创建实例
*/
private MkjIdlerSingleton() {
}
/**
* 获取实例方法 * @return com.rhjt.mkjtest.singleton.MkjIdlerSingleton
*/
public static MkjIdlerSingleton getInstance() {
if (mkjIdlerSingleton == null) {
synchronized (MkjIdlerSingleton.class) {
if (mkjIdlerSingleton == null) {
mkjIdlerSingleton = new MkjIdlerSingleton();
}
}
}
return mkjIdlerSingleton;
}
}
(2)静态内部类
这种形式兼顾饿汉式的内存浪费,也兼顾 synchronized 性能问题。内部类一定是要在方法调用之前初始化,巧妙地避免了线程安全问题。
public class MkjIdlerSingleton {
/** 使用volatile防止指定重新排序*/
private static volatile MkjIdlerSingleton mkjIdlerSingleton = null;
/** 私有构造器,防止利用构造方法创建实例*/
private MkjIdlerSingleton() {
}
/**
* 获取实例方法
* @return com.rhjt.mkjtest.singleton.MkjIdlerSingleton
*/
public static MkjIdlerSingleton getInstance(){
if (mkjIdlerSingleton==null){
synchronized (MkjIdlerSingleton.class){
if (mkjIdlerSingleton==null){
mkjIdlerSingleton = new MkjIdlerSingleton();
}
}
}
return mkjIdlerSingleton;
}
}
注:使用饿汉式和懒汉式创建单例时避免使用反射和序列化创建对象,因为这两种方式会破坏单例结构。
3、枚举式单例
枚举式不会被反射和序列化破坏,对此具体原因感兴趣的同学可以去研究下源码。
public enum MkjEnumSingleton {
INSTANCE;
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
/** 获取实例*/
public static MkjEnumSingleton getInstance() {
return INSTANCE;
}
}