New
这是一个典型的情况, 我们需要在运行时来实例化一些具体的类. 在需要修改或者扩展的时候我们就需要改这段代码. 一个程序中可能会多次出现类似的代码, 这使得维护和更新非常困难而且容易出错.
通过面向接口的编程, 我们可以把自己从各种变化中隔离出来, 因为如果代码是面向接口的话, 那么通过多态机制, 任何实现了该接口的新类都可以直接被使用.
所以别忘了设计原则: 对修改关闭.
需求
假设你是个披萨店老板, 有以下代码:
这是订购披萨的过程.
而你可能需要多种披萨:
这里就是根据参数来创建不同类型的披萨实例. 然后再进行下一步操作.
但是这样的事情可能会发生: 添加新类型披萨, 淘汰某些类型的披萨.
对代码修修改改. 所以这不是对修改关闭. 上面那部分代码需要修修改改, 下面那部分代码是固定不变的. 那最好的办法就是封装它.
封装对象的创建
需要把变化的部分封装起来, 也就是把创建披萨那部分代码移动到另外一个对象里, 而这个对象将专注于创建披萨.
针对这种对象, 它有一个名字, 叫工厂(Factory). 工厂会处理对象创建的细节.
建立一个简单的披萨工厂
这个类只有一个任务: 为客户创建披萨.
为什么不适用静态(static)方法?
可以使用static方法, 这样的话你就不需要创建一个对象然后再调用方法了. 但是这么做也有一个缺点, 那就是不可以对它继承了, 也无法改变create方法的行为了.
使用SimpleFactory之后:
简单工厂 Simple Factory
简单工厂实际上并不是设计模式, 可以更多的认为是一种编程范式. 但是使用的却是非常广泛.
理清一下目前的情况:
C#实现:
namespace C04FactoryPattern.Bases { public interface IPizza { string Type { get; } void Prepare(); void Bake(); void Cut(); void Box(); } } namespace C04FactoryPattern.Bases { public interface IPizzaStore { Pizza OrderPizza(string type); } } namespace C04FactoryPattern.Bases { public abstract class Pizza: IPizza { public abstract string Type { get;} public void Prepare() { Console.WriteLine($"{Type} is Preparing..."); } public void Bake() { Console.WriteLine($"{Type} is Baking..."); } public void Cut() { Console.WriteLine($"{Type} is Cutting..."); } public void Box() { Console.WriteLine($"{Type} is Boxing..."); } } }
namespace C04FactoryPattern.Models { public class CheesePizza : Pizza { public override string Type => nameof(CheesePizza); } public class ClamPizza : Pizza { public override string Type => nameof(ClamPizza); } public class PepperoniPizza : Pizza { public override string Type => nameof(PepperoniPizza); } public class VeggiePizza : Pizza { public override string Type => nameof(VeggiePizza); } }
namespace C04FactoryPattern.SimpleFactory { public class SimplePizzaFactory { public Pizza CreatePizza(string type) { Pizza pizza = null; switch (type) { case nameof(CheesePizza): pizza = new CheesePizza(); break; case nameof(ClamPizza): pizza = new ClamPizza(); break; case nameof(PepperoniPizza): pizza = new PepperoniPizza(); break; case nameof(VeggiePizza): pizza = new VeggiePizza(); break; } return pizza; } } }
namespace C04FactoryPattern.SimpleFactory { public class PizzaStore: IPizzaStore { private readonly SimplePizzaFactory _factory; public PizzaStore(SimplePizzaFactory factory) { _factory = factory; } public Pizza OrderPizza(string type) { var pizza = _factory.CreatePizza(type); if (pizza != null) { pizza.Prepare(); pizza.Bake(); pizza.Cut(); pizza.Box(); Console.WriteLine($"{type} Done!!!"); } else { Console.WriteLine("We don't have this kind of pizza!!"); } return pizza; } } }
测试:
namespace C04FactoryPattern { class Program { static void Main(string[] args) { Console.WriteLine("Simple Factory:"); PizzaStore pizzaStore = new PizzaStore(new SimplePizzaFactory()); pizzaStore.OrderPizza(nameof(CheesePizza)); pizzaStore.OrderPizza(nameof(PepperoniPizza)); Console.ReadLine(); } } }