抽象工厂模式

抽象工厂模式

说到抽象工厂模式前,首先需要理解两个概念,一个是产品等级,一个是产品族

产品等级

产品等级结构即产品的继承结构,如一个抽象类是键盘,其子类有狼蛛键盘、雷柏键盘、联想键盘,则抽象键盘与具体品牌的键盘之间构成了一个产品等级结构,抽象键盘是父类,而具体品牌的键盘是其子类。也就是说具有共同父类的对象为一个产品等级

产品族

产品族是指由*同一个工厂生产的,位于不同产品等级结构中的一组产品。如小米工厂生产的小米手机、小米电视,小米手机位于手机产品等级结构中,小米电视位于电视产品等级结构中,小米手机、小米电视构成了一个产品族。通俗的说就是,同一家工厂生产出来的不同产品等级构成一个产品族

抽象工厂与工厂模式的区别

工厂方法模式:一个抽象产品类,可以派生出多个具体产品类。
  一个抽象工厂类,可以派生出多个具体工厂类。
  每个具体工厂类只能创建一个具体产品类的实例
抽象工厂模式:多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
  一个抽象工厂类,可以派生出多个具体工厂类。
  每个具体工厂类可以创建多个具体产品类的实例

区别:工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。

定义

抽象工厂模式(Abstract Factory Pattern) 是一种比较常用的模式, 其定义如下:
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
翻译过来就是:为创建一组相关或相互依赖的对象提供一个接口, 而且无须指定它们的具体类。

类图结构

这里写图片描述
由类图可以看到,抽象工厂有两个子类,都实现了父类的createProudctA和createProductB两个方法,工厂1生产的A和B为一个产品族,工厂2生产的A和B又是另一个产品组,而A1和A2又是同一个产品等级

代码实现

假设现在小明想组装台电脑,市场上有很多电脑配件,小明希望用联想的键盘和Dell的鼠标组装一台自己的电脑。代码实现方式就是

抽象Pc工厂类

 /**
 *@DESCRIPTION 生产PC电脑的抽象工厂, 可以生产键盘和鼠标
 *@AUTHOR SongHongWei
 *@TIME 2018/8/12-17:12
 *@PACKAGE_NAME test.factory._abstract
 **/
public abstract class AbstractPcFactory
{
    //生产一个鼠标
    public abstract MouseProduct getMouse();

    //生产一个键盘
    public abstract keyBoardProduct getKeyBoard();
}

鼠标抽象类

/**
 *@DESCRIPTION 抽象的鼠标类也可以是一个接口
 *@AUTHOR SongHongWei
 *@TIME 2018/8/12-15:27
 *@PACKAGE_NAME test.factory.general
 **/
public abstract class MouseProduct
{
    /**
     *@DESCRIPTION 打印鼠标的名称
     *@AUTHOR SongHongWei
     *@TIME   2018/8/12-17:12
     *@CLASS_NAME MouseProduct
    **/ 
    public abstract void getMouserName();
}

键盘抽象类

/**                   
 *@DESCRIPTION 抽象的键盘类也可以是一个接口
 *@AUTHOR SongHongWei
 *@TIME 2018/8/12-15:27
 *@PACKAGE_NAME test.factory.general
 **/
public abstract class keyBoardProduct
{
    /**
     *@DESCRIPTION 打印键盘的名称
     *@AUTHOR SongHongWei
     *@TIME   2018/8/12-17:12
     *@CLASS_NAME MouseProduct
    **/ 
    public abstract void getKeyBoardName();
}

LenovoPc工厂类

 /**
 *@DESCRIPTION 联想鼠标工厂, 负责生产联想鼠标
 *@AUTHOR SongHongWei
 *@TIME 2018/8/12-15:30
 *@PACKAGE_NAME test.factory.general
 **/
public class LenovoPcFactory extends AbstractPcFactory
{
    /*
     * 生产一个联想鼠标
     */

    @Override
    public MouseProduct getMouse()
    {
        return new LenovoMouse();
    }

    /*
     * 生产一个联想键盘
     */
    @Override
    public keyBoardProduct getKeyBoard()
    {
        return new LenovoKeyBoard();
    }
}

DellPc工厂类

 /**
 *@DESCRIPTION 戴尔鼠标工厂, 负责生产戴尔鼠标
 *@AUTHOR SongHongWei
 *@TIME 2018/8/12-15:30
 *@PACKAGE_NAME test.factory.general
 **/
public class DellPcFactory extends AbstractPcFactory
{
    /*
     * 生产一个戴尔鼠标
     */
    @Override
    public MouseProduct getMouse()
    {
        return new DellMouse();
    }

    /*
     *生产一个戴尔键盘
     */
    @Override
    public keyBoardProduct getKeyBoard()
    {
        return new DellKeyBoard();
    }
}

Lenovo鼠标类

 /**
 *@DESCRIPTION 联想鼠标
 *@AUTHOR SongHongWei
 *@TIME 2018/8/12-15:28
 *@PACKAGE_NAME test.factory.general
 **/
public class LenovoMouse extends MouseProduct
{

    @Override
    public void getMouserName()
    {
        System.out.println("I'm mouse come from Lenovo...");
    }
}

Lenovo 键盘类

 /**
 *@DESCRIPTION 联想键盘
 *@AUTHOR SongHongWei
 *@TIME 2018/8/12-15:28
 *@PACKAGE_NAME test.factory.general
 **/
public class LenovoKeyBoard  extends keyBoardProduct
{

    @Override
    public void getKeyBoardName()
    {
        System.out.println("I'm keyboard come from Lenovo...");
    }
}

Dell鼠标类

/**
 *@DESCRIPTION 戴尔鼠标
 *@AUTHOR SongHongWei
 *@TIME 2018/8/12-15:28
 *@PACKAGE_NAME test.factory.general
 **/
public class DellMouse extends MouseProduct
{
    @Override
    public void getMouserName()
    {
        System.out.println("I'm mouse come from Dell...");
    }
}

Dell键盘类

 /**
 *@DESCRIPTION 戴尔键盘
 *@AUTHOR SongHongWei
 *@TIME 2018/8/12-15:28
 *@PACKAGE_NAME test.factory.general
 **/
public class DellKeyBoard extends keyBoardProduct
{

    @Override
    public void getKeyBoardName()
    {
        System.out.println("I'm keyboard come from Dell...");
    }
}

客户端调用

/**
 *@DESCRIPTION ${END}
 *@AUTHOR SongHongWei
 *@TIME 2018/8/12-17:20
 *@PACKAGE_NAME test.factory._abstract
 **/
public class Client
{
    public static void main(String[] args)
    {
        //用户希望自己组装台电脑,但是想用联想的键盘和Dell的鼠标
        AbstractPcFactory pcFactory = new LenovoPcFactory();
        //得到联想键盘
        pcFactory.getKeyBoard().getKeyBoardName();
        pcFactory = new DellPcFactory();
        //得到Dell鼠标
        pcFactory.getMouse().getMouserName();
    }
}

输出结果

I'm keyboard come from Lenovo...
I'm mouse come from Dell...

Process finished with exit code 0

总结

抽象工厂模式的最大缺点就是产品族扩展非常困难, 为什么这么说呢? , 如果要增加一个产品显示器, 也就是说产品家族由原来的2个增加到3个, 看看我们的程序有多大改动吧! 抽象类AbstractPcFactory要增加一个方法getDisplay(), 然后两个实现类都要修改, 想想看, 这严重违反了开闭原则.但是一定要清楚, 是产品族扩展困难, 而不是产品等级。 在该模式下, 产品等级是非常容易扩展的, 增加一个产品等级, 只要增加一个工厂类负责新增加出来的产品生产任务即可。 也就是说横向扩展容易, 纵向扩展困难。
而抽象工厂的优点就是可以在类的内部对产品族进行约束。因为所谓的产品族,一般或多或少的都存在一定的关联,比如一台电脑只能接一个鼠标和键盘, 抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值