设计模式之 - 抽象工厂模式

1,366 阅读4分钟
  • 携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

前言

在使用之前,我们可以简单了解一下什么是抽象工厂模式,抽象工厂是指当有多个抽象角色时使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下,创建多个产品族中的产品对象。
那么如何理解呢?前文提到的工厂方法模式可以理解为针对一个产品系列的,而抽象工厂模式是针对多个产品系列的。

如何理解抽象工厂模式

概念我相信大家了解了一些,我们可以通过实例从代码中更加深刻体现抽象工厂模式。还记得之前提过工厂模式的核心四个角色吗(抽象工厂、具体工厂、抽象产品、具体产品)。

  • 抽象工厂接口,我们使用实例新增家电工厂,里面有两个产品方法 空调和冰箱
public interface IApplianceFactory 
{
    // 空调
    IAirConditionerProduct AirConditioner();
    // 冰箱
    IRefrigeratorProduct Refrigerator();
}
  • 具体工厂继承抽象工厂,实现抽象方法,创建具有特定产品的实例,如格力工厂、美的工厂,每个具体工厂中都会包含一个相应的产品变体
// 具体工厂 格力工厂
public class GreeFactory : IApplianceFactory
{
    public IAirConditionerProduct AirConditioner()
    {
        return new GreeAirConditionerProduct();
    }
    public IRefrigeratorProduct Refrigerator()
    {
        return new GreeRefrigeratorProduct();
    }
}

// 具体工厂 美的工厂
public class MideaFactory : IApplianceFactory
{
    public IAirConditionerProduct AirConditioner()
    {
        return new MideaAirConditionerProduct();
    }
    public IRefrigeratorProduct Refrigerator()
    {
        return new MideaRefrigeratorProduct();
    }
}
  • 抽象产品接口,是构成系列产品的产品接口声明,如冰箱有(四门、双开门),空调有(立式、中央空调)
public interface IRefrigeratorProduct 
{
    // 双门冰箱
    void DoubleDoorRefrigerator();
    // 四门冰箱
    void FourDoorRefrigerator();
}

public interface IAirConditionerProduct
{
    // 立式空调
    void FloorAirConditioner();
    // 中央空调
    void CentralAirConditioning();
}
  • 具体产品,是抽象产品的多种不同类型实现,里面包含的是客户端(业务)所需要的东西
// 美的具体产品实现
public class MideaRefrigeratorProduct : IRefrigeratorProduct
{
    public void DoubleDoorRefrigerator()
    {
        Console.WriteLine("美的双门冰箱真香");
    }
    public void FourDoorRefrigerator()
    {
        Console.WriteLine("美的四门冰箱真香");
    }
}
public class MideaAirConditionerProduct : IAirConditionerProduct
{
    public void FloorAirConditioner()
    {
        Console.WriteLine("美的立式空调真舒服");
    }
    public void CentralAirConditioning()
    {
        Console.WriteLine("美的中央空调真舒服");
    }
}
// 格力具体产品实现
public class GreeRefrigeratorProduct : IRefrigeratorProduct
{
    public void DoubleDoorRefrigerator()
    {
        Console.WriteLine("格力双门冰箱真香");
    }
    public void FourDoorRefrigerator()
    {
        Console.WriteLine("格力四门冰箱真香");
    }
}
public class GreeAirConditionerProduct : IAirConditionerProduct
{
    public void FloorAirConditioner()
    {
        Console.WriteLine("格力立式空调真舒服");
    }
    public void CentralAirConditioning()
    {
        Console.WriteLine("格力中央空调真舒服");
    }
}
  • 客户端调用 image.png

以上是抽象工厂方法的具体实现,不难看出,当客户端想要使用Gree格力产品的时候,我们只需要修改IApplianceFactory product = new GreeFactory(); 即可实现,客户端与具体产品解耦。

image.png

类图

总结

针对上述例子如果需要引用更多的厂商如 海尔 呢?

  • 新增实现类HaierAirConditionerProduct继承IAirConditionerProduct
  • 新增工厂HaierFactory继承IApplianceFactory即可

客户需求变更,需要更多的产品如 洗衣机 代码会做出什么改变?

  • 添加抽象产品接口IWashingMachineProduct
  • 添加具体产品实现类GreeWashingMachineProduct,MideaWashingMachineProduct
  • 集成到工厂接口

优点

  • 在客户端调用的时候根本看不到具体产品使用的是Gree还是Midea,是的客户端与具体产品实现解耦。
  • 只需要在应用开始的时候创建一次,这样就让我们改动具体工厂变得非常的容易,并且能够保证客户端始终只使用同一个工厂中的对象。

缺点

  • 对于涉及到多个产品族(美的、格力)与多个产品等级(空调、冰箱)结构的系统,增加新的产品族,工厂方法不用修改原有代码,只需要扩展新增即可,遵循了开闭原则!但是在新增新的产品等级的时候需要修改原有代码,无法遵循开闭原则。
  • 采用该模式会新增更多的接口和类,会使系统更加抽象,代码更加复杂

当然针对上面所遇到的问题,之前我也看过一些书籍,也有方法来解决,如使用简工厂模式来改进抽象工厂模式等等,大家在使用的时候也要去深入研究是否适用,如果不是最佳实践那么只能使系统愈加复杂。