抽象工厂模式——AbstractFactory

抽象工厂模式是工厂模式的升级版本,在有多个业务品种,业务分类时,通过抽象工厂模式产生需要的对象将更为高效。

案例展示——AbstractFactory怎样用?

 接着工厂方法模式那个案例,我们继续进行探索。考虑这样一种业务场景:有一天宝马汽车公司由于赚了大钱,财大气粗,打算把经营的不怎么样的奔驰公司给收购了,以达到拓展业务扩大生产规模的目的。好事成双,在扩大规模的同时,公司的科研部门很给力,设计出了一种高科技产品,希望将这种功能加在宝马车和奔驰车上。经过公司高层和科研部门的磨合洽谈,终于达成了一致性需求:在宝马X6和奔驰B系列车上加高科技产品,宝马X5和奔驰A系列上不加高科技产品。

分析: 我们该怎样设计我们的系统呢?工厂模式还能使用吗?假如只是生产奔驰系列汽车,ok,没有问题,可以直接抽象出一个接口,然后分别让BaomaCar和BenchiCar去实现,然后在工厂里面注册一下就行,因为都属于车这一个类别,没有其他的约束。但是现在问题的关键是要加一个层级:有没有加高科技产品,宝马车和奔驰车的一个系列要加高科技产品,另一个系列不加,显然这样的需求工厂方法模式没有办法完成。这时,我们就可以通过抽象工厂模式来完成这种分层级的需求,设计如下:

  • AbstractBenchiCar和AbstractBaomaCar是两个抽象类,分别封装了各自汽车的共同属性。

  • AbstractCarFactory是生产不同类型的汽车的抽象工厂

  • NewCarFactory和NonCarFactory继承了AbstractCarFactory,分别用于生产是否带有高科技的宝马车和奔驰车

类图设计如下:

image

代码实现如下:

//宝马车抽象类
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的定义

定义: 为创建一组相关或相互依赖的对象提供一个接口,而无需指定它们的具体类。抽象工厂模式的通用类图如下:

image

 抽象工厂的关键在于由于产品之间的层级关系形成了产品族。就如刚刚的案例一样,宝马车和奔驰车不是同一个类型的汽车,但是由于是否具备高科技产品这一约束条件从而形成了两个产品族:加了高科技产品的宝马X6和奔驰B,没有加高科技产品的宝马X5和奔驰A。下面是具有两个产品族的通用类图:

image

 从类图中我们可以得到:标有①和②的是分属不同类别的两个产品族。下面是这个类图的具体代码实现,可以作为一个通用模板。

//抽象产品类
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的优点和缺点

优点

  • 封装良好: 每个产品的实现类不需要高层模块操心,高层模块只需要知道对应的工厂就能得到需要的对象。

  • 产品族内的约束为非公开状态

缺点: 产品族扩展困难,就拿上面那个案例来说,假如研发部又研发出一项新技术,想要对其进行扩展,这时我们需要有多少改动呢?首先,这相当于多出了一个层级,需要在抽象工厂中进行注册,需要生成用一个对应的工厂,需要在各个汽车抽象类中声明,需要在实现类中实现,几乎对所有的类都进行了改造。

参考

《设计模式之禅》

猜你喜欢

转载自blog.csdn.net/king123456man/article/details/82692800
今日推荐