有一天,我想买一台微软的Microsoft Lumia820的手机,那么手机工厂如何提供一个方法让我简单方便地选择这款手机呢?我们可以用简单工厂模式实现这个过程。
//==========================================================
class Lumia820 : MobilePhone
{
public override void Call()
{
Console.WriteLine("用Lumia820打电话");
}
public override void SendMSG()
{
Console.WriteLine("用Lumia820发短信");
}
}
//==========================================================
class Program
{
static void Main(string[] args)
{
MobilePhone ph;
ph = SimpleFactory.CreatePhone("Lumia820");
ph.Call();
ph.SendMSG();
Console.ReadKey();
}
}
//==========================================================
class SimpleFactory
{
static MobilePhone ph;
public static MobilePhone CreatePhone(string phonename)
{
switch (phonename)
{
case "Iphone4S":
ph = new Iphone4S();
break;
case "GalaxyNote2":
ph = new GalaxyNote2();
break;
case "HTCOneM7":
ph = new HTCOneM7();
break;
case "Lumia820":
ph = new Lumia820();
break;
default:
break;
}
return ph;
}
}
那这个时候如果我不想要这台手机了,我想买一台Iphone4S,该怎么来创建新的手机对象呢?这样我们不可避免的要修改工厂类。
扩展新的功能却要影响到之前已经写好的代码,这不满足开放封闭原则。那么有没有一种新的办法让我们不需要修改原来的代码又可以创建出新的收集对象的实例呢?
我们可以创建一个手机工厂类,管理各个手机工厂,每个不同的手机工厂负责创建不同品牌的手机。这些不同品牌的手机都继承自手机类。
class Program
{
static void Main(string[] args)
{
Factory f = new MicrosoftFactory(); // AppleFactory
MobilePhone ph = f.CreatePhone();
ph.Call();
ph.SendMSG();
Console.ReadKey();
}
}
abstract class Factory
{
public abstract MobilePhone CreatePhone();
}
class AppleFactory : Factory
{
public override MobilePhone CreatePhone()
{
return new Iphone4S();
}
}
class SamsungFactory : Factory
{
public override MobilePhone CreatePhone()
{
return new GalaxyNote2();
}
}
class HTCFactory : Factory
{
public override MobilePhone CreatePhone()
{
return new HTCOneM7();
}
}
class MicrosoftFactory : Factory
{
public override MobilePhone CreatePhone()
{
return new Lumia820();
}
}
abstract class MobilePhone
{
public abstract void Call();
public abstract void SendMSG();
}
class Iphone4S : MobilePhone
{
public override void Call()
{
Console.WriteLine("用Iphone4S打电话");
}
public override void SendMSG()
{
Console.WriteLine("用Iphone4S发短信");
}
}
class GalaxyNote2 : MobilePhone
{
public override void Call()
{
Console.WriteLine("用GalaxyNote2打电话");
}
public override void SendMSG()
{
Console.WriteLine("用GalaxyNote2发短信");
}
}
class HTCOneM7 : MobilePhone
{
public override void Call()
{
Console.WriteLine("用HTCOneM7打电话");
}
public override void SendMSG()
{
Console.WriteLine("用HTCOneM7发短信");
}
}
class Lumia820 : MobilePhone
{
public override void Call()
{
Console.WriteLine("用Lumia820打电话");
}
public override void SendMSG()
{
Console.WriteLine("用Lumia820发短信");
}
}
父类负责定义创建对象的公共接口,而子类则负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成,即由子类来决定究竟应该实例化(创建) 哪一个类。
这样如果我们要添加新的品牌的手机,只需要添加一个新的手机品牌的类继承自手机类,再添加一个手机工厂类继承自手机工厂类,而不需要对原有的正确代码进行修改。
实现了对添加开放,对修改封闭。
UML图:
开放封闭原则(OCP,Open Closed Principle)是所有面向对象原则的核心。软件设计本身所追求的目标就是封装变化、降低耦合,而开放封闭原则正是对这一目标的最直接体现。 关于开放封闭原则,其核心的思想是: 软件实体应该是可扩展,而不可修改的。 对扩展是开放的,而对修改是封闭的。
对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。 对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。
实现开放封闭的核心思想就是对抽象编程,而不对具体编程,因为抽象相对稳定。让类依赖于固定的抽象,所以对修改就是封闭的;而通过面向对象的继承和对多态机制,可以实现对抽象体的继承,通过覆写其方法来改变固有行为,实现新的扩展方法,所以对于扩展就是开放的。这是实施开放封闭原则的基本思路。
简单工厂模式如果需要增加新类型,那么需要修改工厂类的代码,这就使得整个设计在一定程度上违反了“开放封闭原则”。我们定义一个抽象的工厂类,而定义具体的工厂类来实现这个抽象按钮工厂类中定义的方法。抽象化的结果使这种结构可以在不修改具体工厂类的情况下引进新的产品。这一特点使得工厂方法模式具有超越简单工厂模式的优越性。
工厂方法模式是简单工厂模式的延伸,它继承了简单工厂模式的优点,同时还弥补了简单工厂模式的不足。工厂方法模式是使用频率最高的设计模式之一,是很多开源框架和API类库的核心模式。
该模式的优点:
在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类被实例化这一细节,用户只需要关心所需产品对应的工厂,无需关心创建产品的细节,甚至无需知道产品类的类名。 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。
使用工厂方法模式的另一个优点是在系统中加入新产品时,无需修改抽象工厂和抽象产品提供的接口,无需修改客户端,也无需修改其它的具体工厂和具体产品,而只要添加一个新的具体工厂和具体产品即可。
使用工厂方法模式的另一个优点是在系统中加入新产品时,无需修改抽象工厂和抽象产品提供的接口,无需修改客户端,也无需修改其它的具体工厂和具体产品,而只要添加一个新的具体工厂和具体产品即可。
该模式的缺点:
在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,类成对增加,将导致系统设计较为庞大,且运行时系统会有额外的开销。 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现的时候可能需要用到反射等技术,增加了系统的实现难度。
适用场景:
1、不能清楚知道所必须创建的对象的类。
2、一个类希望由它的子类来指定它所创建的对象。
3、将创建对象的职责委托给多个子类中的某一个,且不同子类提供不同实现。
本来想自己总结的,结果发现自己写不出书上那么有逻辑性的话。真是菜。