简单工厂
简介
简单工厂通过一个单独的工厂类来创建不同类型的对象,根据客户端的需求决定创建哪种产品类的实例。
简单工厂模式封装了对象的创建过程,使得客户端不需要知道具体的对象创建细节,只需与工厂类交互即可获得所需的对象。
简单工厂模式是工厂模式家族中最简单实用的模式之一,可理解为工厂模式的一种特殊实现。
简单工厂模式不属于23种GOF设计模式之一。
示例
假设你是一个咖啡店的顾客,你到咖啡店里想要点一杯咖啡。在咖啡店里,有一个咖啡师负责制作各种类型的咖啡,比如美式咖啡、拿铁、卡布奇诺等等。
当你告诉咖啡师你想要什么样的咖啡时,比如说你要一杯拿铁,咖啡师就会根据你的要求准备一杯拿铁咖啡给你,而你不需要知道拿铁咖啡是如何制作的,也不需要知道咖啡师的具体操作步骤,只需要告诉咖啡师你的需求,咖啡师就会为你制作出符合你要求的咖啡。
在这个例子中,咖啡师可以被视为一个简单工厂,他负责根据顾客的需求制作不同类型的咖啡。顾客不需要知道咖啡是如何制作的,也不需要知道咖啡师的具体操作步骤,只需要告诉咖啡师自己想要什么样的咖啡,咖啡师就会为顾客提供相应的咖啡。
using System; // 定义咖啡类 public abstract class Coffee { public abstract void Brew(); } // 定义不同类型的咖啡类 public class Americano : Coffee { public override void Brew() { Console.WriteLine("制作美式咖啡"); } } public class Latte : Coffee { public override void Brew() { Console.WriteLine("制作拿铁咖啡"); } } public class Cappuccino : Coffee { public override void Brew() { Console.WriteLine("制作卡布奇诺咖啡"); } } // 定义咖啡工厂类 public class CoffeeFactory { // 根据咖啡类型创建对应的咖啡对象 public static Coffee CreateCoffee(string type) { switch (type.ToLower()) { case "americano": return new Americano(); case "latte": return new Latte(); case "cappuccino": return new Cappuccino(); default: throw new ArgumentException("不支持的咖啡类型"); } } } class Program { static void Main(string[] args) { // 客户点一杯拿铁 Coffee latte = CoffeeFactory.CreateCoffee("latte"); latte.Brew(); // 客户点一杯美式 Coffee americano = CoffeeFactory.CreateCoffee("americano"); americano.Brew(); // 客户点一杯卡布奇诺 Coffee cappuccino = CoffeeFactory.CreateCoffee("cappuccino"); cappuccino.Brew(); } }
缺点
-
违反开闭原则(OCP):当需要添加新的产品类型时,通常需要修改工厂类的代码,这违反了开闭原则,即系统应该对扩展开放,对修改关闭的原则。
-
责任过重:简单工厂模式的工厂类负责创建多种产品类型的对象,导致工厂类的责任过重,随着产品类型的增多,工厂类的代码可能会变得庞大、复杂,不利于维护和扩展。
-
耦合度高:客户端代码与具体产品类型紧密耦合,因为客户端需要知道可用的产品类型,并且直接依赖于工厂类来创建对象,导致了耦合度的增加。
工厂模式
在工厂方法模式中,每个具体产品都有对应的工厂类,工厂类负责创建特定类型的产品对象。这样一来,当需要添加新的产品类型时,只需创建对应的新产品类和工厂类即可,无需修改原有的工厂类,符合开闭原则。
以咖啡为例,工厂方法模式中可能会有多个工厂类,比如美式咖啡工厂、拿铁咖啡工厂、卡布奇诺咖啡工厂等,每个工厂类负责创建对应类型的咖啡对象。这样,当需要添加新类型的咖啡时,只需创建新的具体产品类和对应的工厂类,不会影响已有的代码结构,实现了系统的可扩展性和维护性。
using System; // 定义咖啡接口 public interface ICoffee { void Brew(); } // 具体的咖啡类 public class Americano : ICoffee { public void Brew() { Console.WriteLine("制作美式咖啡"); } } public class Latte : ICoffee { public void Brew() { Console.WriteLine("制作拿铁咖啡"); } } public class Cappuccino : ICoffee { public void Brew() { Console.WriteLine("制作卡布奇诺咖啡"); } } // 定义咖啡工厂接口 public interface ICoffeeFactory { ICoffee CreateCoffee(); } // 具体的咖啡工厂类 public class AmericanoFactory : ICoffeeFactory { public ICoffee CreateCoffee() { return new Americano(); } } public class LatteFactory : ICoffeeFactory { public ICoffee CreateCoffee() { return new Latte(); } } public class CappuccinoFactory : ICoffeeFactory { public ICoffee CreateCoffee() { return new Cappuccino(); } } class Program { static void Main(string[] args) { // 创建美式咖啡 ICoffeeFactory americanoFactory = new AmericanoFactory(); ICoffee americano = americanoFactory.CreateCoffee(); americano.Brew(); // 创建拿铁咖啡 ICoffeeFactory latteFactory = new LatteFactory(); ICoffee latte = latteFactory.CreateCoffee(); latte.Brew(); // 创建卡布奇诺咖啡 ICoffeeFactory cappuccinoFactory = new CappuccinoFactory(); ICoffee cappuccino = cappuccinoFactory.CreateCoffee(); cappuccino.Brew(); } }
优点:
- 符合开闭原则(OCP):工厂方法模式允许系统在不修改现有代码的情况下引入新的产品类型,通过添加新的具体工厂类和产品类来扩展系统,因此符合开闭原则。
- 降低了客户端与具体产品类之间的耦合:客户端只依赖于抽象的工厂接口和产品接口,不需要直接与具体的产品类耦合,从而降低了耦合度,提高了系统的灵活性和可维护性。
- 具体产品的创建延迟到具体工厂类:工厂方法模式将具体产品的创建推迟到具体工厂类中,每个具体工厂类负责创建特定类型的产品对象,使得系统的结构更加清晰,易于理解和扩展。
缺点:
- 类的数量增加:工厂方法模式引入了多个工厂类和产品类,导致了类的数量增加,增加了系统的复杂度。
- 可能会导致类的层次结构复杂化:如果产品类的种类过多,可能会导致工厂类的层次结构变得复杂,不利于系统的管理和维护。
- 每个具体产品都需要一个具体工厂类:每种具体产品都需要对应的具体工厂类,当产品种类较多时,可能会导致工厂类的数量增加,不利于系统的管理和维护。