【发布时间】:2013-11-01 14:20:56
【问题描述】:
我正在整理这个设计模式的解释和代码示例,试图帮助我周围的其他人掌握它(同时帮助我自己掌握这个模式)。
我正在寻找的是对我的解释和代码示例的意见或批评...谢谢!
什么是工厂模式? 工厂模式利用一个特定的专用“对象创建者对象”来处理对象的创建——以及大多数情况下的实例化——对象,类似于现实世界的工厂。
现实世界的例子
想象一家汽车厂是各种汽车的创造者。该汽车厂的一条装配线可能会在某一天生产一辆卡车,但在另一天可能会重新装配以生产汽车。假设经销商向其指定的客户处理部门订购了 10 辆汽车。然后,该部门利用某家工厂订购了 10 辆汽车。客户处理人员并不关心自己制造汽车(想象一下糟糕的结果),他们只使用最终产品,确保经销商得到他们的车辆。
同一辆车的新车型第二年问世,订单开始涌入。客户处理人员(仍然不关心汽车的生产)下订单,但现在他们收到的汽车不同了,组装方法甚至工厂可能完全不同,但帐户处理程序不必担心这一点。一个额外的想法:车辆的工厂组装商可能确切地知道如果某个账户处理人下订单(即账户处理人 X 下订单,工厂组装商知道对于账户处理人 X,他们生产 10 辆 Y 型车辆)要采取什么行动)。另一种选择可能是帐户处理程序准确地告诉组装商要生产哪种类型的车辆。
如果帐户处理程序还处理车辆的创建(即它们是耦合的),则每次车辆以任何方式发生变化时,每个帐户处理程序都必须重新培训以生产该车辆。这将产生质量问题,因为帐户处理人员的数量远远多于工厂数量......会发生错误,费用会高得多。
回到 OOP
对象工厂作为一种应用于软件工程的设计模式,在概念上类似于上面的示例……工厂生产出各种类型的其他对象,您可以利用生产某种对象类型的装配线(对象装配器),以某种方式。组装器可以检查请求的客户端并处理,或者客户端可以告诉组装器它需要什么对象。现在......您在一个项目中并创建了一个对象工厂和各种组装器,稍后在项目的道路上,需求略有变化,您现在被要求更改对象内容以及其客户如何处理该对象。由于您使用了工厂模式,这是一个简单的更改,并且在一个位置,您可以更改或添加工厂生成的对象,并更改汇编器放置对象内容的格式。
不幸的做法是没有工厂方法,实例化每个对象实例并在客户端本身中格式化对象内容......假设您在 20 个客户端中使用了这个特定对象。现在你必须去找每一个客户,改变每一个对象实例和格式......真是浪费时间......懒惰......第一次做正确的方式,这样你就可以节省自己(和其他人)的时间以后再努力。
代码示例 (C#)
下面是一个利用工厂生产食品和各种食品的例子
Factory module
public enum FoodType
{
//enumerated foodtype value, if client wants to specify type of object, coupling still occurs
Hamburger, Pizza, HotDog
}
/// <summary>
/// Object to be overridden (logical)
/// </summary>
public abstract class Food
{
public abstract double FoodPrice { get; }
}
/// <summary>
/// Factory object to be overridden (logical)
/// </summary>
public abstract class FoodFactory
{
public abstract Food CreateFood(FoodType type);
}
//-------------------------------------------------------------------------
#region various food objects
class Hamburger : Food
{
double _foodPrice = 3.59;
public override double FoodPrice
{
get { return _foodPrice; }
}
}
class Pizza : Food
{
double _foodPrice = 2.49;
public override double FoodPrice
{
get { return _foodPrice; }
}
}
class HotDog : Food
{
double _foodPrice = 1.49;
public override double FoodPrice
{
get { return _foodPrice; }
}
}
#endregion
//--------------------------------------------------------------------------
/// <summary>
/// Physical factory
/// </summary>
public class ConcreteFoodFactory : FoodFactory
{
public override Food CreateFood(FoodType foodType)
{
switch (foodType)
{
case FoodType.Hamburger:
return new Hamburger();
break;
case FoodType.HotDog:
return new HotDog();
break;
case FoodType.Pizza:
return new Pizza();
break;
default:
return null;
break;
}
}
}
/// <summary>
/// Assemblers
/// </summary>
public class FoodAssembler
{
public string AssembleFoodAsString(object sender, FoodFactory factory)
{
Food food = factory.CreateFood(FoodType.Hamburger);
if (sender.GetType().Name == "default_aspx")
{
return string.Format("The price for the hamburger is: ${0}", food.FoodPrice.ToString());
}
else
{
return food.FoodPrice.ToString();
}
}
public Food AssembleFoodObject(FoodFactory factory)
{
Food food = factory.CreateFood(FoodType.Hamburger);
return food;
}
}
Calling factory
FoodFactory factory = new ConcreteFoodFactory(); //create an instance of the factoryenter code here
lblUser.Text = new FoodAssembler().AssembleFoodAsString(this, factory); //call the assembler which formats for string output
Object o = new FoodAssembler().AssembleFoodObject(factory); //example: instantiating anon object, initialized with created food object
【问题讨论】:
-
也许是社区维基?
-
为什么票数接近?这个问题是有效的,虽然它有点长:)
标签: c# design-patterns factory-pattern