上篇文章讲到了对工厂方法模式进行变化后带来的缺陷,而为了解决工厂方法模式所带来的缺陷,从而引出了抽象工厂模式。
在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法具有唯一性。一般情况下,一个具体工厂中只有一个或者一组重载的工厂方法。但是有时候我们希望一个工厂可以提供多个产品对象,而不是单一的产品对象,如一个电器工厂,它可以生产电视机、电冰箱、空调等多种电器,而不是只生产某一种电器。为了更好地理解抽象工厂模式,先引入两个概念:
- 产品等级:就好比一个抽象类是手机,其子类有苹果、小米、华为,而抽象类手机与具体品牌的手机之间就构成了一个产品等级结构
- 产品簇:产品簇是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如苹果工厂生产的苹果手机、苹果电脑,苹果手机位于手机产品等级结构中,苹果电脑位于电脑产品等级结构中,苹果手机和苹果电脑就构成了一个产品簇
三、抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂来创建其他工厂,该超级工厂又称为其他工厂的工厂。它提供了一种创建对象的最佳方式
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象
抽象工厂模式可以理解为将简单工厂模式和工厂方法模式进行整合。从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)
简单理解:工厂方法模式的工厂是产品等级工厂,因为它们只创建产品等级。就好比手机工厂它只负责创建手机。而在抽象工厂模式中的工厂则是产品簇工厂,它们负责创建产品簇,就好比苹果工厂,它会创建手机、电脑等
/* ----------------------- 服务端 ----------------------- */
/**
* 食物抽象产品
*/
interface Food {
void production();
}
/**
* 具体产品
*/
class HanBao implements Food {
@Override
public void production() {
System.out.println("生产的汉堡包咯");
}
}
class Xiaolongxia implements Food {
@Override
public void production() {
System.out.println("生产的小龙虾咯");
}
}
/**
* 添加产品等级
* 喝的抽象产品
*/
interface Drink {
public void drink();
}
class Cola implements Drink {
@Override
public void drink() {
System.out.println("可乐好喝。。");
}
}
class Beer implements Drink {
@Override
public void drink() {
System.out.println("夏天喝啤酒最爽了。。");
}
}
/*
* 抽象工厂
*/
interface Factory {
public Food getFood();
public Drink getDrink();
}
/**
* 宵夜工厂
*/
class XiaoYeFactory implements Factory {
@Override
public Food getFood() {
return new Xiaolongxia();
}
@Override
public Drink getDrink() {
return new Beer();
}
}
/**
* KFC 工厂
*/
class KFCFactory implements Factory {
@Override
public Food getFood() {
return new HanBao();
}
@Override
public Drink getDrink() {
return new Cola();
}
}
/* ----------------------- 服务端 ----------------------- */
这个时候如果要增加产品等级,我们只需要新增工厂类和产品类即可
使用场景: QQ 换皮肤,一整套一起换。 生成不同操作系统的程序
抽象工厂模式的优点
抽象工厂模式的缺点
- 产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的工厂里加代码,又要在具体的工厂里面加代码,这样就违反了设计原则中的开封原则
总结
- 产品等级比较固定,考虑抽象工厂模式
- 产品等级经常变化则不建议抽象工厂模式
- 产品等级少则建议工厂方法模式
- 工厂模式的意义
将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系解耦,从而提高项目的扩展性和维护性 - 设计模式的 “依赖抽象” 原则
创建对象实例时,不要直接 new,而是把这个 new 的动作放在一个工厂的方法中并返回,还有的说法是变量不要直接持有具体类的引用- 不要让类继承具体类,而是继承抽象类或者是实现接口,因为接口比具体类更稳定
- 不要覆盖基类中已经实现的方法
- 创建型模式对于调用者来说,隐藏了复杂的逻辑处理过程, 流水线生产