构建模式

简单工厂模式

一句话

简单工厂模式就是让一个工厂类承担构建所有对象的职责。调用者需要什么产品,让工厂生产出来即可。

缺点

示例

可以把create Apple 的复杂逻辑封装在工厂内

工厂方法模式

一句话

把一个大工厂拆成若干小工厂

优点

缺点

工厂太多

示例

苹果工厂:

public class AppleFactory {
    public Fruit create(){
        return new Apple();
    }
}

梨子工厂:

public class PearFactory {
    public Fruit create(){
        return new Pear();
    }
}

调用者:

public class User {
    private void eat(){
        AppleFactory appleFactory = new AppleFactory();
        Fruit apple = appleFactory.create();
        PearFactory pearFactory = new PearFactory();
        Fruit pear = pearFactory.create();
        apple.eat();
        pear.eat();
    }
}

抽象工厂模式

一句话

所有工厂都实现 IFactory 这个接口

Tip

抽象工厂模式适用于增加同类工厂这样的横向扩展需求,不适合新增功能这样的纵向扩展。因为接口新加一个方法会影响所有子类

优点

我们在创建时指定了具体的工厂类后,在使用时就无需再关心是哪个工厂类,只需要将此工厂当作抽象的 IFactory 接口使用即可。这种经过抽象的工厂方法模式被称作抽象工厂模式。

由于客户端只和 IFactory 打交道了,调用的是接口中的方法,使用时根本不需要知道是在哪个具体工厂中实现的这些方法,这就使得替换工厂变得非常容易。

缺点

缺点是抽象工厂模式太重了,如果 IFactory 接口需要新增功能,则会影响到所有的具体工厂类。使用抽象工厂模式,替换具体工厂时只需更改一行代码,但要新增抽象方法则需要修改所有的具体工厂类。

示例

public interface IFactory {
    Fruit create();
}

然后苹果工厂和梨子工厂都实现此接口:

public class AppleFactory implements IFactory {
    @Override
    public Fruit create(){
        return new Apple();
    }
}
public class PearFactory implements IFactory {
    @Override
    public Fruit create(){
        return new Pear();
    }
}

此时,调用者可以将 AppleFactory 和 PearFactory 统一作为 IFactory 对象使用,调用者 Java 代码如下:

public class User {
    private void eat(){
        IFactory appleFactory = new AppleFactory();
        Fruit apple = appleFactory.create();
        IFactory pearFactory = new PearFactory();
        Fruit pear = pearFactory.create();
        apple.eat();
        pear.eat();
    }
}

单例模式

某个对象全局只需要一个实例时,就可以使用单例模式。
两种实现方式:饿汉式和懒汉式。

优点

缺点

示例

建造模式

原型模式

类似JS的object,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

优点

缺点

Warning

注意浅拷贝和深拷贝

示例

奶茶:

public class MilkTea{
    public String type;
    public boolean ice;

    public MilkTea clone(){
        MilkTea milkTea = new MilkTea();
        milkTea.type = this.type;
        milkTea.ice = this.ice;
        return milkTea;
    }
}

下单:

private void order(){
    MilkTea milkTeaOfJay = new MilkTea();
    milkTeaOfJay.type = "原味";
    milkTeaOfJay.ice = false;
    
    MilkTea yourMilkTea = milkTeaOfJay.clone();
    
    // 一千位粉丝都调用 milkTeaOfJay 的 clone 方法即可
    ...
}

Reference

如何用「设计模式」制作珍珠奶茶? - 知乎 (zhihu.com)