简单工厂模式
一般是一个工厂类对应多个具体产品类,通过外界向工厂传递的参数来判断创建某一个具体的产品类。
既然被叫做“工厂”当然不能只生产一样产品,简单工厂只生产同一家族的产品,具体的说就是简单工厂创建的类都是从同一个抽象继承下来的。根据客户不同的需求来创建不同的类,可是被创建的类都必须满足一个条件:必须是同一家族的产品(从同一个根继承下来的子类)。例如:有一个生产水果的简单工厂,根据客户的需要可以生产苹果、橘子、葡萄、香蕉,但是必须满足一个要求,就是它只能生产水果。如果客户需要机器、房屋等东西,那么这些要求都将不能被满足.
简单工厂结构简单,由三个部分构成:
类工厂 : 是最核心的部分,作为简单工厂对外使用的接口,负责实现创建实例的逻辑
抽象产品: 工厂生产所有的产品的抽象 ,可能是抽象类或接口,也可能是普通的基类
具体产品: 简单工厂创建的具体类的实例
举例如下:
public interface Fruit{
}
public class Apple implement Fruit{
}
public class Orange implement Fruit{
}
public class SimpleFactory{
public static final APPLE = 1;
public static final ORANGE = 2;
public Fruit createFruit(int type){
switch(type){
case APPLE: return new Orange();
case ORANGE: return new Apple();
}
}
评价:
Fruit 就是抽象产品, Apple 和Orange是具体产品,SimpleFactory为类工厂,是最核心的功能.所有的核心功能都是靠工厂类实现的,如根据条件判断创建哪种具体的产品,以及实际创建产品等。在这一点上违背了“对象的职责均衡分布的原则”,因为功能过于集中在工厂类本身,随着简单工厂生产的产品种类的增加,使其业务逻辑无限的增加,会使其本身越来越复杂而难于维护和扩展。
缺点:随着产品种类增加使其越来越难以使用
优点:与工厂方法和抽象工厂相比, 其优势是简单易用, 只靠一个工厂类就可以创建所有的产品类
适用场合:当工厂只生产同一品种的具体产品,而且产品数量有限的时候,可以考虑使用此工厂模式。
Factory Method模式
在工厂父类中定义一个标准的方法用来生产产品。一般来说这个方法应该被声明成抽象方法(当工厂父类是抽象类的时候),或接口中的空方法(工厂父类仅仅是接口),这个方法只有方法的定义并没有具体实现。将这个方法的具体实现延迟到子类中来完成。这样父类只需要负责取出抽象的产品,而不必关心怎么去创建具体的产品和到底创建哪一种具体的产品。至于究竟应该创建何种具体的产品由具体的子类负责决定。考虑到简单工厂模式中因为功能过于集中在工厂类中而产生的种种的缺陷,在Factory Method模式中把工厂类生产产品的定义和生产具体产品的实现拆分开,用一个类的继承体系来消除工厂类中复杂的逻辑判断语句。从而使类的职责、能力能够比较均衡的分布。
Factory Method结构由四个部分构成:
抽象类工厂 : 定义统一的接口来创建产品。
具体类工厂 :实现创建具体产品类的类工厂(一般为多个)。
抽象产品: 工厂生产所有产品的抽象 ,可能是抽象类或接口,也可能是普通的基类。
具体产品: Factory Method创建的具体类的实例(多个)。
举例如下:
public interface AbstractFactory{
public Fruit create();
}
public class AppleFactory implement AbstractFactory{
public Fruit create(){
return new Apple();
}
}
public class OrangeFactory implement AbstractFactory{
public Fruit create(){
return new Orange();
}
}
评价:
如此, 客户端程序可以通过更改创建产品的工厂类的子类,用统一的方式创建不同的具体产品。即使需要增加生产新的产品也不需要修改现有的代码,只须创建一个生产这个产品的子工厂类。前提是这个新产品和原来工厂生产的产品必须是一类的(接口必须是一致的)。
优势:
因为生产具体产品是靠子工厂类实现的,增加新的产品不会影响到现有的程序,从这点上来看程序是“闭合”的。修改子工厂类的实现方式也不会影响客户端的使用。
缺点:
在工厂方法模式中因为所有的具体产品都是同一个父类(或接口)继承下来的,它只能生产“同一种类”的具体产品。比如上例:这个工厂只能生产各种类的Fruit, 如果你需要食物、汽车和电子产品的话,那么上面的工厂方法模式是不可能满足你的。
还有因为在客户端调用此模式生产产品的时候是直接使用的子工厂类,如果需要修改生产产品的种类的话,则需要修改客户端的代码,这点有些不满足面向抽象的原则。如果要解决这种问题那就需要和别的设计模式结合起来使用。
Abstract Factory模式
上面讲的工厂模式并不能够生产不同种类的产品,为了解决这个问题,就需要使用Abstract Factory模式 。抽象工厂模式和工厂方法模式有了很大的不同。Abstract Factory模式的目的提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。使用抽象工厂创建的产品是“产品族”,也就是两族或两族以上的产品,并且这些产品是“相关”的、“相互依赖”的。如果只生产一族产品,抽象工厂模式就完全退化成了工厂方法模式。
所以抽象工厂使用的前提条件有两个:
1、生产产品族大于一族,只有生产两族以上的产品才使用抽象工厂。
2、产品之间有特殊的相关或依赖关系,产品之间最少应该有两种关系;
纵向来看每种产品组内部产品之间有继承关系。例如:产品AbstractProductA与ProductA1和ProductA2之间有继承关系是同一产品族产品;
横向来看两个产品族之间的产品也应该有一一对应关系,例如:ProductA1与ProductB1之间,或ProductA2与ProductB2之间的对应关系。在只满足条件1的前提下,感觉应该使用多个工厂方法模式来代替抽象工厂模式,这样使用起来应该会方便一些。
举例如下:
using System;
// "AbstractFactory"
abstract class ContinentFactory
{
// Methods
abstract public Herbivore CreateHerbivore();
abstract public Carnivore CreateCarnivore();
}
// "ConcreteFactory1"
class AfricaFactory : ContinentFactory
{
// Methods
override public Herbivore CreateHerbivore()
{
return new Wildebeest();
}
override public Carnivore CreateCarnivore()
{
return new Lion();
}
}
// "ConcreteFactory2"
class AmericaFactory : ContinentFactory
{
// Methods
override public Herbivore CreateHerbivore()
{
return new Bison();
}
override public Carnivore CreateCarnivore()
{
return new Wolf();
}
}
// "AbstractProductA"
abstract class Herbivore
{
abstract public void Eat();
}
// "AbstractProductB"
abstract class Carnivore
{
// Methods
abstract public void Eat( Herbivore h );
}
// "ProductA1"
class Wildebeest : Herbivore
{
override public void Eat()
{
Console.WriteLine(this + "eats Africa's Glass");
}
}
// "ProductB1"
class Lion : Carnivore
{
// Methods
override public void Eat( Herbivore h )
{
// eat wildebeest
Console.WriteLine( this + " eats " + h );
}
}
// "ProductA2"
class Bison : Herbivore
{
override public void Eat()
{
Console.WriteLine(this + "eats American's Glass");
}
}
// "ProductB2"
class Wolf : Carnivore
{
// Methods
override public void Eat( Herbivore h )
{
// Eat bison
Console.WriteLine( this + " eats " + h );
}
}
// "Client"
class AnimalWorld
{
// Fields
private Herbivore herbivore;
private Carnivore carnivore;
// Constructors
public AnimalWorld( ContinentFactory factory )
{
carnivore = factory.CreateCarnivore();
herbivore = factory.CreateHerbivore();
}
// Methods
public void RunFoodChain()
{
herbivore.Eat();
carnivore.Eat( herbivore );
}
}
/// <summary>
/// GameApp test class
/// </summary>
class GameApp
{
public static void Main( string[] args )
{
// Create and run the Africa animal world
ContinentFactory africa = new AfricaFactory();
AnimalWorld world = new AnimalWorld( africa );
world.RunFoodChain();
// Create and run the America animal world
ContinentFactory america = new AmericaFactory();
world = new AnimalWorld( america );
world.RunFoodChain();
Console.Read();
}
}