背景

当我们需要一辆自行车时,我们不需要关心这辆车是如何制造的;只需要知道自己要买的是什么,然后由工厂制作并提供给我们。

同样,在我们的软件编程中,如果有一个类实例需要在许多地方被创建和初始化,且实例的初始化比较复杂,那么我们也可以用“工厂”的思维来设计我们的代码

这样做会有什么样的好处呢?
首先,我们创建对象,只需要知道对象的名字;
然后,我并不需要知道对象的具体实现,我只需要了解这个对象提供了什么接口。

简单工厂模式

简单工厂模式:通过工厂类来创建对象,并且根据传入的参数来决定产品的类型。
代码示例

public interface ICar {
    void show();
}

public class ACar implements ICar {
    @Override
    public void show() {
        System.out.println("这是A车");
    }
}

public class BCar implements ICar {
    @Override
    public void show() {
        System.out.println("这是B车");
    }
}

public class CarFactory {

    public ICar buyCar(String carType){
        ICar iCar = null;
        if("A车".equals(carType)){
            iCar = new ACar();
        }else if("B车".equals(carType)){
            iCar = new BCar();
        }
        return iCar;
    }
}

public class SimpleFactoryTest {

    public static void main(String[] args) {
        CarFactory carFactory = new CarFactory();
        ICar aCar = carFactory.buyCar("A车");
        ICar bCar = carFactory.buyCar("B车");
        aCar.show();
        bCar.show();
    }
}

运行结果
在示例中,我们简单的创建了一个ICar接口,并新建了A车、B车两个产品;
由CarFactory类来根据不同的产品名称,生成不同的产品对象。

缺点:如果要新增产品,那么势必要修改工厂类中的创建方法(buyCar方法,增加新的if-else判断),这明显不符合我们的开闭原则(对扩展开放,对修改关闭)。

工厂方法模式

工厂方法模式:每个产品子类对应一个工厂子类,利用多态特性动态创建对象。
代码示例(仅重写工厂类代码)

public interface ICarFactory {
    ICar buyCar();
}

public class ACarFactory implements ICarFactory {
    @Override
    public ICar buyCar() {
        ICar aCar = new ACar();
        return aCar;
    }
}

public class BCarFactory implements ICarFactory {
    @Override
    public ICar buyCar() {
        ICar bCar = new BCar();
        return bCar;
    }
}

public class FactoryMethodTest {
    public static void main(String[] args) {
        ICarFactory aCarFactory = new ACarFactory();
        ICar aCar = aCarFactory.buyCar();
        aCar.show();
    }
}

运行结果
在示例中,我们创建了一个工厂的接口,并为每个产品分别建立工厂子类;
这样做的好处是:
1.我们想要创建什么的产品对象,只需要实例化该产品的工厂子类,并调用创建方法,不需要传任何的参数;
2.在业务增长过程中,需要新的产品,我们只需要新增产品子类与工厂子类即可。

抽象工厂模式

背景
在使用工厂方法模式时,如果你的产品非常的多,那么你的系统会变得非常的复杂;
在我们之前的示例中,存在着A车、B车,那么如果后面又有了A飞机、B飞机、A船、B船...我们应该怎么来设计我们的代码呢?

我们应当对这些产品进行一个分组。
可以是横向的,也可以是纵向的;可以是分为A工厂,B工厂;也可以是车、飞机、船。

代码示例

public interface ICar {
    void show();
}

public class ACar implements ICar {
    @Override
    public void show() {
        System.out.println("这是A车");
    }
}

public interface IAircraft {
    void show();
}

public class AAirCraft implements IAircraft {

    @Override
    public void show() {
        System.out.println("这是A飞机");
    }
}

public interface IFactory {
    ICar buyCar();

    IAircraft buyAirCraft();
}

public class AFactory implements IFactory {
    @Override
    public ICar buyCar() {
        ICar acar = new ACar();
        return acar;
    }

    @Override
    public IAircraft buyAirCraft() {
        IAircraft aaircraft = new AAirCraft();
        return aaircraft;
    }
}

public class AbstractFactoryTest {
    public static void main(String[] args) {
        IFactory aFactory = new AFactory();
        ICar aCar = aFactory.buyCar();
        IAircraft aircraft = aFactory.buyAirCraft();
        aCar.show();
        aircraft.show();
    }
}

运行结果
在示例中,我们分别创建了A飞机、A车两个产品子类,并新建AFactory类来对A品牌的产品进行创建以及初始化。

总结

简单工厂模式:
有唯一的工厂类,工厂类的创建方法根据传入的参数进行判断(if-else),来决定创建什么样的产品对象。(违反了开闭原则)
工厂方法模式:
多个工厂类实现工厂接口,利用堕胎来创建不同的产品对象。(产品过多,会使得系统越来越复杂)
抽象工厂模式:
抽象工厂模式把产品子类进行分组,同组中的不同产品由同一个工厂子类的不同方法负责创建,从而减少了工厂子类的数量。

注:工厂方法模式和抽象工厂模式都属于创建型模式。




最近看到小灰大大发了工厂模式的漫画,顺便复习了一下并做了一个学习笔记~

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

一个喜欢拔刀的萌新Coder