创建型模式抽象了对象的创建(实例化)过程。类创建型模式使用继承改变被实例的类, 对象创建型模式将对象的创建的工作延迟到另一个对象中。通过对象创建模式绕开new,避免对象创建过程(new)的中紧耦合。
一、意图
提供一个创建一系列相关或互相依赖的对象的接口(提供创建对象的接口),而无需指定它们的具体类。
二、动机
在软件系统中,经常面临着一系列互相依赖的对象的创建工作。同时,由于需求的变化,往往存在更多系列对象的创建工作。
三、适用性
-
一个系统要独立于它的产品的创建,组合和表示时。
-
一个系统要由多个产品系列中的一个来配置时。
-
当强调一系列相关产品对象的设计以便进行联合使用时。
-
当你提供一个产品类库,而只想显示它们的接口而不是实现时。
四、效果
- (优点)分离了具体类(通过抽象类)。
- (优点)易于改变产品系列。
- (优点)有利于产品的一致性(当一个系列的产品对象被设计成一起工作时,客户程序一次只能使用同一个系列中的对象)。
- (缺点)难以支持新种类的产品。
五、代码示例
想象一个场景,一个工厂专门生产小米手机、小米移动电源、小米数据线。客户程序我们可能写成如下。
using System;
namespace AbstractFactory
{
class Client
{
static void Main(string[] args)
{
MakeLine makeLine = new MakeLine();//依赖具体类MakeLine
Console.WriteLine(makeLine.print());
MakePhone makePhone = new MakePhone();//依赖具体类MakePhone
Console.WriteLine(makePhone.print());
MakePower makePower = new MakePower();//依赖具体类MakePower
Console.WriteLine(makePower.print());
Console.ReadLine();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace AbstractFactory
{
class MakePhone
{
public string print()
{
return "生产小米手机";
}
}
class MakePower
{
public string print()
{
return "生产小米电源";
}
}
class MakeLine
{
public string print()
{
return "生产小米数据线";
}
}
}
如果我们现在想增加生产华为的手机、移动电源、数据线怎么办?首先我们增加三个类分别生产华为的手机、电源、数据线。然后客户端也要进行进行修改,增加实例化华为三个类的实例化。这就违背了之前的依赖倒置设计原则:高层模块不应该依赖底层模块,二者都应该依赖于抽象。
改良后:
using System;
namespace AbstractFactoryImprove
{
class Client
{
static void Main(string[] args)
{
IFactory factory = new FactoryA();//依赖抽象
Console.WriteLine(factory.makePhone().Print());
Console.WriteLine(factory.makePower().Print());
Console.WriteLine(factory.makeLine().Print());
Console.ReadLine();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace AbstractFactoryImprove
{
abstract class IFactory
{
public abstract IMakePhone makePhone();
public abstract IMakePower makePower();
public abstract IMakeLine makeLine();
}
abstract class IMakePhone
{
abstract public string Print();
}
abstract class IMakePower
{
abstract public string Print();
}
abstract class IMakeLine
{
abstract public string Print();
}
class FactoryA_MakePhone : IMakePhone
{
public override string Print()
{
return "生产小米手机";
}
}
class FactoryA_MakePower : IMakePower
{
public override string Print()
{
return "生产小米电源";
}
}
class FactoryA_MakeLine : IMakeLine
{
public override string Print()
{
return "生产小米数据线";
}
}
class FactoryA : IFactory
{
public override IMakeLine makeLine()
{
return new FactoryA_MakeLine();
}
public override IMakePhone makePhone()
{
return new FactoryA_MakePhone();
}
public override IMakePower makePower()
{
return new FactoryA_MakePower();
}
}
}
修改之后我们想增加华为的生产线,我们只需在底层增加四个类FactoryB、FactoryB_MakeLine、FactoryB_MakePower、FactoryB_MakePhone,客户端不需要改变,只需要传给它FactoryB的实例就可以,因为依赖的是抽象类(运行时依赖),在运行时你给我什么,我用什么,而没改良之前的代码,运行时是不能改变的。
我们再来看上面说的抽象工厂的缺点:难以支持新种类的产品。假如现在我们想生产手机壳,那么我就需要改变IFactory和所有继承它的子类,这种情况就不适合抽象工厂了。
“一系列”怎么理解呢,小米手机、小米电源、小米线是一个牌子的,有关联。
(学习笔记,仅供参考。走火入魔,概不负责。如有错误,谢谢指出。^_^)