工厂模式家族出现了最青春靓丽的三姐妹,有不同的个性和独特的魅力。她们分别是:简单工厂模式、工厂方法模式、抽象工厂模式。从她们诞生到现在,一直都在为面向对象事业打拼并且奉献着……
苹果手机正在一代一代的更新着,据说IPhone6S将要在今年6月份发布。我们不妨自己先生产一些IPhone。就用我们学到的工厂模式吧!
首先要定义一些我们想要的一些苹果手机类,如IPhone4S类、IPhone5S类、IPhone6S类,可见这些类都有一个共同点就是都是苹果公司生产的苹果手机,具有苹果手机的特点和功能,不同的是它们的型号,所以可抽象出一个父类IPhone。这样写成代码如下:
//IPhone手机类
public abstract class IPhone
{
private int type = 0;
public abstract string GetPhone();
}
//子类,得到产品IPhone4
class IPhone4 : IPhone
{
public override string GetPhone()
{
return "出厂的是苹果4S";
}
}
//子类,得到产品iPhone5
class IPhone5 : IPhone
{
public override string GetPhone()
{
return "出厂的是苹果5S";
}
}
//子类,得到产品IPhone6
class IPhone6 : IPhone
{
public override string GetPhone()
{
return "出厂的是苹果6S";
}
}
1、简单工厂模式
简单工厂模式:就是由一个工厂通过传入的参量来决定实例化一个类中的哪一个对象。简单工厂其实并没有用到抽象类,只有一个工厂类MyFactory里面有个工厂放CreateProduct返回一个基类产品 ,具体返回什么具体实例通过传入参数然后用分支语句判断
优点:工厂类包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了类与具体产品的依赖。
缺点:工厂里面是一个选择分支语句,每增加一个类,都要相应的修改工厂类增加分支语句,所以简单工厂模式不符合开放-封闭原则。
结构图:见博客http://blog.csdn.net/xdd19910505/article/details/21477411
用简单工厂来生产苹果手机:
苹果简单工厂就是只有苹果工厂类,工厂方法就是CreatIPhone,参数是IPhone型号,工厂通过型号创建不同的苹果手机,如:IPhone4S、IPhone5S、IPhone6S.。很明显的缺点就是苹果每生产一个苹果就要修改简单工厂类,增加分支语句,这就违反了开放-封闭原则。
苹果简单工厂为:
//苹果简单工厂
public class IPhoneFactory
{
public static IPhone createIPhonetype(int type)
{
IPhone apple = null;
switch (type)
{
case 4:
apple = new IPhone4();
break;
case 5:
apple = new IPhone5();
break;
case 6:
apple = new IPhone6();
break;
}
return apple;
}
}
IPhone apple;
apple = IPhoneFactory.createIPhonetype(4);
Console.WriteLine(apple.GetPhone());
apple = IPhoneFactory.createIPhonetype(5);
Console.WriteLine(apple.GetPhone());
apple = IPhoneFactory.createIPhonetype(6);
Console.WriteLine(apple.GetPhone());
Console.Read();
2、工厂方法模式
工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。使一个类的实例化延迟到其子类。
优点:当需要增加类时,不需要改动原有的工厂类了,只需要增加此功能的具体类和相应的工厂类就可以了,遵循了开放-封闭原则,实现了可扩展。
缺点:工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现具体类,选择判断的问题在客户端上进行,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。想要添加功能类,在简单工厂中改工厂类就可以,而在工厂方法中添加功能类相对应的工厂类还需要修改客户端。
用工厂方法模式来生产苹果手机:
苹果工厂方法模式有一个工厂基类IPhoneFactory,此工厂和上面不一样,是抽象的。该类定义一个虚工厂方法CreateIPhone,返回IPhone基类,然后不同型号的手机对应一个该型号的手机工厂,比如IPhone5Factory,此工厂实现虚工厂方法,返回值是具体的IPhone手机,如CreatePhone5S。优点是新出一个苹果手机型号,只需派生一个该型号的工厂而无需修改原来的代码。符合封闭修改,开放扩展原则。
相关工厂代码如下:
//工厂方法模式 //生产苹果抽象工厂 interface IPhoneFactory { IPhone CreateIPhone(); } //苹果4工厂 class IPhone4Factory:IPhoneFactory { public IPhone CreateIPhone() { return new IPhone4() ; } } //苹果5工厂 class IPhone5Factory :IPhoneFactory { public IPhone CreateIPhone() { return new IPhone5(); } } //苹果6工厂 class IPhone6Factory : IPhoneFactory { public IPhone CreateIPhone() { return new IPhone6(); } }
客户端代码:
IPhone apple3 = appleFactory2.CreateIPhone(); Console.WriteLine(apple3.GetPhone()); Console.Read();
同样的我们依然得到的我们想要的苹果手机。你想要什么型号的苹果手机,只不需要更改工厂内代码,只需要增加想要的手机类和相对应的子工厂即可。
结果为:
3、抽象工厂模式
抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
优点:抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。
缺点:产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。
同样是生产苹果手机的例子:
抽象工厂就不止生产IPhone手机了,还生产相关的周边产品,首先IPhoneFactory基类会定义两个虚方法,一个是CreateIPhone用来生产手机,另一个是CreateIPhoneCharger用于生产对应型号的手机充电器(假定不同型号手机使用不同的充电器)。然后派生类IPhone5SFactory就要生产两种相关的产品,一个是IPhone5S,还有一个是IPhone5sCharger,这两个对象是对应的关系,因此封装到抽象工厂来生产一些列相关的对象。
这时不同与工厂方法模式的地方是增加了充电器类和其相关子类,如IPhoneCharger及其子类IPhone4SCharger、IPhone5SCharger、IPhone6SCharger,工厂也有所不同,比如增加了充电器的工厂。
//抽象工厂模式 //苹果手机接口 interface IPhone { IPhone GetPhone(int type); } //苹果4S类 class IPhone4S :IPhone { public IPhone GetPhone(int type) { Console.WriteLine("出厂的是苹果4S"); return null ; } } //苹果5S、6S类如上4S类 //苹果充电器接口 interface IPhoneCharger { IPhoneCharger GetCharger(int type); } //苹果4S充电器 class IPhone4SCharger :IPhoneCharger { public IPhoneCharger GetCharger(int type) { Console .WriteLine ("生产苹果4S充电器"); return null ; } } //苹果5S、6S充电器如4S类 //工厂类接口 //生产苹果抽象工厂 interface IPhoneFactory { IPhone CreateIPhone(); IPhoneCharger CreateIPhoneCharger(); } //苹果4工厂 class IPhone4Factory:IPhoneFactory { public IPhone CreateIPhone() { return new IPhone4S() ; } public IPhoneCharger CreateIPhoneCharger() { return new IPhone4SCharger (); } } //苹果5工厂 class IPhone5Factory :IPhoneFactory { public IPhone CreateIPhone() { return new IPhone5S(); } public IPhoneCharger CreateIPhoneCharger() { return new IPhone5SCharger (); } } //苹果6工厂同上
IPhoneFactory factory = new IPhone4Factory(); IPhone pingguo = factory.CreateIPhone(); pingguo.GetPhone(4 ); IPhoneCharger applechar = factory.CreateIPhoneCharger(); applechar.GetCharger(4); Console.Read();
小结:
(1)简单工厂 VS. 工厂方法:它们都集中封装了对象的创建,使得要更换对象时,不需要做大的改动就可实现,降低了客户程序与产品对象的耦合。工厂方法模式是简单工厂模式的进一步抽象和推广,由于使用了多态性,工厂方法模式克服了简单工厂违背开放-封闭原则的优点,又保持了封装对象创建过程的优点。
(2) 工厂方法 VS. 抽象工厂:工厂方法模式是一种极端情况的抽象工厂模式,而抽象工厂模式可以看成是工厂方法模式的一种推广。 其实工厂方法模式是用来创建一个产品的等级结构的,而抽象工厂模式是用来创建多个产品的等级结构的。工厂方法创建一般只有一个方法,创建一种产品。抽象工厂一般有多个方法,创建一系列产品。 工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
(3)用最简单的话来概括就是,简单工厂只有一个具体工厂类来创建一种基类的多个不同派生类,工厂方法就是有多个派生于一个基类的具体工厂类,每个具体工厂只生产一种基类的一个派生类,抽象工厂也是只有一个工厂基类,但是每个具体工厂生产多个相关基类的各一个派生类。