抽象工厂模式

现实中的工厂是一个生产产品的机构,这个工厂可以很大,产品品类非常丰富。我们作为工厂的客户,只需要告诉工厂我们需要什么就可以了,根本不关心工厂是怎么去生产的。

作为代码设计,我们也不希望知道对象是如何生成的,我们只想要一个对象罢了。

现在以汽车厂为例,我们知道汽车厂,像比亚迪这样的,既能生产汽车,又能生产电池。加入我们想要一个比亚迪的汽车,我们就可以告诉比亚迪工厂,我需要一辆比亚迪汽车,至于工厂里采购钢材,采购橡胶,那和我没有任何关系,我只是需要比亚迪汽车。

假设现在吉利也可以造汽车,但是不能造电池。那我需要一辆吉利汽车,也是没有问题的,只是不能在吉利买电池罢了。

不管是比亚迪还是吉利,都是工厂;不管是比亚迪汽车还是吉利汽车,都是汽车;不管是比亚迪电池还是吉利电池,都是电池。

这样我们就能抽象出三个概念来:工厂,汽车和电池。

未来,如果需要特斯拉电池或者汽车,只需要新建一个特斯拉厂就可以了。

下面看看如何利用代码去实现。

  1. 首先定义一个抽象产品Battery:
package factory;

public abstract class Battery {
    private String core;

    public Battery(String core) {
        this.core = core;
    }

    public void desc() {
        System.out.println("本电池采用了" + core + "电芯");
    };
}
  1. 然后定义一个抽象类Car:
package factory;

public abstract class Car {
    private String engine;

    private String wheels;

    public Car(String engine, String wheels) {
        this.engine = engine;
        this.wheels = wheels;
    }

    public void desc() {
        System.out.println("这辆车采用了" + engine + "引擎,装配了" + wheels + "轮胎!");
    }
}
  1. 定义抽象工厂:
package factory;

import java.lang.reflect.InvocationTargetException;

//工厂有生产汽车和自行车的能力
public abstract class Factory {

    public static Factory getFactory(String factoryName) {
        Factory factory = null;
        try {
            factory = (Factory) Class.forName(factoryName).getDeclaredConstructor().newInstance();
        } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException
                | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return factory;
    }
    public abstract Car createCar(String engine, String wheels);

    public abstract Battery createBattery(String core);
}

抽象工厂用到了反射的办法去生成具体工厂,这样扩展性比较强,未来新增任何工厂,都不用修改抽象工厂类。

  1. 定义具体的产品:

BydCar.java

package factory;

public class BydCar extends Car {
    private String engine;

    private String wheels;

    public BydCar(String engine, String wheels) {
        super(engine, wheels);
        this.engine = engine;
        this.wheels = wheels;
    }

    @Override
    public void desc() {
        System.out.println("比亚迪汽车采用自研" + engine + "发动机,使用" + wheels + "轮胎。");
    }
}

BydBattery.java

package factory;

public class BydBattery extends Battery {
    private String core;

    public BydBattery(String core) {
        super(core);
        this.core = core;
    }

    @Override
    public void desc() {
        super.desc();
    }
}

GellyCar.java

package factory;

import java.util.StringJoiner;

public class GellyCar extends Car {
    private String engine;

    private String wheels;

    public GellyCar(String engine, String wheels) {
        super(engine, wheels);
        this.engine = engine;
        this.wheels = wheels;
    }

    @Override
    public void desc() {
        System.out.println("吉利汽车采用自研发动机:" + engine + ",使用" + wheels + "轮胎。");
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", GellyCar.class.getSimpleName() + "[", "]")
                .add("engine='" + engine + "'")
                .add("wheels='" + wheels + "'")
                .toString();
    }
}
  1. 定义具体工厂:

BydFactory.java

package factory;

public class BydFactory extends Factory {

    @Override
    public Car createCar(String engine, String wheels) {
        return new BydCar(engine, wheels);
    }

    @Override
    public Battery createBattery(String core) {
        return new BydBattery(core);
    }
}

GeelyFactory.java

package factory;

public class GeelyFactory extends Factory {
    @Override
    public Car createCar(String engine, String wheels) {
        return new GellyCar(engine, wheels);
    }

    @Override
    public Battery createBattery(String core) {
        return null;
    }
}

到现在为止,所有的类都已经定义好了。下面就是具体的使用了:

package factory;

public class Main {
    public static void main(String[] args) {
        //新建一个比亚迪的工厂
        Factory bydFactory = Factory.getFactory("factory.BydFactory");
        //生产比亚迪汽车和电池
        Car bydCar = bydFactory.createCar("B3", "邓禄普");
        bydCar.desc();
        Battery bydBattery = bydFactory.createBattery("三洋");
        bydBattery.desc();

        //新建一个吉利工厂
        Factory geelyFactory = Factory.getFactory("factory.GeelyFactory");
        Car geelyCar = geelyFactory.createCar("G1", "固特异");
        geelyCar.desc();
    }
}

这段代码打印如下:

比亚迪汽车采用自研B3发动机,使用邓禄普轮胎。
本电池采用了三洋电芯
吉利汽车采用自研发动机:G1,使用固特异轮胎。

工厂模式的好处是显而易见的,我们根本不需要关注生产的细节,使用者只需要提供一些原材料就可以了,至于原材料如何组织,那是工厂的事情。还有一点就是添加一个新工厂很容易。

但是工厂模式的缺点也是明显的,就是难以增加新的零件,比如要给汽车生产加一个零件——挡风玻璃——就很难,得要通盘修改。而且实现的具体工厂越多,修改难度就越大。

你可能感兴趣的:(抽象工厂模式)