设计模式03--创建型模式

1 设计模式分类

创建型:单例模式、工厂模式、原型模式、建造者模式
结构型:适配器模式、桥接器模式、装饰模式、组合模式、外观模式、享元模式、代理模式
行为型:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式

2 工厂模式

  • 工厂模式属于创建型模式,
  • 用法是定义一个类,用这个类来封装对象的实例化过程
  • 适用于大量重建某种、某批对象的时刻

2.1 简单工厂/静态工厂

创建一个类,创建一个静态方法,根据传进来地字符串创建对象。出啊同方法就是使用if else或者switch ... case ...返回要创建地具体对象。例如构造一个生产Pizza的工厂类

  • 优点是实现简单
  • 缺点是违反了ocp原则,增加新需求需要在使用处进行改动,例如添加一个新的pizza品种

2.2 抽象工厂

  1. 定义一个interface用于创建相关或者有依赖地对象簇,而无需指明具体地类
  2. 将工厂分为两层,将负责创建的任务交给子类

2 单例模式

保证某个类只能有一个对象,并且提供获取该对象引用的方法。

3 创建方法

3.1 饿汉式

class Singleton1{
	// 在定义时进行初始化
    private final static Singleton1 SINGLETON_1 = new Singleton1();
    private Singleton1(){}
    public static Singleton1  getSingleton(){
        return  SINGLETON_1;
    }
}

class Singleton2{
    private final  static  Singleton2 SINGLETON_1;
    // 静态代码块
    static {
        SINGLETON_1 = new Singleton2();
    }
    private Singleton2(){}

    public static Singleton2  getSingleton(){
        return  SINGLETON_1;
    }
}

特点:

  1. 写法简单,在类加载地过程中就完成了实例化,避免了线程同步的问题。
  2. 在类加载的时候就会创建实例,会造成内存的浪费

3.2 懒汉式

3.2.1创建方法1

public class Lazy1 {
    private static Lazy1 instance;
    private Lazy1(){}
    public static Lazy1 getInstance(){
        if(instance == null){
            instance = new Lazy1();
        }
        return instance;
    }
}
  • 懒加载
  • 线程不安全
  • 实际开发时不可用

可以考虑加入synchronized 关键字解决。

class Lazy2{
    private static Lazy2 instance;
    private Lazy2(){}
    public static synchronized Lazy2 getInstance(){
        if(instance == null){
            instance = new Lazy2();
        }
        return instance;
    }
}
  • 线程安全
  • 但是效率低(每次获取实例都需要加锁,效率低)

3.2.2 创建方法2–双重检查

先判断对象是否未创建,然后再加锁减小加锁粒度。
法一:错误示范

class Lazy3{
    private static Lazy3 instance;
    private Lazy3(){}
    public static synchronized Lazy3 getInstance(){
    	// 线程不安全
        if(instance == null){
            synchronized (Lazy3.class){
                instance = new Lazy3();
            }
        }
        return instance;
    }
}
  • 线程不安全,会导致重复创建

正确做法:使用volatile关键字,保证修改的可见性

class Lazy3{
	// volatile 解决可见性问题
    private static volatile Lazy3 instance;
    private Lazy3(){}
    public static synchronized Lazy3 getInstance(){
        if(instance == null){
            synchronized (Lazy3.class){
	            if(instance == null)
	                instance = new Lazy3();
            }
        }
        return instance;
    }
}
  • 双重检查地,保证了在实例还未创建时,若干线程同时调用getInstance方法。
  • volatile关键字:保障了可见性与有序性

3.2.3 创建方法3-静态内部类

public final class Singleton {
	private Singleton() { }
	// 问题1:属于懒汉式还是饿汉式
	private static class LazyHolder {
		static final Singleton INSTANCE = new Singleton();
	}
	// 问题2:在创建时是否有并发问题
	public static Singleton getInstance() {
		return LazyHolder.INSTANCE;
	}
}
  • 采用类加载机制保证线程安全问题
  • 在创建Singleton类时,内部类LazyHolder不会被加载,只有在调用后才会被加载(实现了懒加载)

3.2.3 创建方法3-枚举

enum Singleton{
	INSTANCE; // 属性
	public void method1(){}
}

public static void main(String[] args) {
	Singleton lz1 = Singleton.INSTANCE;
	lz1.method1();
}

优点:

  • 懒加载
  • 线程安全
  • 反序列化

4 原型模式ProtoType

  • 当创建对象比较复杂,可以利用原型模式来简化创建过程
  • 不用重新创建,可以动态获取对象运行时的状态
  • 用原型实例指定创建对象的方式,通过拷贝这些圆形创建新对象,无需知道创建细节。即obj.clone()

例子:

  • Spring Bean

4.1 深拷贝与浅拷贝

浅拷贝:

  • 对于基本类型的数据变量,会创建一个全新的副本
  • 对于引用类型的变量,浅拷贝会采用引用传递
    深拷贝:
  • 复制所有基本类型变量
  • 对所有引用类型变量创建全新的副本

深拷贝可以通过:重写clone方法,或者使用序列化来实现

5 建造者模式

  • 将产品与产品的建造过程解耦==>建造者模式。例如盖房子(打地基、砌墙、封顶),盖平房、盖摩天大厦
  • 科技奖复杂的构建过程进行抽离,使得这个抽象过程的不同实现可以构造成不同的对象

例如:StringBuilder

你可能感兴趣的:(设计模式,设计模式)