彻底了解设计模式
Posted wei198621
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了彻底了解设计模式相关的知识,希望对你有一定的参考价值。
目录
参考文档:23 种设计模式详解(全23种) https://blog.csdn.net/A1342772/article/details/91349142
git代码: https://github.com/wei198621/DesignPatternDemo
23种设计模式,分为三大类:
A创建型模式:五种, A1:单例模式、A2:工厂方法模式、A3:抽象工厂模式、A4:建造者模式、A5:原型模式。
B结构型模式:七种, B1:代理模式、B2:外观模式、B3:适配器模式、B4:装饰器模式、B5:桥接模式、B6:组合模式、B7:享元模式。
C行为型模式: 十一种,观察者模式、策略模式、模板方法模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
A创建型模式
A1 单例模式
原文: https://blog.csdn.net/A1342772/article/details/91349142
定义:确保一个类最多只有一个实例,并提供一个全局访问点
单例模式可以分为两种:预加载和懒加载
2.1 预加载
顾名思义,就是预先加载。再进一步解释就是还没有使用该单例对象,但是,该单例对象就已经被加载到内存了。
public class PreloadSingleton
public static PreloadSingleton instance = new PreloadSingleton();
//其他的类无法实例化单例类的对象
private PreloadSingleton()
;
public static PreloadSingleton getInstance()
return instance;
很明显,没有使用该单例对象,该对象就被加载到了内存,会造成内存的浪费。
2.2 懒加载
为了避免内存的浪费,我们可以采用懒加载,即用到该单例对象的时候再创建。
public class Singleton
private static Singleton instance=null;
private Singleton()
;
public static Singleton getInstance()
if(instance==null)
instance=new Singleton();
return instance;
2.3 单例模式和线程安全
(1)预加载只有一条语句return instance,这显然可以保证线程安全。但是,我们知道预加载会造成内存的浪费。
(2)懒加载不浪费内存,但是无法保证线程的安全。首先,if判断以及其内存执行代码是非原子性的。其次,new Singleton()无法保证执行的顺序性。
不满足原子性或者顺序性,线程肯定是不安全的,这是基本的常识,不再赘述。我主要讲一下为什么new Singleton()无法保证顺序性。我们知道创建一个对象分三步:
memory=allocate();//1:初始化内存空间
ctorInstance(memory);//2:初始化对象
instance=memory();//3:设置instance指向刚分配的内存地址
vm为了提高程序执行性能,会对没有依赖关系的代码进行重排序,上面2和3行代码可能被重新排序。我们用两个线程来说明线程是不安全的。线程A和线程B都创建对象。其中,A2和A3的重排序,将导致线程B在B1处判断出instance不为空,线程B接下来将访问instance引用的对象。此时,线程B将会访问到一个还未初始化的对象(线程不安全)。
#### 2.4 保证懒加载的线程安全
我们首先想到的就是使用synchronized关键字。synchronized加载getInstace()函数上确实保证了线程的安全。但是,如果要经常的调用getInstance()方法,不管有没有初始化实例,都会唤醒和阻塞线程。为了避免线程的上下文切换消耗大量时间,如果对象已经实例化了,我们没有必要再使用synchronized加锁,直接返回对象。
public class Singleton
private static Singleton instance = null;
private Singleton()
;
public static synchronized Singleton getInstance()
if (instance == null)
instance = new Singleton();
return instance;
我们把sychronized加在if(instance==null)判断语句里面,保证instance未实例化的时候才加锁
public class Singleton
private static Singleton instance = null;
private Singleton()
;
public static synchronized Singleton getInstance()
if (instance == null)
synchronized (Singleton.class)
if (instance == null)
instance = new Singleton();
return instance;
我们经过2.3的讨论知道new一个对象的代码是无法保证顺序性的,因此,我们需要使用另一个关键字volatile保证对象实例化过程的顺序性。
public class Singleton
private static volatile Singleton instance = null;
private Singleton()
;
public static synchronized Singleton getInstance()
if (instance == null)
synchronized (instance)
if (instance == null)
instance = new Singleton();
return instance;
到此,我们就保证了懒加载的线程安全。
A2:工厂方法模式
讲了简单工厂,工厂方法,抽象工厂,
感觉例子不是太好,说实话没有体会到 工厂方法与抽象工厂的区别。
https://blog.csdn.net/A1342772/article/details/91349142
B结构型模式
B1:代理模式
C行为型模式
以上是关于彻底了解设计模式的主要内容,如果未能解决你的问题,请参考以下文章