工厂模式是一种创建型设计模式,主要将对象的创建和使用分离,使得系统更加灵活和可维护。常见的工厂模式有简单工厂模式、工厂方法模式和抽象工厂模式,以下是 C# 实现的三个案例:
简单工厂模式
简单工厂模式通过一个工厂类来创建对象,而不需要把客户端代码与具体类的实现细节绑定在一起。
using System;
// 1. 定义产品接口
public interface IProduct
{
void Use();
}
// 2. 创建具体产品类
public class ConcreteProductA : IProduct
{
public void Use()
{
Console.WriteLine("using ConcreteProductA");
}
}
public class ConcreteProductB : IProduct
{
public void Use()
{
Console.WriteLine("using ConcreteProductB");
}
}
// 3. 创建工厂类
public class ProductFactory
{
public static IProduct CreateProduct(string type)
{
switch (type)
{
case "a":
return new ConcreteProductA();
case "b":
return new ConcreteProductB();
default:
throw new ArgumentException("unknown product type");
}
}
}
// 4. 运用业务代码
class Program
{
static void Main(string[] args)
{
IProduct productA = ProductFactory.CreateProduct("a");
productA.Use();
IProduct productB = ProductFactory.CreateProduct("b");
productB.Use();
}
}
代码解析:
- 定义了一个
IProduct
接口,其中包含Use
方法,这是所有具体产品类需要实现的功能。 ConcreteProductA
和ConcreteProductB
是具体的产品类,它们实现了IProduct
接口,分别实现了自己的Use
方法。ProductFactory
是工厂类,它的静态方法CreateProduct
根据传入的参数(这里是字符串)来决定创建并返回哪个具体产品类的实例。- 在
Main
方法中,应用业务代码通过调用ProductFactory.CreateProduct
方法来获取产品实例,而不需要关心具体的创建过程,降低了客户端与具体产品类的耦合度。
工厂方法模式
工厂方法模式将对象的创建放在一个接口中,但让子类决定实例化哪一个类,使一个类的实例化延迟到其子类。
using System;
// 1. 定义产品接口
public interface IProduct
{
void Use();
}
// 2. 创建具体产品类
public class ConcreteProductA : IProduct
{
public void Use()
{
Console.WriteLine("using ConcreteProductA");
}
}
public class ConcreteProductB : IProduct
{
public void Use()
{
Console.WriteLine("using ConcreteProductB");
}
}
// 3. 定义抽象工厂类
public abstract class ProductFactory
{
public abstract IProduct CreateProduct();
}
// 4. 创建具体工厂类
public class ConcreteProductAFactory : ProductFactory
{
public override IProduct CreateProduct()
{
return new ConcreteProductA();
}
}
public class ConcreteProductBFactory : ProductFactory
{
public override IProduct CreateProduct()
{
return new ConcreteProductB();
}
}
// 5. 运用业务代码
class Program
{
static void Main(string[] args)
{
ProductFactory factoryA = new ConcreteProductAFactory();
IProduct productA = factoryA.CreateProduct();
productA.Use();
ProductFactory factoryB = new ConcreteProductBFactory();
IProduct productB = factoryB.CreateProduct();
productB.Use();
}
}
代码解析:
- 同样先定义了
IProduct
接口和两个具体的产品类ConcreteProductA
、ConcreteProductB
。 - 新增了一个抽象工厂类
ProductFactory
,其中包含一个抽象方法CreateProduct
,用于创建产品实例。 ConcreteProductAFactory
和ConcreteProductBFactory
是具体的工厂类,它们继承自ProductFactory
并实现了CreateProduct
方法,分别负责创建ConcreteProductA
和ConcreteProductB
的实例。- 在应用业务代码中,通过创建不同的具体工厂类实例,调用其
CreateProduct
方法来获取对应的产品实例。这种方式符合开闭原则,当需要增加新的产品时,只需要新增对应的产品类和工厂类,而无需修改现有的工厂类代码。
抽象工厂模式
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
using System;
// 1. 定义抽象产品接口1
public interface ICar
{
void Drive();
}
// 2. 定义抽象产品接口2
public interface IMotorcycle
{
void Ride();
}
// 3. 创建具体产品类 - 汽车
public class HondaCar : ICar
{
public void Drive()
{
Console.WriteLine("Driving Honda Car");
}
}
public class ToyotaCar : ICar
{
public void Drive()
{
Console.WriteLine("Driving Toyota Car");
}
}
// 4. 创建具体产品类 - 摩托车
public class HondaMotorcycle : IMotorcycle
{
public void Ride()
{
Console.WriteLine("Riding Honda Motorcycle");
}
}
public class ToyotaMotorcycle : IMotorcycle
{
public void Ride()
{
Console.WriteLine("Riding Toyota Motorcycle");
}
}
// 5. 定义抽象工厂接口
public interface IAutoFactory
{
ICar CreateCar();
IMotorcycle CreateMotorcycle();
}
// 6. 创建具体工厂类
public class HondaFactory : IAutoFactory
{
public ICar CreateCar()
{
return new HondaCar();
}
public IMotorcycle CreateMotorcycle()
{
return new HondaMotorcycle();
}
}
public class ToyotaFactory : IAutoFactory
{
public ICar CreateCar()
{
return new ToyotaCar();
}
public IMotorcycle CreateMotorcycle()
{
return new ToyotaMotorcycle();
}
}
// 7. 应用业务代码
class Program
{
static void Main(string[] args)
{
IAutoFactory hondaFactory = new HondaFactory();
ICar hondaCar = hondaFactory.CreateCar();
IMotorcycle hondaMotorcycle = hondaFactory.CreateMotorcycle();
hondaCar.Drive();
hondaMotorcycle.Ride();
IAutoFactory toyotaFactory = new ToyotaFactory();
ICar toyotaCar = toyotaFactory.CreateCar();
IMotorcycle toyotaMotorcycle = toyotaFactory.CreateMotorcycle();
toyotaCar.Drive();
toyotaMotorcycle.Ride();
}
}
代码解析:
- 定义了两个抽象产品接口
ICar
和IMotorcycle
,分别表示汽车和摩托车产品的行为。 - 创建了多个具体产品类,如
HondaCar
、ToyotaCar
、HondaMotorcycle
、ToyotaMotorcycle
,它们分别实现对应的抽象产品接口。 - 抽象工厂接口
IAutoFactory
声明了两个创建产品的方法CreateCar
和CreateMotorcycle
,用于创建汽车和摩托车。 HondaFactory
和ToyotaFactory
是具体的工厂类,实现了IAutoFactory
接口,负责创建对应品牌的汽车和摩托车实例。- 在应用业务代码中,通过选择不同的具体工厂类,可以创建出不同品牌的汽车和摩托车产品,并且这些产品之间是相关联的,比如都是同一品牌下的不同类型交通工具。 当需要增加新的品牌或产品类型时,需要修改抽象工厂接口和所有具体工厂类,这是抽象工厂模式的一个缺点,但它可以确保创建出来的一系列产品的一致性。
简单工厂模式
- 优点 :
- 实现简单:模式结构简单,易于理解和实现,适合初学者快速上手和小型项目开发。
- 解耦对象创建和使用:将对象创建逻辑封装在工厂类中,客户端无需了解具体创建过程,只需与工厂类交互获取对象,降低了客户端与具体产品类的耦合度。
- 便于代码维护:当创建对象的逻辑发生变化时,只需修改工厂类,而无需改动客户端代码,在一定程度上方便了维护。
- 缺点 :
- 违背开闭原则:当需要增加新的产品类型时,必须修改工厂类的代码来添加新的创建逻辑,这可能会引入新的错误,并且违反了软件设计中对扩展开放、对修改关闭的开闭原则。
- 工厂类职责过重:随着产品种类不断增加,工厂类中的条件判断逻辑会变得越来越复杂,导致工厂类难以维护和理解,不符合单一职责原则。
- 应用场景 :
- 产品种类较少且稳定:当项目中需要创建的对象种类较少,且后期很少会有新增产品类型的情况时,简单工厂模式可以很好地简化对象的创建过程。
- 需求变化不大:如果业务需求相对稳定,对软件的扩展性要求不高,使用简单工厂模式可以快速实现对象的创建管理。
工厂方法模式
- 优点 :
- 符合开闭原则:新增产品时,只需创建新的具体产品类和对应的具体工厂类,无需修改现有代码,提高了系统的扩展性和可维护性。
- 责任明确:每个具体工厂类只负责创建一种具体产品,符合单一职责原则,使得代码结构更加清晰,便于理解和维护。
- 解耦程度高:客户端只与抽象工厂类和抽象产品类交互,具体产品的创建过程被完全封装在具体工厂类中,进一步降低了客户端与具体产品的耦合度。
- 缺点 :
- 类数量增多:每增加一种产品,就需要增加一个具体产品类和一个具体工厂类,导致系统中的类数量快速增加,增加了代码的复杂性和管理成本。
- 理解难度增加:由于引入了抽象工厂类和多个具体工厂类,相比简单工厂模式,工厂方法模式的结构更加复杂,需要开发者花费更多时间来理解和掌握。
- 应用场景 :
- 产品不断扩展:适用于产品种类会不断增加和变化的场景,例如电商系统中商品类型的不断扩充。
- 创建逻辑多样化:当不同产品的创建逻辑差异较大时,工厂方法模式可以将不同的创建逻辑分别封装在各自的具体工厂类中,使代码更加清晰。
抽象工厂模式
- 优点 :
- 高度解耦:客户端通过抽象工厂接口获取产品,与具体产品类和具体工厂类的实现细节完全解耦,提高了系统的独立性和可维护性。
- 方便维护产品族:可以轻松地创建一系列相关或相互依赖的产品对象,即产品族,保证了产品族中各个产品之间的一致性和完整性,便于对产品族进行统一管理和维护。
- 易于切换产品族:在运行时可以很方便地切换不同的具体工厂,从而获取不同产品族的对象,增强了系统的灵活性和可扩展性。
- 缺点 :
- 结构复杂:抽象工厂模式涉及多个抽象产品类、具体产品类、抽象工厂类和具体工厂类,结构较为复杂,增加了系统的理解和实现难度。
- 维护成本高:当产品族中需要增加新的产品时,不仅需要修改抽象工厂接口,还需要修改所有具体工厂类,维护成本较高,违背了开闭原则。
- 应用场景 :
- 创建相关产品族:适用于需要创建一系列相互关联或依赖的对象的场景,如游戏开发中创建不同主题风格的角色、场景和道具等产品族。
- 跨平台开发:在开发跨平台应用程序时,不同平台(如 Windows、Mac、Linux 等)有各自的界面组件(按钮、文本框等),可以使用抽象工厂模式为每个平台创建对应的产品族,实现界面的统一管理和切换。