抽象工厂模式

思考抽象工厂模式

抽象工厂专注于产品簇的实现,主要是那些有关联关系的,如果只有一个产品的话就退化成了工厂方法模式

总结:

  • 简单工厂就是创建了一个工厂,直接在工厂中if-else决定实现哪个类
  • 工厂方法就是一个抽象工厂对应多个具体的工厂实现,里面决定实现哪些产品,也就是延伸到子类中去实现,但只是一个产品,多个产品就不行了,得用抽象工厂
  • 抽象工厂就是多个有关联关系的产品,形成一个产品簇,抽象工厂的实现类进行组合

1.抽象工厂模式的本质

抽象工厂模式的本质:选择产品簇的实现。

产品簇(Product family)指具有相同或相似的功能结构或性能,共享主要的产品特征、组件或子结构,并通过变型配置来满足特定市场的一组产品的聚类。

工厂方法是选择单个产品的实现,虽然一个类里面可以有多个工厂方法,但是这些方法之间一般是没有联系的,即使看起来像有联系。

但是抽象工厂着重的就是为一个产品簇选择实现,定义在抽象工厂里面的方法通常是有联系的,它们都是产品的某一部分或者是相互依赖的。如果抽象工厂里面只定义一个方法,直接创建产品,那么就退化成为工厂方法了。

2.何时选用抽象工厂模式

建议在以下情况中选用抽象工厂模式。

  • 如果希望一个系统独立于它的产品的创建、组合和表示的时候。换句话说,希望一个系统只是知道产品的接口,而不关心实现的时候。
  • 如果一个系统要由多个产品系列中的一个来配置的时候。换句话说,就是可以动态地切换产品簇的时候。
  • 如果要强调一系列相关产品的接口,以便联合使用它们的时候。

3.优缺点

抽象工厂模式的优点

  • 分离接口和实现
    客户端使用抽象工厂来创建需要的对象,而客户端根本就不知道具体的实现是谁,客户端只是面向产品的接口编程而已。也就是说,客户端从具体的产品实现中解耦。

  • 使得切换产品簇变得容易
    因为一个具体的工厂实现代表的是一个产品簇,比如上面例子的Schemel代表装机方案一:Intel的 CPU+技嘉的主板,如果要切换成为Scheme2,那就变成了装机方案二:AMD的CPU +微星的主板。

客户端选用不同的工厂实现,就相当于是在切换不同的产品簇。

抽象工厂模式的缺点

  • 不太容易扩展新的产品
    前面也提到这个问题了,如果需要给整个产品簇添加一个新的产品,那么就需要修改抽象工厂,这样就会导致修改所有的工厂实现类。在前面提供了一个可以扩展工厂的方式来解决这个问题,但是又不够安全。如何选择,则要根据实际应用来权衡。

  • 容易造成类层次复杂
    在使用抽象工厂模式的时候,如果需要选择的层次过多,那么会造成整个类层次变得复杂。
    举个例子来说,就比如前面讲到的DAO的示例,现在这个DAO只有一个选择的层次,也就是选择是使用关系型数据库来实现,还是用Xml来实现。现在考虑这样一种情况,如果关系型数据库实现里面又分成几种,比如,基于Oracle的实现、基于SqlServer的实现、基于MySql 的实现等。
    那么客户端怎么选择呢?不会把所有可能的实现情况全部都做到一个层次上吧,这个时候客户端就需要一层一层地选择,也就是整个抽象工厂的实现也需要分出层次来,每一层负责一种选择,也就是一层屏蔽一种变化,这样很容易造成复杂的类层次结构。

4.抽象工厂模式的结构

在这里插入图片描述

  • Abstract Factory:抽象工厂,定义创建一系列产品对象的操作接口。
  • Concrete Factory:具体的工厂,实现抽象工厂定义的方法,具体实现一系列产品对象的创建。
  • Abstract Product:定义一类产品对象的接口。
  • Concrete Product:具体的产品实现对象,通常在具体工厂里面,会选择具体的产品实现对象,来创建 - 符合抽象工厂定义的方法返回的产品类型的对象。
  • Client:客户端,主要使用抽象工厂来获取一系列所需要的产品对象,然后面向这些产品对象的接口编程,以实现需要的功能。

5.实现

在这里插入图片描述

cpu产品

/**
 * @description:cpu接口
 */
public interface Cpu {

    /**
     * 初始化cpu
     */
    void initCpu();
}

/**
 * @description:英特尔cpu
 */
public class IntelCpu implements Cpu{
    //针脚
    private int pins=0;

    public IntelCpu(int pins){
        this.pins=pins;
    }

    @Override
    public void initCpu() {
        System.out.println("Cpu-->英特尔 针脚数"+pins);
    }
}

/**
 * @description:AMDcpu
 */
public class AmdCpu implements Cpu{

    private int pins=0;

    public AmdCpu(int pins){
        this.pins=pins;
    }

    @Override
    public void initCpu() {
        System.out.println("Cpu-->AMD 针脚数"+pins);
    }
}

主板接口

/**
 * @description:主板接口
 */
public interface Mainboard {

    /**
     * 初始化主板
     */
    void initMainBoard();
}

/**
 * @description:华硕主板
 */
public class AsusMainboard implements Mainboard{
    //针脚
    private int pins=0;

    public AsusMainboard(int pins){
        this.pins=pins;
    }

    @Override
    public void initMainBoard() {
        System.out.println("Mainboard-->华硕 针脚数"+pins);
    }
}

/**
 * @description:微星主板
 */
public class MsiMainboard implements Mainboard{

    private int pins=0;

    public MsiMainboard(int pins){
        this.pins=pins;
    }

    @Override
    public void initMainBoard() {
        System.out.println("Mainboard-->微星 针脚数"+pins);
    }
}

抽象工厂

/**
 * @description:抽象工厂
 */
public interface AbstractFactory {

    /**
     * 创建cpu
     * @return
     */
    Cpu createCpu();

    /**
     * 创建主板
     * @return
     */
    Mainboard createMainboard();
}

/**
 * @description:自组电脑1 (英特尔cpu+华硕主板) 假设都是1156针脚
 */
public class CustomComputer1 implements AbstractFactory{
    @Override
    public Cpu createCpu() {
        return new IntelCpu(1156);
    }

    @Override
    public Mainboard createMainboard() {
        return new AsusMainboard(1156);
    }
}

/**
 * @description:自组电脑2 (AMDcpu + 微星主板) 假设都是963针脚
 */
public class CustomComputer2 implements AbstractFactory{
    @Override
    public Cpu createCpu() {
        return new AmdCpu(963);
    }

    @Override
    public Mainboard createMainboard() {
        return new MsiMainboard(963);
    }
}

组装类

/**
 * @description:工程师组装电脑
 */
public class Engineer {

    /**
     * cpu
     */
    private Cpu cpu=null;

    /**
     * 主板
     */
    private Mainboard mainboard=null;

    /**
     * 组装电脑
     * @param factory
     */
    public void makeComputer(AbstractFactory factory){
        cpu=factory.createCpu();
        mainboard=factory.createMainboard();

        cpu.initCpu();
        mainboard.initMainBoard();
    }

}

测试

public class Client {

    public static void main(String[] args) {
        Engineer engineer = new Engineer();
        //顾客想组装的电脑配置
        engineer.makeComputer(new CustomComputer1());
    }
}

类图
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值