创建型模式
- 封装了系统使用哪些类
- 隐藏了这些类类的实例是如何创建和放在一起的
建造者
将复杂对象的构建与表示相分离,同样的构建过程可以创建不同的表示
classDiagram class Builder { +buildPart() } class ConcreteBuilder { +buildPart() +getResult() } Builder <|-- ConcreteBuilder ConcreteBuilder --> Product class Director { +construct() } Director o--> Builder
- 可以改变一个产品内部表示
- 构造代码与表示代码分离
- 对构造进行更细粒度的控制
interface Builder{ Builder process1(); Builder process2(); Builder process3(); Product build();}class ConcreteBuilder implements Builder{ // 方法实现...}class ProductDirector{ public Product constructProduct(Builder builder){ builder.process1(); builder.process2(); builder.process3(); return builder.build(); }}// 使用ProductDirector director = new ProductDirector();Product product = director.constructProduct(new ConcreteBuilder());
工厂模式
简单工厂
客户无需知道具体产品的名称,只需要知道产品类所对应的参数即可
class Factory{ public Product get(int condition){ switch(condition){ case 1: return new Product1(); case 2: return new Product2(); } return null; }}
但是工厂的职责过重,而且当类型过多时不利于系统的扩展维护
工厂方法
定义一个接口,让子类创建该接口的实例,也就是将实例化延迟到工厂的子类
classDiagram ConcreteProduct --|> Product class ConcreteCreator { +factoryMethod() ConcreteProduct } class Creator { +factoryMethod() Product +operation() } ConcreteCreator --|> Creator ConcreteCreator ..> ConcreteProduct
- 工厂方法模式适合于构造同属于同一个类别的不同产品,所有的产品属于同一个系列中
模板方式和工厂模式的核心思想非常类似, 都是把一些操作留给子类去实现。模板方法经常使用工厂方法作为其算法的一部分
abstract class AbstractCreator{ abstract Product get(); public void doSomething(){ // do something Product product = get(); // do something }}class Creator1 extends AbstractCreator{ Product get(){...}}class Creator2 extends AbstractCreator{ Product get(){...}}// 使用Factory factory = new Creator2();Product product = factory.doSomething();
抽象工厂
提供一个创建一系列相关或相互依赖对象的接口,而无需指定具体类
classDiagram class AbstractFactory { +createProductA() +createProductB() } class ConcreteFactory1 { +createProductA() +createProductB() } class ConcreteFactory2 { +createProductA() +createProductB() } ConcreteFactory1 --|> AbstractFactory ConcreteFactory2 --|> AbstractFactory ProductA1 --|> AbstractProductA ProductA2 --|> AbstractProductA ProductB1 --|> AbstractProductB ProductB2 --|> AbstractProductB client ..> AbstractFactory client ..> AbstractProductA client ..> AbstractProductB
- 分离了具体的类
- 使得产品改变变得容易
- 利于维护产品的一致性
- 扩展产品种类困难
abstract class Factory{ abstract Product get(int condition);}class ProductAFactory extends Factory{ ProductA get(int condition){...}}class ProductBFactory extends Factory{ ProductB get(int condition){...}}// 使用Factory factory = new ProductAFactory();Product product = factory.get(condition);
在实践中,每个工厂一般都会是单例。工厂内部可使用原型模式来实现
原型
通过一个原型对象创建新的对象
classDiagram class Prototype { +clone() } class ConcretePrototype1 { +clone() } class ConcretePrototype2 { +clone() } Prototype <|-- ConcretePrototype1 Prototype <|-- ConcretePrototype2 Client --> Prototype
- 可以在运行时刻动态改变产品种类
- 改变值或结构就能获得新对象
- 动态配置
class Product { Part1 part1; @Override protected Object clone() throws CloneNotSupportedException { Product product = (Product) super.clone(); product.part1 = (Part1)part1.clone(); return product; }}
单例
一个类仅有一个实例,并只拥有一个全局访问点
问题:谁来销毁单例对象?什么时候销毁?
- 单例模式适用于生命周期很长的对象 一般不会显式销毁
- 使用SingletonDestroyer在程序关闭时进行销毁
- 对于相互依赖的单例对象 需要注意顺序
饿汉式
- 类初始化时,会立即加载该对象,线程天生安全,调用效率高
public class Singleton { private static final Singleton SINGLETON = new Singleton(); private Singleton() { } public static Singleton getInstance(){ return SINGLETON; }}
懒汉式
- 类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象,具备懒加载功能
public class Singleton { private static Singleton SINGLETON ; private Singleton() { } // 线程不安全 public static Singleton getInstance(){ if (SINGLETON == null){ SINGLETON = new Singleton(); } return SINGLETON; }}
静态内部类方式
- 结合了懒汉式和饿汉式各自的优点,真正需要对象的时候才会加载,加载类是线程安全的
public class Singleton { private Singleton() { } private static class SingletonClass{ public static final Singleton SINGLETON = new Singleton(); } public static Singleton getInstance(){ return SingletonClass.SINGLETON; }}
枚举单例
- 使用枚举实现单例模式 优点:实现简单、调用效率高,枚举本身就是单例,由jvm从根本上提供保障!避免通过反射和反序列化的漏洞, 缺点没有延迟加载
public class Singleton { private Singleton() { } private enum SingletonEnum{ INSTANCE; private Singleton singleton; SingletonEnum() { singleton = new Singleton(); } public Singleton getSingleton() { return singleton; } } public static Singleton getInstance(){ return SingletonEnum.INSTANCE.getSingleton(); }}
双重检测加锁
public class Singleton { private static volatile Singleton SINGLETON; // 如果没有volatile JVM的指令重排序很有可能导致实例化多个对象 private Singleton() { } public static Singleton getInstance(){ if (SINGLETON == null){ synchronized (Singleton.class){ if (SINGLETON == null){ SINGLETON = new Singleton(); } } } return SINGLETON; }}
// SINGLETON = new Singleton() 可以分解为以下三个步骤1 memory=allocate();// 分配内存 相当于c的malloc2 ctorInstanc(memory) //初始化对象3 s=memory //设置s指向刚分配的地址// 上述三个步骤可能会被重排序为 1-3-2,也就是:1 memory=allocate();// 分配内存 相当于c的malloc3 s=memory //设置s指向刚分配的地址2 ctorInstanc(memory) //初始化对象