抽象工厂模式是工厂模式的升级版本,在有多个业务品种,业务分类时,通过抽象工厂模式产生需要的对象将更为高效。
案例展示——AbstractFactory怎样用?
接着工厂方法模式那个案例,我们继续进行探索。考虑这样一种业务场景:有一天宝马汽车公司由于赚了大钱,财大气粗,打算把经营的不怎么样的奔驰公司给收购了,以达到拓展业务扩大生产规模的目的。好事成双,在扩大规模的同时,公司的科研部门很给力,设计出了一种高科技产品,希望将这种功能加在宝马车和奔驰车上。经过公司高层和科研部门的磨合洽谈,终于达成了一致性需求:在宝马X6和奔驰B系列车上加高科技产品,宝马X5和奔驰A系列上不加高科技产品。
分析: 我们该怎样设计我们的系统呢?工厂模式还能使用吗?假如只是生产奔驰系列汽车,ok,没有问题,可以直接抽象出一个接口,然后分别让BaomaCar和BenchiCar去实现,然后在工厂里面注册一下就行,因为都属于车这一个类别,没有其他的约束。但是现在问题的关键是要加一个层级:有没有加高科技产品,宝马车和奔驰车的一个系列要加高科技产品,另一个系列不加,显然这样的需求工厂方法模式没有办法完成。这时,我们就可以通过抽象工厂模式来完成这种分层级的需求,设计如下:
AbstractBenchiCar和AbstractBaomaCar是两个抽象类,分别封装了各自汽车的共同属性。
AbstractCarFactory是生产不同类型的汽车的抽象工厂
NewCarFactory和NonCarFactory继承了AbstractCarFactory,分别用于生产是否带有高科技的宝马车和奔驰车
类图设计如下:
代码实现如下:
//宝马车抽象类
public abstract class AbstractBaomaCar {
public abstract void getColor();
public abstract void getPrice();
//是否具有新科技
public abstract void getNew();
//模板方法
public void run(){
this.getColor();
this.getPrice();this.getNew();
}
}
//没加高科技的宝马车:X5
public class NonBaomaX5 extends AbstractBaomaCar {
public void getColor() {
System.out.println("我是宝马X5系列,我是宝石红。。。");
}
public void getPrice() {
System.out.println("我要卖40w。。。");
}
public void getNew() {
System.out.println("我是宝马X6系列,我没有加新科技。。。");
}
}
//加了高科技的宝马车:X6
public class NewBaomaX6 extends AbstractBaomaCar {
public void getColor() {
System.out.println("我是宝马X6系列,我是宝石黑。。。");
}
public void getPrice() {
System.out.println("我要卖60w。。。");
}
public void getNew() {
System.out.println("我是宝马X6系列,我加了新科技。。。");
}
}
//奔驰车抽象类
public abstract class AbstractBenchiCar{
public abstract void getColor();
public abstract void getPrice();
//是否具有新科技
public abstract void getNew();
//模板方法
public void run(){
this.getColor();
this.getPrice();
this.getNew();
}
}
//没加高科技的奔驰车:A
public class NonBenchiA extends AbstractBenchiCar {
public void getColor() {
System.out.println("我是奔驰A系列,我是高原红。。。");
}
public void getPrice() {
System.out.println("我要卖160w。。。");
}
public void getNew() {
System.out.println("我是奔驰A系列,我没有加新科技。。。");
}
}
//加了高科技的奔驰车:B
public class NewBenchiB extends AbstractBenchiCar {
public void getColor() {
System.out.println("我是奔驰B系列,我是宝石蓝。。。");
}
public void getPrice() {
System.out.println("我要卖70w。。。");
}
public void getNew() {
System.out.println("我是奔驰B系列,我加了新科技。。。");
}
}
//汽车生产工厂
public abstract class AbstractCarFactory {
//生产宝马系列车
public abstract AbstractBaomaCar createBaomaCar();
//生产奔驰系列车
public abstract AbstractBenchiCar createBenchiCar();
}
//生产加了高科技的汽车
public class NewCarFactory extends AbstractCarFactory {
//只生产加了新科技的宝马车
public AbstractBaomaCar createBaomaCar() {
return new NewBaomaX6();
}
//只生产加了新科技的奔驰车
public AbstractBenchiCar createBenchiCar() {
return new NewBenchiB();
}
}
//生产没加高科技的汽车
public class NonCarFactory extends AbstractCarFactory {
//只生产没有加新科技的宝马车
public AbstractBaomaCar createBaomaCar() {
return new NonBaomaX5();
}
//只生产没有加新科技的奔驰车
public AbstractBenchiCar createBenchiCar() {
return new NonBenchiA();
}
}
在一个场景中运行代码:
public class Client {
public static void main(String[] args) {
//定义出两个工厂
AbstractCarFactory factory1 = new NonCarFactory();
AbstractCarFactory factory2 = new NewCarFactory();
//生产没有新科技的宝马车:X5
System.out.println("生产宝马X5,没有新科技。。。");
AbstractBaomaCar x5 = factory1.createBaomaCar();
//生产没有新科技的奔驰车:A
System.out.println("生产奔驰A,没有新科技。。。");
AbstractBenchiCar A = factory1.createBenchiCar();
//生产有新科技的宝马车:X6
System.out.println("生产宝马X6,有新科技。。。");
AbstractBaomaCar x6 = factory2.createBaomaCar();
//生产有新科技的奔驰车:B
System.out.println("生产奔驰B,有新科技。。。");
AbstractBenchiCar B = factory2.createBenchiCar();
System.out.println("==============Show Time==============");
x5.run();
System.out.println("=============");
A.run();
System.out.println("=============");
x6.run();
System.out.println("=============");
B.run();
}
}
//结果如下:
生产宝马X5,没有新科技。。。
生产奔驰A,没有新科技。。。
生产宝马X6,有新科技。。。
生产奔驰B,有新科技。。。
==============Show Time==============
我是宝马X5系列,我是宝石红。。。
我要卖40w。。。
我是宝马X6系列,我没有加新科技。。。
=============
我是奔驰A系列,我是高原红。。。
我要卖160w。。。
我是奔驰A系列,我没有加新科技。。。
=============
我是宝马X6系列,我是宝石黑。。。
我要卖60w。。。
我是宝马X6系列,我加了新科技。。。
=============
我是奔驰B系列,我是宝石蓝。。。
我要卖70w。。。
我是奔驰B系列,我加了新科技。。。
回归本源——什么是AbstractFactory?
AbstractFactory的定义
定义: 为创建一组相关或相互依赖的对象提供一个接口,而无需指定它们的具体类。抽象工厂模式的通用类图如下:
抽象工厂的关键在于由于产品之间的层级关系形成了产品族。就如刚刚的案例一样,宝马车和奔驰车不是同一个类型的汽车,但是由于是否具备高科技产品这一约束条件从而形成了两个产品族:加了高科技产品的宝马X6和奔驰B,没有加高科技产品的宝马X5和奔驰A。下面是具有两个产品族的通用类图:
从类图中我们可以得到:标有①和②的是分属不同类别的两个产品族。下面是这个类图的具体代码实现,可以作为一个通用模板。
//抽象产品类
public abstract class AbstractProductA {
//每个产品共有的方法
public void sharedMethod(){
//业务逻辑
}
//每个业务共有方法,不同实现
public abstract class doSomething();
}
//产品A1的实现类
public class ProductA1 extends AbstractProductA {
public void doSomething() {
//业务逻辑
}
}
//产品A2的实现类
public class ProductA2 extends AbstractProductA {
public void doSomething() {
//业务逻辑
}
}
//抽象工厂类
public abstract class AbstractCreator {
//创建A产品家族
public abstract AbstractProductA createProductA();
//创建B产品家族
public abstract AbstractProductB createProductB();
}
//产品等级1的实现类
public class Creator1 extends AbstractCreator {
//只生产产品等级为1的A产品
public AbstractProductA createProductA() {
return new ProductA1();
}
//只生产产品等级为1的B产品
public AbstractProductB createProductB() {
return new ProductB1();
}
}
//产品等级1的实现类
public class Creator2 extends AbstractCreator {
//只生产产品等级为2的A产品
public AbstractProductA createProductA() {
return new ProductA2();
}
//只生产产品等级为2的B产品
public AbstractProductB createProductB() {
return new ProductB2();
}
}
//场景类
public class Client {
public static void main(String[] args) {
//定义两个工厂
AbstractCreator creator1 = new Creator1();
AbstractCreator creator2 = new Creator2();
//生产A1对象
AbstractProductA a1 = creator1.createProductA();
//生产A2对象
AbstractProductA a2 = creator2.createProductA();
//生产B1对象
AbstractProductB b1 = creator1.createProductB();
//生产B2对象
AbstractProductB b2 = creator2.createProductB();
//业务逻辑
}
}
AbstractFactory的优点和缺点
优点
封装良好: 每个产品的实现类不需要高层模块操心,高层模块只需要知道对应的工厂就能得到需要的对象。
产品族内的约束为非公开状态
缺点: 产品族扩展困难,就拿上面那个案例来说,假如研发部又研发出一项新技术,想要对其进行扩展,这时我们需要有多少改动呢?首先,这相当于多出了一个层级,需要在抽象工厂中进行注册,需要生成用一个对应的工厂,需要在各个汽车抽象类中声明,需要在实现类中实现,几乎对所有的类都进行了改造。
参考
《设计模式之禅》