设计模式系列

422 阅读4分钟

软件设计模式(DesignPattern)

Java中一般常用的设计模式有23种,其中常用的几种设计模式应该去掌握。 总体来说设计模式分为三大类:

创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

单例模式

1、什么是单例模式?

百度百科是这样定义的:单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例

我是这样理解的:单例模式就是只允许一个实例,最开始使用它的时候是C#中,我要实例化一个A窗体,但是有个需求就是A窗体必须是唯一,不管我在B窗体操作A窗体还是C窗体中操作A窗体都是如此,这时候就使用到了单例模式。

2、单例模式分类

  • 懒汉单例模式:在第一次调用的时候实例化本身,在并发环境下,可能出现多个本身对象。所以线程是不安全的。

  • 饿汉单例模式:在类初始化时,已经自行实例化一个静态对象,所以本身就是线程安全的。

  • 登记单例模式:通过一个专门的类对各单例模式的单一实例进行管理和维护。

  • 枚举模式

3、特点

A、 单例模式类只能有一个实例 B、 单例模式类必须自己创建自己的唯一实例 C、 单例模式类必须给所有其他对象提供这一实例

代码示例

1:懒汉模式example
public class SingleExample {
	
	/**
	 * 该函数限制用户主动创建实例
	 */
	private SingleExample() {}
	private static SingleExample singleExample= null;
	
	/**
	 * 获取SingleExample实例(也叫静态工厂方法)
	 * @return SingleExample
	 */
	public static SingleExample getSingleExample() {
		/* SingleExample为空时创建它,反之直接返回,保证唯一性 */
		if(singleExample == null){
			singleExample = new SingleExample();
		}
		return singleExample;
	}
	
}

这种方式在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。 这种方式基于类加载机制避免了多线程的同步问题,但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到懒加载的效果。

2:饿汉模式example
public class SingleExample {

	/**
	 * 该函数限制用户主动创建实例
	 */
	private SingleExample() {}

	private static final SingleExample singleExample = new Singleton();

	/**
	 * 获取SingleExample实例,也叫静态工厂方法
	 * @return SingleExample
	 */
	public static SingleExample getInstance() {
		return SingleExample;
	}
}
3:静态内部类单例模式
public class SingleExample {
	/**
	 * 类级的内部类,也就是静态类的成员式内部类,该内部类的实例与外部类的实例
	 * 没有绑定关系,而且只有被调用时才会装载,从而实现了延迟加载
	 * @author dream
	 *
	 */
	private static class SingleExampleHolder{
		/**
		 * 静态初始化器,由JVM来保证线程安全
		 */
		private static final SingleExample instance = new SingleExample();
	}
	
	/**
	 * 私有化构造方法
	 */
	private SingleExample(){
		
	}
	
	public static SingleExample getInstance(){
		return SingleExampleHolder.instance;
	}
}

4:登记模式example
public class SingleExample {

	// 存储需要进行维护和管理的类的实例
	private static Map<String, SingleExample> map = new HashMap<String, SingleExample>();
	
	/**
	 * 静态创建实例并添加到Map集合
	 */
	static {
		SingleExample singleExample = new SingleExample();
		map.put(SingleExample.getClass().getName(), singleExample);//运用了反射
	}

	/**
	 * 该函数限制用户主动创建实例
	 */
	private SingleExample() {};

  /**
      * 静态工厂方法,返回指定登记对象的唯一实例
      * 对于已经登记的直接取出返回,对于还未登记的先登记,然后取出返回
      *
      */
     public static RegMap getInstance(String name){
         if(name==null){
             name="SingleExample";
         }
         if(map.get(name)==null){
             try {
                 map.put(name, (RegSingleton) Class.forName(name).newInstance());
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
         return map.get(name);
     }

}
5:枚举单例模式
public enum SingleExample {  
     INSTANCE;  
     public void doSomeThing() {  
     }  
 }  

枚举单例的优点就是简单,但是大部分应用开发很少用枚举,可读性并不是很高,不建议使用。

何时选用单例模式 当需要控制一个类的实例只能有一个,而且客户只能从一个全局访问点访问它时,可以选用单例模式,这些功能恰好是单例模式要解决的问题。