设计模式 (1): 5 种创建型模式 (结合代码详解)

发布时间 2023-10-08 23:35:44作者: 你好,一多

1 单例模式

需考虑的问题:

  • 是否线程安全
  • 是否延迟创建
  • 有无破坏单例的方法

饿汉单例

public class _01Eager {
    // 不延迟单例
    // 类初始化时创建单例
    private static final _01Eager instance = new _01Eager();
    private _01Eager(){}
    public static _01Eager getInstance(){
        return instance;
    }
}

懒汉单例

public class _02Lazyer {
    // 方法延迟单例
    // 相比于 饿汉式,把 instance 的创建
    // 从 类初始化时 移动到 方法调用时
    private static _02Lazyer instance;
    private _02Lazyer(){}
    public static synchronized _02Lazyer getInstance(){
        if(instance == null)
            instance = new _02Lazyer();
        return instance;
    }
}

双重检验单例

public class _03DoubleCheck {
    // 方法延迟单例
    // 相比 懒汉式,缩小锁粒度
    private static _03DoubleCheck instance;
    private _03DoubleCheck(){}
    public static _03DoubleCheck getInstance(){
        if(instance == null){
            synchronized (_03DoubleCheck.class){
                if(instance == null) {
                    instance = new _03DoubleCheck();
                }
            }
        }
        return instance;
    }
}

静态内部类单例

public class _04Static implements Serializable {
    private static class Static {
        private final static _04Static instance = new _04Static();
    }
    private _04Static(){}
    public static _04Static getInstance(){
        return Static.instance;
    }
}

破坏单例 (反射、反序列化)

(导入序列化工具依赖:org.apache.commons.commons-lang3

public class StaticAttack {
    StaticAttack(){}
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 测试 反射和反序列化 破坏 静态内部类
        staticAttack();
    }
    public static void staticAttack() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 单例对象
        _04Static obj = _04Static.getInstance();
        isSingleton(obj, _04Static.getInstance()); // true
        // 测试是否可以破坏单例
        _04Static newObj1, newObj2;
        // 反射创建 新对象 可以破坏单例
        Constructor<_04Static> constructor = _04Static.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        newObj1 = constructor.newInstance();
        isSingleton(obj, newObj1); // false
        // 反序列化创建 新对象 可以破坏单例
        byte[] serialize = SerializationUtils.serialize(obj);
        newObj2 = SerializationUtils.deserialize(serialize);
        isSingleton(obj, newObj2); // false
    }
    public static void isSingleton(Object obj1, Object obj2){
        System.out.println("是否是单例? " + (obj1 == obj2));
    }
}

枚举类单例

// 枚举类可以避免 反射 和 反序列化 破坏单例
public enum _05Enum {
    SINGLETON;
    // 单例的方法
    public String doSomething(){
        return "处理结束";
    }
}
// 调用单例的方法
_05Enum.SINGLETON.doSomething();

2 工厂模式

简单工厂模式

  • 消费者:依赖 商店
  • 商店:依赖 工厂,返回 具体产品
  • 工厂:if - else 地创建 具体产品
  • 产品:产品种类 通过 实现 很多抽象产品(接口)
public class sf {
    // 抽象产品类 Vehicle
    interface Vehicle {}
    // Vehicle 的 具体产品
    static class Car implements Vehicle {
        public String toString() {
            return "Car";
        }
    }
    static class Bike implements Vehicle {
        public String toString() {
            return "Bike";
        }
    }
    // 所有具体产品 都共用 抽象产品的工厂
    static class VehicleFactory {
        Vehicle createVehicle(String type){
            if(type == null)
                return null;
            Vehicle vehicle = null;
            if(type.equalsIgnoreCase("Car"))
                vehicle = new Car();
            else if(type.equalsIgnoreCase("Bike"))
                vehicle = new Bike();
            return vehicle;
        }
    }
}

工厂方法模式

public class fm {
    // 抽象产品类 Vehicle
    interface Vehicle {}
    // Vehicle 的 具体产品
    static class Car implements Vehicle {
        public String toString() {
            return "Car";
        }
    }
    static class Bike implements Vehicle {
        public String toString() {
            return "Bike";
        }
    }
    // Vehicle 的 抽象工厂
    static abstract class VehicleFactory {
        abstract Vehicle createVehicle();
    }
    // *继承* 抽象工厂
    // 一个具体产品 对应 一个具体工厂
    static class CarFactory extends VehicleFactory {
        Vehicle createVehicle(){
            return new Car();
        }
    }
    static class BikeFactory extends VehicleFactory {
        Vehicle createVehicle() {
            return new Bike();
        }
    }
}

3 抽象工厂模式

实现抽象工厂模式

public class af {
    // 抽象工厂用于产品族
    // 产品族 和 各自的抽象工厂
    interface Vehicle {}
    interface Accessory {}
    // interface Engine {} 产品族拓展的例子
    interface VehicleFactory {
        Vehicle createVehicle();
    }
    interface AccessoryFactory {
        Accessory createAccessory();
    }
    // interface EngineFactory { Engine createEngine();}

    // Vehicle 的 具体产品
    static class Car implements Vehicle {
        public String toString() {
            return "Car";
        }
    }
    static class Bike implements Vehicle {
        public String toString() {
            return "Bike";
        }
    }
    // Accessory 的具体产品
    static class CarAccessory implements Accessory {
        public String toString() {
            return "CarAccessory";
        }
    }
    static class BikeAccessory implements Accessory {
        public String toString() {
            return "BikeAccessory";
        }
    }
    // 每 *实现* 一个接口,产品族就拓展一类产品
    // 产品族工厂 实现了 多个接口,实现产品族的可拓展性
    static class CarFactory implements
            VehicleFactory, AccessoryFactory //,EngineFactory
    {
        public Vehicle createVehicle() {
            return new Car();
        }
        public Accessory createAccessory() {
            return new CarAccessory();
        }
    }
    static class BikeFactory implements
            VehicleFactory, AccessoryFactory //,EngineFactory
    {
        public Vehicle createVehicle() {
            return new Bike();
        }
        public Accessory createAccessory() {
            return new BikeAccessory();
        }
    }
}

对比三种工厂模式

| 简单工厂模式:
	 简单工厂
	/ if-else \ 
  A1           A2 

| 工厂方法模式:
      A 抽象工厂
      - 生产 A
     /  继承   \
 A1 具体工厂   A2 具体工厂
 - 生产 A1     - 生产 A2

| 抽象工厂模式:
	    (A,B...)抽象产品族工厂
		/           \
 A 抽象工厂(接口)   B 抽象工厂(接口)
 - 生产 A (接口)    - 生产 B (接口)
        \     	     /
      (A1, B1) 具体产品族工厂
	   - 生产 A1 (实现接口)
	   - 生产 B1 (实现接口)

可以看到,抽象工厂可以实现最复杂的功能,但是在简单情形下增加了复杂性

如何选择工厂方法和抽象工厂?

在实际应用中,需要根据具体的需求和场景选择合适的模式:

  • 如果产品种类较少,可以使用工厂方法模式
  • 如果产品种类较多,形成了产品族(并且 产品族 有可能 增删 产品),可以使用抽象工厂模式

4 建造者模式

5 原型模式