创建者模式
抽象工厂模式
概念
抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这是很多地方对于抽象工厂模式的描述,说实话感觉不是特别好懂。
按我的理解,用大白话讲,就是定义一套工厂的规范,按照这套规范可以创建很多的工厂,生产出不同的产品。
我们拿牛马人生公司为例。
假如苹果公司找到了牛马人生公司,跟牛马人生公司说,你帮我代加工生产手机和汽车等等一系列苹果公司的产品,但是要求生产苹果产品的工厂内必须只能生产苹果公司的产品。
牛马人生公司满口答应,多大点事对吧。
第二天,又有一个雪梨公司也找到了牛马人生公司,也要求代加工雪梨公司的产品,要求跟苹果公司一样。
牛马人生公司想了想也同意了。
牛马人生公司找到了工厂设计人员,总工程师想了想,苹果公司跟雪梨公司生产的产品都是一样的,何不设计一套工厂的规范,按照此工厂规范建造的工厂,就能满足苹果、雪梨这类的科技公司,后面还有什么西瓜公司、南瓜公司,也都可以按照这套规范来建造工厂。
于是乎,工厂创建规范出炉了,规范定义了,必须要有手机生产流水线、汽车组装流水线等等。
这一套定义工厂创建规范,并按照规范创建工厂,生产对应产品的思路就是抽象工厂模式。
实现步骤
下面我们用代码来表示这个逻辑。
-
首先我们定义了一个抽象类
AbstractFactory
,用来表示工厂的创建规范,如下面的代码所示,我们定义了这一类的工厂,必须要有生产手机和汽车的能力。规范里并没有告诉工厂要怎么生产产品,这些在具体的工厂中去完成。/** * 抽象工厂。 * 抽象工厂里定义了这个工厂所能获取的所有产品(对象)。具体创建这些产品的行为在子类中实现。 * * @author wanggt * @date 2023-06-17 11:19:21 */ public abstract class AbstractFactory { /** * 生产手机。 * * @param model 型号 * * @author wanggt * @date 2023-06-17 11:22:34 */ public abstract Phone producePhone(String model); /** * 生产汽车。 * * @param color 颜色 * * @author wanggt * @date 2023-06-17 11:26:02 */ public abstract Car produceCar(String color); }
-
我们的规范中除了定义了工厂的规范,还简单地定义了生产出来的产品有什么功能。例如,手机得可以打电话吧,汽车得能走吧。这些功能可能不同的公司实现的方式不同,比如有些汽车用油,有些汽车用电。规范里不管,我只说明,得有这个功能,才能叫做汽车。
/** * 手机的接口定义。 * * @author wanggt * @date 2023-06-17 11:26:37 */ public interface Phone { /** * 拨打电话。 * * @author wanggt * @date 2023-06-17 11:27:28 */ void call(String targetNum); }
/** * 汽车的接口定义。 * * @author wanggt * @date 2023-06-17 11:27:45 */ public interface Car { /** * 往前冲。 * * @author wanggt * @date 2023-06-17 11:28:28 */ void run(); }
-
现在开始按照规范来打造工厂了。苹果工厂中手机流水线生产出来的手机是苹果手机
ApplePhone
,汽车流水线生产出来的是苹果汽车AppleCar
。/** * 苹果工厂。 * * @author wanggt * @date 2023-06-17 11:29:43 */ public class AppleFactory extends AbstractFactory { @Override public Phone producePhone(String model) { return new ApplePhone(model); } @Override public Car produceCar(String color) { return new AppleCar(color); } }
/** * 苹果手机 * * @author wanggt * @date 2023-06-17 11:32:44 */ public class ApplePhone implements Phone { private final String model; public ApplePhone(String model) { this.model = model; } @Override public void call(String targetNum) { System.out.println("你好,我是苹果手机,型号 " + model + ",你是" + targetNum); } }
/** * 苹果汽车 * * @author wanggt * @date 2023-06-17 16:57:03 */ public class AppleCar implements Car { private final String color; public AppleCar(String color) { this.color = color; } @Override public void run() { System.out.println("我是苹果汽车,我百公里加速1秒"); } }
-
按照规范打造了雪梨工厂,雪梨工厂中手机流水线生产出来的手机是雪梨手机
PearPhone
,汽车流水线生产出来的是雪梨汽车PearCar
。/** * 雪梨工厂。 * * @author wanggt * @date 2023-06-17 11:30:21 */ public class PearFactory extends AbstractFactory { @Override public Phone producePhone(String model) { return new PearPhone(model); } @Override public Car produceCar(String color) { return new PearCar(color); } }
public class PearPhone implements Phone { private final String model; public PearPhone(String model) { this.model = model; } @Override public void call(String targetNum) { System.out.println("你好,我是雪梨手机,型号 " + model + ",你是" + targetNum); } }
public class PearCar implements Car { private final String color; public PearCar(String color) { this.color = color; } @Override public void run() { System.out.println("我是雪梨汽车,百公里加速100秒"); } }
-
苹果公司看到雪梨公司也建了一个跟他一样的公司,这还得了,立马联系上了牛马人生公司的商务部门,要求多增加一套苹果工厂。牛马人生公司的商务部门向高层领导投诉,设计部门写的规范太难懂了,这不是他们商务部门要去研究的东西。这个时候,设计部门给商务部门提供了一套规则。如果是
apple
公司,就创建AppleFactory
工厂,如果是pear
公司,就创建PearFactory
工厂。商务很满意,设计这么简单,这不是有手就行。public class FactoryProducer { /** * 获取工厂。 * * @param company 公司 * * @author wanggt * @date 2023-06-17 14:11:05 */ public static AbstractFactory getFactory(String company) { if ("apple".equalsIgnoreCase(company)) { return new AppleFactory(); } else if ("pear".equalsIgnoreCase(company)) { return new PearFactory(); } else { return null; } } }
-
工厂红红火火开工了,工厂建好之后,又试运行了下流水线,一台台手机,一辆辆汽车从工厂里生产出来,总设计师感到很满足。终于又为公司干了点实事,今年的裁员应该轮不到他了吧。
public class AbstractFactoryPatternDemo { public static void main(String[] args) { // 创建一个苹果公司的工厂,并生产对应的产品 AbstractFactory appleFactory = FactoryProducer.getFactory("apple"); Phone phone = appleFactory.producePhone("11"); phone.call("1234567890"); Car appleCar = appleFactory.produceCar("白色"); appleCar.run(); System.out.println("===================="); // 创建一个雪梨公司的工厂,并生产对应的产品 AbstractFactory pearFactory = FactoryProducer.getFactory("pear"); Phone pearPhone = pearFactory.producePhone("30"); pearPhone.call("12343453464562"); Car pearCar = pearFactory.produceCar("黄色"); pearCar.run(); } }
你好,我是苹果手机,型号 11,你是1234567890 我是苹果汽车,我百公里加速1秒 ==================== 你好,我是雪梨手机,型号 30,你是12343453464562 我是雪梨汽车,百公里加速100秒
优缺点分析
我们现在来分析下总工程师设计的这一套工厂创建规范。
优点就是按照这套工厂创建规范打造出来的工厂,生产出来的产品都是同一个产品族的,要么都是苹果公司的产品,要么都是雪梨公司的产品。进入苹果工厂,闭着眼睛也能知道,里面生产的全部苹果公司的产品。手机必定是苹果手机,而不可能是雪梨手机。
而且接下来如果有类似的公司找到牛马人生公司的时候,完全可以按照这套工厂创建规范,再创建一个西瓜工厂即可。
但是缺点也是有的。总工程师摸了摸下巴,没有告诉其他人这个缺点。
那就是假如以后苹果公司增加了一些产品,例如苹果飞机,那必然就要修改工厂创建规范。修改了工厂创建规范之后,还得去扩建苹果工厂,去增加这个流水线。
但是雪梨公司并不会生产飞机,那么这个时候,雪梨工厂里面出现了一点问题,雪梨工厂里面有为生产飞机的预留位置,实际上并不会生产飞机,这多少让雪梨公司的人不爽。因为那为生产飞机预留的位置,似乎一直在提醒他们,你雪梨公司就是比苹果公司差。