【再探】设计模式— 工厂方法、单例及原型模式

发布于:2024-04-30 ⋅ 阅读:(25) ⋅ 点赞:(0)

 创建型设计模式是处理对象创建的设计模式,主要特点是“将对象的创建与业务代码分离”。一共有五种:工厂方法模式、单例模式、原型模式、抽象工厂模式及建造者模式。

1 单例模式

需求:

  1. 在整个系统中只需要一个实例。
  2. 管理共享资源,例如数据库连接、配置文件读取等,可以减少资源消耗,提高性能。

1.1 单例模式介绍

确保某个类只有一个实例,自行实例化并且向整个系统提供这个实例。

图 单例模式UML

饿汉模式

在程序启动时就进行对象的实例化,单例对象会在类被加载时创建。实现简单、线程安全。但是无法进行懒加载,会带来一定的系统开销。

懒汉模式

类加载时不会创建单例对象,而是等到真正需要的时候才创建。懒汉模式第一次调用时才初始化,避免了内存浪费,但是需要注意线程安全问题。

枚举

实现单例的最佳方法,自动支持序列化机制、防止多次实例化并且线程安全。

图 实现单例模式的方式

public class HungryModel {

    private HungryModel() {}

    private final static HungryModel instance = new HungryModel();

    public static HungryModel getInstance() {
        return instance;
    }
}
public class DoubleCheckLocking {

    private DoubleCheckLocking() {}

    private static DoubleCheckLocking instance = null;

    public static DoubleCheckLocking getInstance() {
        if (instance == null) {
            synchronized (DoubleCheckLocking.class) {
                if (instance == null) instance = new DoubleCheckLocking();
            }
        }
        return instance;
    }
}
public class IoDHSingleton {

    private IoDHSingleton() {}

    private static class Holder {
        static final IoDHSingleton instance = new IoDHSingleton();
    }

    public static IoDHSingleton getInstance() {
        return Holder.instance;
    }

}

1.1.1 优缺点

优点:确保一个类在系统中只有一个实例,节约系统资源,提高性能。

缺点:不符合单一职责原则。

2 原型模式

需求:

  1. 需要频繁创建属性近似的对象。
  2. 需要保持对象在某个时刻的状态。

2.1 原型模式介绍

通过一个已存在的对象克隆出多个一摸一样的对象。

图 原型模式UML

public class Address implements Cloneable{

    public Address() {}

    @Override
    public Address clone() throws CloneNotSupportedException {
        return (Address)super.clone();
    }

    @Override
    public String toString() {
        return "Address(" + Integer.toHexString(hashCode()) + ")";
    }
}

public class User implements Cloneable{

    private List<Address> addressList;

    public void setAddressList(List<Address> addressList) {
        this.addressList = addressList;
    }

    @Override
    public User clone() throws CloneNotSupportedException {
        User clone = (User)super.clone();
        if (addressList != null) {
            List<Address> newList = new ArrayList<>();
            for (Address address : addressList) {
                newList.add(address.clone());
            }
            clone.setAddressList(newList);
        }
        return clone;
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        User user = new User();
        List<Address> addresses = new ArrayList<>();
        addresses.add(new Address());
        addresses.add(new Address());
        user.setAddressList(addresses);

        User clone = user.clone();
        System.out.println(user);
        System.out.println(clone);
    }

    @Override
    public String toString() {
        return "User(" + Integer.toHexString(hashCode()) +"){" +
                "addressList=" + addressList +
                '}';
    }
}

2.1.1 优缺点

优点:1)减少了代码量;2)可读性、可维护性好,耦合度减小。

缺点:2)不符合单一职责原则;2)不符合开闭原则。当对象添加新的属性时可能需要修改代码。

3 工厂方法模式

需求:

  1. 将对象创建与业务代码剥离。
  2. 让用户在不需要知道具体的类型情况下,创建符合的对象。
  3. 隐藏创建这个实例的创建细节。

3.1 工厂方法模式介绍

将对象的创建与自身的业务逻辑分离。定义一个有创建对象接口的工厂,把创建对应产品的细节封装在不同的工厂实现类中。每增加新的产品,只需增加该产品以及对应的工厂实现类。

图 工厂方法模式UML

public class Car {

    private String engine;

    protected Car(String engine) {
        this.engine = engine;
    }
}

public class BMWCar extends Car{
    public BMWCar(String engine) {
        super(engine);
    }
}

public class TeslaCar extends Car{
    public TeslaCar(String engine) {
        super(engine);
    }
}

 

public interface CarFactory {
    Car buildCar();
}

public class BMWCarFactory implements CarFactory{
    @Override
    public Car buildCar() {
        return new BMWCar("汽油发动机");
    }
}

public class TeslaCarFactory implements CarFactory{
    @Override
    public Car buildCar() {
        return new TeslaCar("电动发动机");
    }
}
public class CarShop {
    public static void main(String[] args) {
        CarFactory carFactory = new BMWCarFactory();
        carFactory.buildCar();

        carFactory = new TeslaCarFactory();
        carFactory.buildCar();
    }
}

3.1.1 优缺点

优点:1)符合单一职责原则,可读性好。2)符合开闭原则,扩展性好。3)符合依赖倒置原则,耦合度降低。

缺点:类的数量增加,增加了系统的复杂性,可能会影响性能。