抽象工厂模式
介绍
抽象工厂模式可以说是是工厂方法模式的升级版,当需要创建的产品有多个产品线(产品族)时,使用抽象工厂模式是比较好的选择。
简单地说就是工厂的工厂,抽象工厂可以创建具体工厂,由具体工厂来产生具体产品。
在抽象工厂模式中有如下角色:
- AbstractFactory:抽象工厂,它声明了用来创建不同产品的方法。
- ConcreteFactory:具体工厂,实现抽象工厂中定义的创建产品的方法。
- AbstractProduct:抽象产品,为每种产品声明业务方法。
- ConcreteProduct:具体产品,定义具体工厂生产的具体产品,并实现抽象产品中定义的业务方法。
代码实现
场景:
- 现在有2个产品族,一个水果,一个必需品
- 水果有2种,苹果,香蕉
- 必需品也有2种,大米,盐
- 工厂生产的东西必须包含一种水果,一种必需品
产品族
public interface AbstractFruit {
void produceFruit();
}
public interface AbstractNecessities {
void produceNecessities();
}
具体产品
// 具体产品1(苹果)
public class AppleA implements AbstractFruit{
@Override
public void produceFruit() {
System.out.println("抽象工厂...生产水果...apple...");
}
}
// 具体产品2(香蕉)
public class BananaA implements AbstractFruit {
@Override
public void produceFruit() {
System.out.println("抽象工厂...生产水果...banana...");
}
}
// 具体产品3(盐)
public class SaltA implements AbstractNecessities {
@Override
public void produceNecessities() {
System.out.println("抽象工厂...生产必需品...salt...");
}
}
// 具体产品4(大米)
public class RiceA implements AbstractNecessities {
@Override
public void produceNecessities() {
System.out.println("抽象工厂...生产必需品...rice...");
}
}
以上是纵向关系,苹果、香蕉继承于水果,盐、大米继承于必需品
现在构建工厂,首先一个父工厂(抽象工厂),然后两个具体工厂
// 定义 生产 产品工厂 的抽象工厂
public interface AbstractFactory {
AbstractFruit produceFruit();
AbstractNecessities produceNecessities();
}
2个具体工厂
// 具体工厂1号,本工厂职责:只生产苹果和盐
public class AppleAndSaltFactory implements AbstractFactory {
@Override
public AbstractFruit produceFruit() {
return new AppleA();
}
@Override
public AbstractNecessities produceNecessities() {
return new SaltA();
}
}
// 具体工厂2号,本工厂职责:只生产香蕉和大米
public class BananaAndRiceFactory implements AbstractFactory {
@Override
public AbstractFruit produceFruit() {
return new BananaA();
}
@Override
public AbstractNecessities produceNecessities() {
return new RiceA();
}
}
工厂的使用
public class AbstractClient {
public static void main(String[] args) {
AbstractFactory appleAndSaltFactory = new AppleAndSaltFactory();
appleAndSaltFactory.produceFruit().produceFruit();
appleAndSaltFactory.produceNecessities().produceNecessities();
AbstractFactory bananaAndRiceFactory = new BananaAndRiceFactory();
bananaAndRiceFactory.produceFruit().produceFruit();
bananaAndRiceFactory.produceNecessities().produceNecessities();
}
}
/* 运行结果
抽象工厂...生产水果...apple...
抽象工厂...生产必需品...salt...
抽象工厂...生产水果...banana...
抽象工厂...生产必需品...rice...
*/
抽象工厂的优缺点
优点
- 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。
- 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。
- 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
缺点
- 在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品。因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便
- 使用抽象工厂模式要求设计人员在设计之初就能够全面考虑,不会在设计完成之后向系统中增加新的产品等级结构,也不会删除已有的产品等级结构,否则将会导致系统出现较大的修改,为后续维护工作带来诸多麻烦。
小结(应用场景)
先看优缺点!
这个例子有点欠佳,看到这里,如果还不明白抽象工厂,接下来举一个进行扩展的例子,你应该就可以明白了。
1. 横向拓展易
如果增加新的具体工厂(就是所谓的产品族),比如,新增一个 只生产苹果和大米的工厂。
那么,不需要修改原有的代码,只需要新增一个工厂类 AppleAndRiceFactory implements AbstractFactory
即可。
2. 纵向扩展难
比如,新增一类产品 — 家电(相当于新增具体的产品)。
要想工厂具有生产家电的功能,就需要修改 AbstractFactory
的代码,新增加一个生产家电的方法,那么就需要重新构建所有实现了 AbstractFactory
接口的类,极为复杂。
简单工厂、工厂方法、抽象工厂区别
简单工厂 : 用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)
抽象工厂 :用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)
工厂设计模式