旧游无处不堪寻
无寻处,惟有少年心
设计模式-工厂方法

创建型模式是为了绕开 new 来避免对象创建过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。他是接口抽象之后的第一步工作。

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。

解释


工厂方法模式建议使用特殊的工厂方法代替对于对象构造函数的直接调用(即使用 new 运算符)。对象仍将通过 new 运算符创建,只是将对象的构造函数改在工厂方法中调用。工厂方法返回的对象通常被称作产品

注意: 仅当这些产品具有共同的基类或者接口时,子类才能返回不同类型的产品。

基类中的工厂方法的返回类型为公共接口

上述示例为: 卡车 Truck 和轮船 Ship 类都必须实现运输 Transport 接口,该接口声明了一个名为 deliver 交付的方法。每个类都将以不同的方式实现该方法。陆路运输 Road­Logistics 类中的工厂方法返回卡车对象,而海路运输 Sea­Logistics 类则返回轮船对象。

工厂方法模式 UML


适用场景


  1. 当你在编写代码的过程中,如果无法预知对象确切类别及其依赖关系时,可使用工厂方法
  2. 如果你希望用户能扩展你软件库或框架的内部组件,可使用工厂方法
  3. 如果你希望复用现有对象来节省系统资源,而不是每次都重新创建对象,可使用工厂方法

代码示例


using System;
namespace FactoryMethodPatternDemo
{
// creator
abstract class Creator
{
public abstract IProduct FactoryMethod();

public string SomeOperation()
{
var product = FactoryMethod();
var result = "Creator: The same creator's code has just worked with "
+ product.Operation();

return result;
}
}

class ConcreteCreator1 : Creator
{
public override IProduct FactoryMethod()
{
return new ConcreteProduct1();
}
}

class ConcreteCreator2 : Creator
{
public override IProduct FactoryMethod()
{
return new ConcreteProduct2();
}
}

// product
public interface IProduct
{
string Operation();
}

class ConcreteProduct1 : IProduct
{
public string Operation()
{
return "{Result of ConcreteProduct1}";
}
}
class ConcreteProduct2 : IProduct
{
public string Operation()
{
return "{Result of ConcreteProduct2}";
}
}

// client
class Client
{
public void Main()
{
Console.WriteLine("App: Launched with the ConcreteCreator1.");
ClientCode(new ConcreteCreator1());

Console.WriteLine("");
Console.WriteLine("App: Launched with the ConcreteCreator2.");
ClientCode(new ConcreteCreator2());
}

public void ClientCode(Creator creator)
{
// ...
Console.WriteLine("Client: I'm not aware of the creator's class," +
"but it still works.\n" + creator.SomeOperation());
// ...
}
}

// program
class Program
{
static void Main(string[] args)
{
new Client().Main();
// output

// App: Launched with the ConcreteCreator1.
// Client: I'm not aware of the creator's class, but it still works.
// Creator: The same creator's code has just worked with {Result of ConcreteProduct1}

// App: Launched with the ConcreteCreator2.
// Client: I'm not aware of the creator's class, but it still works.
// Creator: The same creator's code has just worked with {Result of ConcreteProduct2}
}

}
}