概述
抽象工厂模式(Abstract Factory
)就是对一组具有相同主题的工厂进行封装。抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产同一类(等级)的产品,而抽象工厂模式可生产多个类(等级)的产品。
例如:在生产奶茶过程中需要加入椰果或珍珠果,如果使用工厂方法模式,我们需要准备奶茶工厂、椰果工厂、珍珠果工厂。使用抽象工厂模式后,我们只需要一个工厂就是红茶工厂,该工厂涵盖了椰果工厂、珍珠果工厂需要做的事情。
模式由来
工厂方法模式考虑的是同一类产品。比如女朋友要喝的红茶、奶茶,但红茶的工厂只能生产红茶,奶茶的工厂只能生产奶茶,同理可以知道手机厂只能造手机,如畜牧场只养动物、电视机厂只生产电视机等。
也就是说工厂类只考虑生产同类的产品,并不能跨类生产。如果现在我有个需求,手机厂我能够生产电视怎么办,生活中这种综合型的生产商非常多,所以我应该要满足这样的需求,此时抽象工厂登场了。
产品等级
产品等级指的是不同厂商生产的同一类产品,比如手机:小米工厂生产的手机和华为工厂生产的手机不一样。在上述课程中我们学过红茶和绿茶就是相同的产品等级,他们就好比小米手机和华为手机的区别,如果只需要解决产品等级生产问题,那么使用工厂方法模式即可。
产品簇
同一个具体工厂所生产的位于不同类的一组产品称为一个产品族,比如:手机工厂生产的手机、电脑、电视。大米和电脑不能算作一个产品簇,因为他们之间没什么关系。上述中相同主题指的就是同一个产品簇。
工厂方法模式解决的范畴是产品等级(TCL空调,海尔空调)
抽象工厂模式解决的范畴是产品族等级(TCL电视机、TCL空调)
角色
- 抽象工厂(Creator)
该类为具体工厂的父类,主要用于规范描述具体工厂的公共接口
- 具体工厂(Concrete Creator)
被外界真正调用的类,实现工厂方法(
FactoryMethod
)创建产品的实例,包含若干个子工厂方法,如珍珠果方法,椰果方法,子工厂方法负责生产对应的具体子产品,所有具体子产品(椰果、珍珠果)组合成一个具体产品(如加珍珠果的椰果味红茶) - 抽象产品(Product)
该类为具体产品的父类,主要用于规范描述具体产品的公共接口
- 具体产品(Concrete Product)
工厂类创建的目标类,工厂创建出来的产品对象为该类的实例
案例分析
在前面工厂方法模式学习后,我们知道,红茶有专门的红茶机器、奶茶有专门的奶茶机器,女朋友想喝什么都可以。但突然有一天,女朋友想要在红茶中加入珍珠果或椰果,在奶茶中加入椰果和珍珠果怎么办?此时混入了其他产品,此时我们可以通过抽象工厂来解决。
创建抽象产品
//抽象产品1-茶 abstract class Tea { public abstract void drink(); } //抽象产品2-辅料食物 abstract class Food { public abstract void eat(); }
创建具体产品
//具体产品1-红茶 class RedTea extends Tea { public RedTea() { System.out.println("在制作红茶"); } @Override public void drink() { System.out.println("喝红茶"); } } //具体产品1-奶茶 class MilkTea extends Tea { public MilkTea() { System.out.println("在制作奶茶"); } @Override public void drink() { System.out.println("喝奶茶"); } } //具体产品2-珍珠果 class Pearl extends Food{ public Pearl() { System.out.println("在制作珍珠果"); } @Override public void eat() { System.out.println("吃珍珠果"); } } //具体产品2-椰果 class Coconut extends Food{ public Coconut() { System.out.println("在制作椰果"); } @Override public void eat() { System.out.println("吃椰果"); } }
创建抽象工厂
//抽象工厂,抽象工厂存放着产品簇(多个不同级)产品 abstract class AbstractFactory { public abstract Tea createTea(); public abstract Food createFood(); }
创建具体工厂
//红茶生产工厂-生产红茶和椰果 class RedTeaFactory extends AbstractFactory { @Override public Tea createTea() { return new RedTea(); } @Override public Food createFood() { return new Coconut(); } } //奶茶生产工厂-生产奶茶和珍珠果 class MilkTeaFactory extends AbstractFactory { @Override public Tea createTea() { return new MilkTea(); } @Override public Food createFood() { return new Pearl(); } }
请女朋友喝茶
public class GirlFriend { public static void main(String[] args) { RedTeaFactory redTeaFactory = new RedTeaFactory(); Tea redTea = redTeaFactory.createTea(); Food food1 = redTeaFactory.createFood(); System.out.print("女朋友开始"); redTea.drink(); food1.eat(); } }
抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。
- 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
- 当增加一个新的产品族时不需要修改原代码,满足开闭原则。
其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。
总结
无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。
所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。