我正在编写一个设计模式的解释和代码示例,试图帮助身边的人掌握它(同时也帮助自己掌握该模式)。
我想要的是对我的解释和代码示例的意见或批评...谢谢!
工厂模式是什么? 工厂模式利用特定的“对象创建对象”来处理对象的创建和实例化,类似于现实世界中的工厂。
现实世界的例子 想象一下汽车工厂是各种类型汽车的制造商。汽车工厂的其中一条生产线可能在某一天生产卡车,但在另一天可能会重新配置为生产汽车。假设一家经销商向其指定的客户处理部门订购了10辆汽车。然后该部门使用特定的工厂并订购了这10辆汽车。客户处理人员不关心制作汽车本身(想象一下可怜的结果),他们只处理最终产品,确保经销商获得他们的车辆。
接下来的一年里,同样的车型推出了新款,并开始大量订购。客户处理人员(仍然不关心汽车的生产)下订单,但现在他们收到的汽车是不同的,组装方法甚至可能完全不同,但客户处理人员不需要担心这一点。另一个想法是,汽车制造商可能知道如果某个客户处理人员下订单时应该采取什么行动(例如,客户处理人员X下订单,工厂组装者知道他们为客户处理人员X生产10辆Y型车)。另一种选择可能是客户处理人员告诉组装者要生产什么类型的车辆。
如果客户处理人员也负责车辆的创建(即它们被耦合在一起),每当车辆以任何方式更改时,每个客户处理人员都必须接受重新培训以生产该车辆。这将导致质量问题,因为客户处理人员比工厂数量多得多...错误将会发生,费用将会大大增加。
回到面向对象编程 将对象工厂作为应用于软件工程的设计模式与上述概念类似...工厂生产各种其他对象,您可以使用组装线(对象组装器)生产特定类型的对象,并以特定方式返回。组装器可以检查请求的客户端并处理,或者客户端可能会告诉组装器它需要哪个对象。现在...您正在一个项目中创建一个对象工厂和各种组装器,项目在未来的某个时间里需求稍有变化,您现在被要求更改对象内容以及客户端如何处理该对象。由于您使用了工厂模式,这是一个简单的更改,并且可以在一个位置更改或添加工厂生产的对象,并更改组装器将对象内容布局的格式。
使用工厂方法的不幸方式是在客户端中实例化每个对象实例并格式化对象内容……假设您在20个客户端中使用了此特定对象。现在,您必须转到每个客户端,更改每个对象实例和格式……多么浪费时间…要懒惰……第一次就用正确的方法,这样您就可以节省自己(和其他人)的时间和精力。
代码示例(C#) 以下是使用工厂来制作食物和各种食物对象的示例
我想要的是对我的解释和代码示例的意见或批评...谢谢!
工厂模式是什么? 工厂模式利用特定的“对象创建对象”来处理对象的创建和实例化,类似于现实世界中的工厂。
现实世界的例子 想象一下汽车工厂是各种类型汽车的制造商。汽车工厂的其中一条生产线可能在某一天生产卡车,但在另一天可能会重新配置为生产汽车。假设一家经销商向其指定的客户处理部门订购了10辆汽车。然后该部门使用特定的工厂并订购了这10辆汽车。客户处理人员不关心制作汽车本身(想象一下可怜的结果),他们只处理最终产品,确保经销商获得他们的车辆。
接下来的一年里,同样的车型推出了新款,并开始大量订购。客户处理人员(仍然不关心汽车的生产)下订单,但现在他们收到的汽车是不同的,组装方法甚至可能完全不同,但客户处理人员不需要担心这一点。另一个想法是,汽车制造商可能知道如果某个客户处理人员下订单时应该采取什么行动(例如,客户处理人员X下订单,工厂组装者知道他们为客户处理人员X生产10辆Y型车)。另一种选择可能是客户处理人员告诉组装者要生产什么类型的车辆。
如果客户处理人员也负责车辆的创建(即它们被耦合在一起),每当车辆以任何方式更改时,每个客户处理人员都必须接受重新培训以生产该车辆。这将导致质量问题,因为客户处理人员比工厂数量多得多...错误将会发生,费用将会大大增加。
回到面向对象编程 将对象工厂作为应用于软件工程的设计模式与上述概念类似...工厂生产各种其他对象,您可以使用组装线(对象组装器)生产特定类型的对象,并以特定方式返回。组装器可以检查请求的客户端并处理,或者客户端可能会告诉组装器它需要哪个对象。现在...您正在一个项目中创建一个对象工厂和各种组装器,项目在未来的某个时间里需求稍有变化,您现在被要求更改对象内容以及客户端如何处理该对象。由于您使用了工厂模式,这是一个简单的更改,并且可以在一个位置更改或添加工厂生产的对象,并更改组装器将对象内容布局的格式。
使用工厂方法的不幸方式是在客户端中实例化每个对象实例并格式化对象内容……假设您在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