(1)创建型模式——抽象工厂

创建型模式——抽象工厂(Abstract Factory)

问题背景

当希望能够替换和扩展一族相关类的实现来给予程序定制性时,可以考虑使用抽象工厂。举一个常见的例子,界面换肤:用户可以自由选择Windows或Mac风格的界面,并且在以后的版本迭代中可能推出更多款式。在这种需求下,如果把客户端实现成这样就会造成很多麻烦:
客户端
这是典型的“非OO”做法,在OOP中,要实现对象行为的动态切换,应该使用多态,而不是将各种行为枚举然后硬编码到程序中。

这种做法会导致程序的弹性降低,后续需求变更时必须修改已有代码,这是大型软件开发中的大忌。如果只是修改私有成员还好,一旦修改了接口,就可能引入回归错误,严重拖慢工作进度。

解决方案

考虑到后续的版本迭代中可能出现更多风格的皮肤,我们从同类界面控件中提取出接口,把引用类型全部改为接口类型,并把控件的创建工作交给一个专门负责创建对象的类,改进后的程序结构是这样的:
程序结构

效果

  1. 实现了抽象和实现的分离,降低了模块间的耦合度。
  2. 将创建工作封装到工厂中,简化了创建和切换产品族的操作。
  3. 同一时刻只能有一款皮肤运行,保证了程序的一致性。

缺陷

抽象工厂虽然实现了产品族的可扩展性,却没有实现产品项的可扩展性,即只能适应一个维度的变化。如果在以后的需求中,程序要增加单选框、复选框、下拉列表等控件,这种结构就又变得很麻烦了。

为了进一步提高程序的可扩展性,可以桥接整合到抽象工厂中,也可以使用反射工厂(后者是目前的主流做法)。

相关模式

  1. 工厂方法:抽象工厂可以通过工厂方法来实现。
  2. 原型:抽象工厂也可以通过传入对象原型来实现。
  3. 单例:一般情况下,只需要一个全局工厂,故抽象工厂常被设计成单例类。

实现

using System;

namespace AbstractFactory
{
    public interface IForm
    {
        void Show();
    }

    public interface IButton
    {
        void Show();
    }

    public class WindowsForm : IForm
    {
        public void Show()
        {
            Console.WriteLine("我是WindowsForm");
        }
    }

    public class MacForm : IForm
    {
        public void Show()
        {
            Console.WriteLine("我是MacForm");
        }
    }

    public class WindowsButton : IButton
    {
        public void Show()
        {
            Console.WriteLine("我是WindowsButton");
        }
    }

    public class MacButton : IButton
    {
        public void Show()
        {
            Console.WriteLine("我是MacButton");
        }
    }

    public interface IControlFactory
    {
        IForm CreateForm();
        IButton CreateButton();
    }

    public class WindowsControlFactory : IControlFactory
    {
        public IForm CreateForm()
        {
            return new WindowsForm();
        }
        public IButton CreateButton()
        {
            return new WindowsButton();
        }
    }

    public class MacControlFactory : IControlFactory
    {
        public IForm CreateForm()
        {
            return new MacForm();
        }
        public IButton CreateButton()
        {
            return new MacButton();
        }
    }

    public class Client
    {
        static IForm form;
        static IButton button;
        static void Show()
        {
            form.Show();
            button.Show();
        }
        static void Main(string[] args)
        {
            Console.WriteLine("使用Windows皮肤...");
            IControlFactory factory = new WindowsControlFactory();
            form = factory.CreateForm();
            button = factory.CreateButton();
            Show();

            Console.WriteLine("切换到Mac皮肤...");
            factory = new MacControlFactory();
            form = factory.CreateForm();
            button = factory.CreateButton();
            Show();
        }
    }
}

运行结果

发布了10 篇原创文章 · 获赞 10 · 访问量 486

猜你喜欢

转载自blog.csdn.net/DIAX_/article/details/104130091