「设计模式」抽象工厂模式

「设计模式」抽象工厂模式

前面我们已经简单介绍了简单工厂模式工厂方法模式,相信很多人对工厂模式(如果单独提到工厂模式,即包括简单工厂模式、工厂方法模式及本文即将介绍的抽象工厂模式)的思想都有了一定的理解。这里我们在简单回顾一下。


一、回顾

简单工厂模式的优缺点

优点

  • 屏蔽产品的具体实现,调用者只关心产品的接口。
  • 实现简单

缺点

  • 增加产品,需要修改工厂类,不符合开放-封闭原则
  • 工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则

工厂方法模式的优缺点

优点

  • 继承了简单工厂模式的优点
  • 符合开放-封闭原则

缺点

  • 增加产品,需要增加新的工厂类,导致系统类的个数成对增加,在一定程度上增加了系统的复杂性。

本文要介绍了抽象工厂模式,是在简单工厂模式和工厂方法模式的基础上衍生出的另外一种创建型设计模式。


二、概念

抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式

抽象工厂模式提供了一种方式,可以将同一产品族的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。客户端程序不需要知道(或关心)它从这些内部的工厂方法中获得对象的具体类型,因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。

产品族: 位于不同产品等级结构中,功能相关的产品组成的家族。如下面的例子,就有两个产品族

image-20221030235108923


三、用途

抽象工厂模式和工厂方法模式一样,都符合开放-封闭原则。但是不同的是,工厂方法模式在增加一个具体产品的时候,都要增加对应的工厂。但是抽象工厂模式只有在新增一个类型的具体产品时才需要新增工厂。也就是说,工厂方法模式的一个工厂只能创建一个具体产品。而抽象工厂模式的一个工厂可以创建属于一类类型的多种具体产品。工厂创建产品的个数介于简单工厂模式和工厂方法模式之间。

在以下情况下可以使用抽象工厂模式:

一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。

系统中有多于一个的产品族,而每次只使用其中某一产品族。

属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。

系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

四、实现方式

/**
 * 接口中修饰符:
 *  Java 7 方法只能为抽象方法,默认为 public abstract
 *  Java 8 增加:默认方法default;静态方法static(默认方法不强制重写,静态方法不会被实现类继承)
 *  Java 9 增加:私有方法
 *
 *  接口中不可以定义变量即只能定义常量,属性默认是public static final,且必须赋值
 */
// 1.------------ 超级工厂,定义产品族 ------------ 
public interface IProductFactory {
    //生产手机
    IPhoneProduct phoneProduct();
    //生产路由器
    IRouterProduct routerProduct();
}
// 2.------------ 产品接口,定义产品功能 ------------ 
//手机产品接口
public interface IPhoneProduct {
    void open();    //开机
    void callup();  //打电话
}
//路由器产品接口
public interface IRouterProduct {
    void open();    //开机
    void openWifi();  //打开WiFi
}
// 3.------------ 具体产品,实现产品接口 ------------ 
//小米手机
public class XiaomiPhone implements IPhoneProduct {
    @Override
    public void open() {
        System.out.println("小米手机:开机");
    }
    @Override
    public void callup() {
        System.out.println("小米手机:打电话");
    }
}
//小米路由器
public class XiaomiRouter implements IRouterProduct {
    @Override
    public void open() {
        System.out.println("小米路由器:开机");
    }
    @Override
    public void openWifi() {
        System.out.println("小米路由器:打开WiFi");
    }
}
//华为手机
public class HuaweiPhone implements IPhoneProduct {
    @Override
    public void open() {
        System.out.println("华为手机:开机");
    }
    @Override
    public void callup() {
        System.out.println("华为手机:打电话");
    }
}
//华为路由器
public class HuaweiRouter implements IRouterProduct {
    @Override
    public void open() {
        System.out.println("华为路由器:开机");
    }
    @Override
    public void openWifi() {
        System.out.println("华为路由器:打开WiFi");
    }
}
// 4.------------ 超级工厂实现类,生产具体产品 ------------ 
//小米工厂,生产小米手机、路由器
public class XiaomiFactory implements IProductFactory{
    @Override
    public IPhoneProduct phoneProduct() {
        return new XiaomiPhone();
    }
    @Override
    public IRouterProduct routerProduct() {
        return new XiaomiRouter();
    }
}
//华为工厂,生产华为手机、路由器
public class HuaweiFactory implements IProductFactory{
    @Override
    public IPhoneProduct phoneProduct() {
        return new HuaweiPhone();
    }
    @Override
    public IRouterProduct routerProduct() {
        return new HuaweiRouter();
    }
}
// 5.------------ 消费者,实现具体消费 ------------ 
public class Consumer {
    public static void main(String[] args) {
        System.out.println("------------小米产品---------------");
        XiaomiFactory xiaomiFactory = new XiaomiFactory();      //小米工厂
        IPhoneProduct xiaomiPhone = xiaomiFactory.phoneProduct();   //生产小米手机
        IRouterProduct xiaomiRouter = xiaomiFactory.routerProduct();//生产小米路由器
        System.out.println("------------华为产品---------------");
        HuaweiFactory huaweiFactory = new HuaweiFactory();      //华为工厂
        IPhoneProduct huaweiPhone = huaweiFactory.phoneProduct();   //华为手机
        IRouterProduct huaweiRouter = huaweiFactory.routerProduct();//华为路由器
    }
}

  • 超级工厂接口,只起到一个限制作用,限制产品族
  • 具体工厂,实现超级工厂接口,生产不同规格的产品

image-20221031001417038


五、“开闭原则”的倾斜性

**“开闭原则”要求系统对扩展开放,对修改封闭,通过扩展达到增强其功能的目的。**对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:

增加产品族:对于增加新的产品族,工厂方法模式很好的支持了“开闭原则”,对于新增加的产品族,只需要对应增加一个新的具体工厂即可,对已有代码无须做任何修改。

增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,不能很好地支持“开闭原则”。

抽象工厂模式的这种性质称为“开闭原则”的倾斜性,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,但不能为新的产品等级结构的增加提供这样的方便。


六、三种工厂模式之间的关系

  • 当抽象工厂模式中每一个具体工厂类只创建一个产品对象,也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式

  • 抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构。

  • 当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式。


七、总结

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。

抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态

抽象工厂模式的主要优点是隔离了具体类的生成,使得客户并不需要知道什么被创建,而且每次可以通过具体工厂类创建一个产品族中的多个对象,增加或者替换产品族比较方便,增加新的具体工厂和产品族很方便;主要缺点在于增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性。


参考资料

大话设计模式

深入浅出设计模式

抽象工厂模式(Factory Method Pattern)

Hollis

狂神说

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FrozenPenguin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值