c#简单工厂、工厂方法与抽象工厂的区别分析

网上的很多讲三个设计模式的案例,但是它们类名,方法名的命名不够形象,很难理解。我自己重新画UML类图和代码展示,以及效果展示图。方便大家更加形象理解。(三种模式下主要考虑的是工厂如何创建产品,不需要考虑应该调用哪个(一个或者多个)工厂的哪个(一个或者多个)产品,这是Client考虑的事情。见下面UML图)
1 本质

三个设计模式名字中都含有“工厂”二字,其含义是使用工厂(一个或一系列方法)去生产产品(一个或一系列类的实例)。

另外,有时候,我们常常会将生产产品的一个或一系列方法封装到一个类中,我习惯把这个类叫做“工厂类”;而被实例化的类称作“产品类”。
  
2 简单工厂

工厂类(SimpleFactory)拥有一个工厂方法(CreateProduct),接受了一个参数,通过不同的参数实例化不同的产品类。

如下边UML类图所示为简单工厂。

在这里插入图片描述

代码如下:

    [STAThread]
    static void Main(string[] args)
    {
        Console.WriteLine("请输入产品名:");
        string productName = Console.ReadLine();
        Form1.IProduct f = Form1.Factory.CreateProduct(productName);
        f.operation1();
        f.operation2();
        Console.ReadLine();
    }

   public class ProductA : IProduct
    {
        public void operation1()
        {
            Console.WriteLine("调用ProductA的operation1的方法");
        }

        public void operation2()
        {
            Console.WriteLine("调用ProductA的operation2的方法");
        }

    }


    public class ProductB : IProduct
    {
        public void operation1()
        {
            Console.WriteLine("调用ProductB的operation1的方法");
        }

        public void operation2()
        {
            Console.WriteLine("调用ProductB的operation2的方法");
        }

    }

    public interface IProduct
    {

        void operation1();

        void operation2();
    }

    public static class Factory
    {
        public static IProduct CreateProduct(string productName)
        {
            IProduct p = null;
            switch (productName)
            {
                case "ProductA":
                    p = new ProductA();
                    break;
                case "ProductB":
                    p = new ProductB();
                    break;
                default:
                    break;
            }

            return p;
        }
    }

优点:

(1)很明显,简单工厂的特点就是“简单粗暴”,通过一个含参的工厂方法,我们可以实例化任何产品类,上至飞机火箭,下至土豆面条,无所不能。所以简单工厂有一个别名:上帝类。

缺点:

(1)任何”东西“的子类都可以被生产,负担太重。当所要生产产品种类非常多时,工厂方法的代码量可能会很庞大。

(2)在遵循开闭原则(对拓展开放,对修改关闭)的条件下,简单工厂对于增加新的产品,无能为力。因为增加新产品只能通过修改工厂方法来实现。

工厂方法正好可以解决简单工厂的这两个缺点。
  
3 工厂方法

工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。

如下边UML类图所示为工厂方法。
  
注意: 主要看IFactory实现类的方法CreateProduct().创建对应的工厂的产品对象(Factory1类创建Factory1Product对象或者Factory2类创建Factory2Product对象),并返回IProduct。

在这里插入图片描述

代码如下:

        public class Factory1Product : IProduct
        {
            public void operation1()
            {
                Console.WriteLine("调用Factory1Product的operation1的方法");
            }

            public void operation2()
            {
                Console.WriteLine("调用Factory1Product的operation2的方法");
            }

        }


        public class Factory2Product : IProduct
        {
            public void operation1()
            {
                Console.WriteLine("调用Factory2Product的operation1的方法");
            }

            public void operation2()
            {
                Console.WriteLine("调用Factory2Product的operation2的方法");
            }

        }

        public interface IProduct
        {

            void operation1();

            void operation2();
        }

        public class Factory1 : IFactory
        {

            public IProduct CreateProduct()
            {
                Console.WriteLine("创建了Factory1Product对象,返回对象为IProduct");
                return new Factory1Product();
            }
        }

        public interface IFactory
        {
            IProduct CreateProduct();
        }

        public class Factory2 : IFactory
        {

            public IProduct CreateProduct()
            {
                Console.WriteLine("创建了Factory2Product对象,返回对象为IProduct");
                return new Factory2Product();
            }
        }

        [STAThread]
        static void Main(string[] args)
        {
            Form1.IFactory f = new Form1.Factory1();
            Form1.IProduct p = f.CreateProduct();
            p.operation1();
            p.operation2();
            Console.ReadLine();
        }

优点:

(1)工厂方法模式就很好的减轻了工厂类的负担,把某一类/某一种东西交由一个工厂生产;(对应简单工厂的缺点1)

(2)同时增加某一类”东西“并不需要修改工厂类,只需要添加生产这类”东西“的工厂即可,使得工厂类符合开放-封闭原则。

缺点:

(1)相比简单工厂,实现略复杂。

(2)对于某些可以形成产品族的情况处理比较复杂。

对于缺点(2),我们可以借用抽象工厂来实现。
  
4 抽象工厂

抽象工厂是应对产品族概念的。

例如,汽车可以分为轿车、SUV、MPV等,也分为奔驰、宝马等。我们可以将奔驰的所有车看作是一个产品族,而将宝马的所有车看作是另一个产品族。分别对应两个工厂,一个是奔驰的工厂,另一个是宝马的工厂。与工厂方法不同,奔驰的工厂不只是生产具体的某一个产品,而是一族产品(奔驰轿车、奔驰SUV、奔驰MPV)。“抽象工厂”的“抽象”指的是就是这个意思。

上边的工厂方法模式是一种极端情况的抽象工厂模式(即只生产一种产品的抽象工厂模式),而抽象工厂模式可以看成是工厂方法模式的一种推广。

如下边UML类图所示为抽象工厂。
  
注意: 主要看IFactory接口的实现类的方法CreateProductA().创建对应的工厂的产品对象(Factory1类创建Factory1ProductA对象或者Factory2类创建Factory2ProductA对象)并返回IProductA。方法CreateProductB().创建对应的工厂的产品对象(Factory1类创建Factory1ProductB对象或者Factory2创建Factory2ProductB对象)并返回IProductB。
在这里插入图片描述

代码如下:

        public class Factory1ProductA : IProductA
        {
            public void operation1()
            {
                Console.WriteLine("调用Factory1ProductA的operation1的方法");
            }

            public void operation2()
            {
                Console.WriteLine("调用Factory1ProductA的operation2的方法");
            }

        }


        public class Factory1ProductB : IProductB
        {
            public void operation3()
            {
                Console.WriteLine("调用Factory1ProductB的operation3的方法");
            }

            public void operation4()
            {
                Console.WriteLine("调用Factory1ProductB的operation4的方法");
            }

        }

        public class Factory2ProductA : IProductA
        {
            public void operation1()
            {
                Console.WriteLine("调用Factory2ProductA的operation1的方法");
            }

            public void operation2()
            {
                Console.WriteLine("调用Factory2ProductA的operation2的方法");
            }

        }

        public class Factory2ProductB : IProductB
        {
            public void operation3()
            {
                Console.WriteLine("调用Factory2ProductB的operation3的方法");
            }

            public void operation4()
            {
                Console.WriteLine("调用Factory2ProductB的operation4的方法");
            }

        }

        public interface IProductA
        {

            void operation1();

            void operation2();
        }

        public interface IProductB
        {

            void operation3();

            void operation4();
        }

        public class Factory1 : IFactory
        {
            public IProductA CreateProductA()
            {
                Console.WriteLine("创建了Factory1ProductA对象,返回对象为IProductA");
                return new Factory1ProductA();
            }

            public IProductB CreateProductB()
            {
                Console.WriteLine("创建了Factory1ProductB对象,返回对象为IProductB");
                return new Factory1ProductB();
            }
        }

        public interface IFactory
        {
            IProductA CreateProductA();

            IProductB CreateProductB();
        }



        public class Factory2 : IFactory
        {

            public IProductA CreateProductA()
            {
                Console.WriteLine("创建了Factory2ProductA对象,返回对象为IProductA");
                return new Factory2ProductA();
            }

            public IProductB CreateProductB()
            {
                Console.WriteLine("创建了Factory2ProductB对象,返回对象为IProductB");
                return new Factory2ProductB();
            }
        }


        [STAThread]
        static void Main(string[] args)
        {
            Form1.IFactory f = new Form1.Factory1();
            Form1.IProductA p = f.CreateProductA();
            p.operation1();
            Form1.IProductB p1 = f.CreateProductB();
            p1.operation3();
            Console.ReadLine();
        }

产品族概念

例如,汽车可以分为轿车、SUV、MPV等,也分为奔驰、宝马等。我们可以将奔驰的所有车看作是一个产品族,而将宝马的所有车作另外一个产品族。分别对应两个工厂,一个是奔驰的工厂,另一个是宝马的工厂。与工厂方法不同,奔驰的工厂不只是生产具体的某一个产品,二十一族产品(奔驰轿车、奔驰SUV、奔驰MPV)。“抽象工厂”的抽象指的就是这个意思。

优点:

1、易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。

2、它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。

缺点:

如果要增加一个产品ProductC,那么就需要增加三个类,IProductC,Factory3ProductA,Factory3ProductB,还需要改动IFactory,Factory1,Factory2才可以完全实现。这样是很糟糕的。

编程是门艺术,这样大批量的改动,显然是非常丑陋的做法。

解决方案:可以使用简单工厂来改进抽象工厂。去除IFactory、Factory1、Factory2三个工厂类,用一个Factory类代替,用一个简单工厂模式来实现。

5 区别

简单工厂 : 用来生产同一等级结构中的任意产品。(不支持拓展增加产品)

工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)

抽象工厂 :用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)
  
6 注意事项

(1)工厂类常常采用单例模式(Singleton)。

(2)工厂类拥有基类(定义共同接口),基类可以为纯虚类,也可以定义缺省方法。

(3)对于工厂方法和抽象工厂,基类中的生产产品的函数常常为虚函数,以实现动态绑定。

(4)调用工厂方法的函数通常采用工厂实现的指针和引用作为形参,以便根据不同的工厂实参调用不同的工厂方法。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值