设计模式(三)抽象工厂

发布时间 2023-08-24 11:57:08作者: 冬先生

一、定义

提供一个创建一系列相关或互相依赖对象的接口,而无须指定他们具体的类,抽象工厂模式是一种创建型模式。

二、描述

抽象工厂比工厂方法的抽象程度更高,通过引入了工厂等级结构,解决了简单工厂模式中工厂类职责太重的原则。为了更好的理解抽象工厂模式,引入两个概念:
1、产品等级结构:指不同品牌的同一类型产品,如:小米电视机、海信电视机、索尼电视机
2、产品族:指同一品牌的不同了类型产品,如:小米电视机、小米手机、小米电脑
抽象工厂模式中的每个具体工厂提供了多个工厂方法用于产生多种不同类型的产品,这些产品构成了一个产品族,它包含以下四个角色:
1、AbstractFactory (抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。
2、ConcreteFactory (具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
3、AbstractProduct (抽象产品角色):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
4、ConcreteProduct (具体产品角色):它定义具体工厂生产的具体产品对象,实现在抽象产品接口中声明的业务方法。

三、例子

X公司要开发一套皮肤库,可切换不同风格,如春天风格,用浅绿色按钮、文本框等,夏天用浅蓝色的,后续还可以增加其他风格。
抽象产品接口:Button、TextField、ComboBox

public interface IButton
{
    void Display();
}

public interface ITextField
{
    void Display();
}

public interface IComboBox
{
    void Display();
}

具体产品类:
SpringButton、SpringTextField、SpringComboBox,Spring风格按钮、文本框、组合框
SummerButton、SummerTextField、SummerComboBox,Summer风格按钮、文本框、组合框

public class SpringButton : IButton
{
    public void Display()
    {
        Console.WriteLine("显示浅绿色按钮。");
    }
}

public class SpringTextField : ITextField
{
    public void Display()
    {
        Console.WriteLine("显示绿色边框文本框。");
    }
}

public class SpringComboBox : IComboBox
{
    public void Display()
    {
        Console.WriteLine("显示绿色边框下拉框。");
    }
}

public class SummerButton : IButton
{
    public void Display()
    {
        Console.WriteLine("显示浅绿色按钮。");
    }
}

public class SummerTextField : ITextField
{
    public void Display()
    {
        Console.WriteLine("显示绿色边框文本框。");
    }
}

public class SummerComboBox : IComboBox
{
    public void Display()
    {
        Console.WriteLine("显示绿色边框下拉框。");
    }
}

抽象皮肤工厂接口:ISkinFactory

public interface ISkinFactory
{
    IButton CreateButton();
    ITextField CreateTextField();
    IComboBox CreateComboBox();
}

具体皮肤工厂类:SpringSkinFactory、SummerSkinFactory

public class SpringSkinFactory : ISkinFactory
{
    public IButton CreateButton()
    {
        return new SpringButton();
    }

    public IComboBox CreateComboBox()
    {
        return new SpringComboBox();
    }

    public ITextField CreateTextField()
    {
        return new SpringTextField();
    }
}

public class SummerSkinFactory : ISkinFactory
{
    public IButton CreateButton()
    {
        return new SummerButton();
    }

    public IComboBox CreateComboBox()
    {
        return new SummerComboBox();
    }

    public ITextField CreateTextField()
    {
        return new SummerTextField();
    }
}

Program:测试代码

Console.WriteLine("加载Spring皮肤\n");

ISkinFactory skinFactory = new SpringSkinFactory();

IButton button = skinFactory.CreateButton();
ITextField textField = skinFactory.CreateTextField();
IComboBox comboBox = skinFactory.CreateComboBox();

button.Display();
textField.Display();
comboBox.Display();

Console.ReadLine();

四、总结

如果需要增加新的产品族很方便,无需修改已有系统,符合开闭原则,但是如果需要增加产品等级结构,会非常麻烦,比如单选按钮(RadioButton),因为抽象工厂ISkinFactory根本没有提供创建的方法,需要依次修改抽象工厂接口、具体皮肤工厂类,抽象工厂模式无法很好的解决此类问题,这也是该模式最大的缺点,所以不适合在产品等级结构不稳定的场景下使用。