设计模式(三)抽象工厂方法模式

534 阅读4分钟

思路:

在工厂模式,如果有多个手机品牌供选择,当我们再添加新的手机品牌的时候,用简单工厂模式,我们就不得不修改简单工厂类,不满足开放封闭原则。于是就引出了工厂方法模式。

那么问题又来了,如果我们之前提到的全是3G手机,现在市场上又出来了4G手机,那么同样的品牌可能既有3G手机又有4G手机,我们又应当怎样去设计这些类的结构呢?

我们其实只需要对工厂方法模式中的工厂类进行简单的修改就可以满足这个条件了。

首先我们可以将手机工厂类转变成接口,提供创建某品牌3G手机的方法和创建某品牌4G手机的方法,这些方法只声明不实现。具体的实现交给对应品牌的工厂类去实现。由对应品牌的工厂类去完成创建该品牌的3G手机或者该品牌的4G手机。

  class Program
    {
        static void Main(string[] args)
        {
            Factory f = new AppleFactory(); // AppleFactory

            MobilePhone3G ph3g = f.CreatePhone3G();
            ph3g.Call();
            ph3g.SendMSG();

            MobilePhone4G ph4g = f.CreatePhone4G();
            ph4g.Call();
            ph4g.SendMSG();

            Console.ReadKey();
        }
    }

    abstract class Factory
    {
        public abstract MobilePhone3G CreatePhone3G();
        public abstract MobilePhone4G CreatePhone4G();
    }

    class AppleFactory : Factory
    {
        public override MobilePhone3G CreatePhone3G()
        {
            return new Iphone4S();
        }
        public override MobilePhone4G CreatePhone4G()
        {
            return new Iphone6();
        }
    }
    class SamsungFactory : Factory
    {
        public override MobilePhone3G CreatePhone3G()
        {
            return new GalaxyNote2();
        }
        public override MobilePhone4G CreatePhone4G()
        {
            return new GalaxyNote4();
        }
    }
    class HTCFactory : Factory
    {
        public override MobilePhone3G CreatePhone3G()
        {
            return new HTCOneM7();
        }
        public override MobilePhone4G CreatePhone4G()
        {
            return new HTCOneM8();
        }
    }
    class MicrosoftFactory : Factory
    {
        public override MobilePhone3G CreatePhone3G()
        {
            return new Lumia820();
        }
        public override MobilePhone4G CreatePhone4G()
        {
            return new Lumia920();
        }
    }
    abstract class MobilePhone3G
    {
        public abstract void Call();
        public abstract void SendMSG();
    }


    class Iphone4S : MobilePhone3G
    {
        public override void Call()
        {
            Console.WriteLine("用Iphone4S打电话");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用Iphone4S发短信");
        }
    }

    class GalaxyNote2 : MobilePhone3G
    {
        public override void Call()
        {
            Console.WriteLine("用GalaxyNote2打电话");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用GalaxyNote2发短信");
        }
    }

    class HTCOneM7 : MobilePhone3G
    {
        public override void Call()
        {
            Console.WriteLine("用HTCOneM7打电话");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用HTCOneM7发短信");
        }
    }

    class Lumia820 : MobilePhone3G
    {
        public override void Call()
        {
            Console.WriteLine("用Lumia820打电话");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用Lumia820发短信");
        }
    }

    abstract class MobilePhone4G
    {
        public abstract void Call();
        public abstract void SendMSG();
    }


    class Iphone6 : MobilePhone4G
    {
        public override void Call()
        {
            Console.WriteLine("用Iphone6打电话");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用Iphone6发短信");
        }
    }

    class GalaxyNote4 : MobilePhone4G
    {
        public override void Call()
        {
            Console.WriteLine("用GalaxyNote4打电话");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用GalaxyNote4发短信");
        }
    }

    class HTCOneM8 : MobilePhone4G
    {
        public override void Call()
        {
            Console.WriteLine("用HTCOneM8打电话");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用HTCOneM8发短信");
        }
    }

    class Lumia920 : MobilePhone4G
    {
        public override void Call()
        {
            Console.WriteLine("用Lumia920打电话");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用Lumia920发短信");
        }
    }

这样,就算我们要添加一类新的手机品牌,也能够从容应对了。

UML图:

吐槽:

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

该模式的优点:

抽象工厂模式的主要优点是隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。

所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。

该模式的缺点:

抽象工厂模式的缺点是在添加新的产品对象时,难以扩展抽象工厂以便生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来很多不便。

开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)

使用情景:

一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都很重要。 系统有多于一个的产品族,而客户端只消费其中某一产品族。 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

note:一个程序员如果从来没有熬夜写程序的经历,不能算是一个好程序员。因为他没有痴迷过,所以不会有大成就。