一句话解释:
??实体类和工厂类均为单独实现,不影响已实现的类,方便扩展。
工厂方法模式(Factory Method Pattern)是一种创建型模式,它允许客户端通过工厂方法来创建对象,而不是直接使用构造函数。这样可以让客户端代码更加灵活,同时保持实现的独立性。工厂方法可以返回同一类的对象,也可以返回不同的类对象。
一个比喻:(班主任与班级)
一个班级对应一个班主任,当插班生超额时,则需要重新组成一个班级,那么此时就需要完成一个班级的各种条件,比如一个新的教室、班主任、班级编号等,当然这个新增的班级对原有的多个班级无影响。
优点:
缺点:
总之,工厂方法模式是一种常用且有效的设计模式,可以提高程序的灵活性和可扩展性,但也需要在实际开发中根据具体情况进行权衡和应用。
使用场景举例:
如下示例,先定义产品接口 IProduct 和工厂接口 IFactory,再分别进行实现:
#region 定义接口interface IProduct{ void Use();}// 定义工厂接口 interface IFactory{ IProduct CreateProduct();}#endregion#region 产品 A// 实现产品接口的具体产品类 class ConcreteProductA : IProduct{ public void Use() { Console.WriteLine("使用具体产品 A"); }}// 实现工厂接口的具体工厂类 class ConcreteFactoryA : IFactory{ public IProduct CreateProduct() { return new ConcreteProductA(); }}#endregion#region 产品 Bclass ConcreteProductB : IProduct{ public void Use() { Console.WriteLine("使用具体产品 B"); }}class ConcreteFactoryB : IFactory{ public IProduct CreateProduct() { return new ConcreteProductB(); }}#endregion
#region 定义接口
interface IProduct
{
void Use();
}
// 定义工厂接口
interface IFactory
IProduct CreateProduct();
#endregion
#region 产品 A
// 实现产品接口的具体产品类
class ConcreteProductA : IProduct
public void Use()
Console.WriteLine("使用具体产品 A");
// 实现工厂接口的具体工厂类
class ConcreteFactoryA : IFactory
public IProduct CreateProduct()
return new ConcreteProductA();
#region 产品 B
class ConcreteProductB : IProduct
Console.WriteLine("使用具体产品 B");
class ConcreteFactoryB : IFactory
return new ConcreteProductB();
下边进行实际的调用:
// 工厂方法模式IFactory factoryA = new ConcreteFactoryA();IProduct productA1 = factoryA.CreateProduct(); // 将对象的创建进行了封装IProduct productA2 = factoryA.CreateProduct();productA1.Use();productA2.Use();IFactory factoryB = new ConcreteFactoryB();IProduct productB = factoryB.CreateProduct();productB.Use();// 不用工厂方法模式的写法ConcreteProductA concreteProductA1 = new ConcreteProductA(); // 直接创建对象concreteProductA1.Use();ConcreteProductA concreteProductA2 = new ConcreteProductA();concreteProductA2.Use();ConcreteProductB concreteProductB = new ConcreteProductB();concreteProductB.Use();
// 工厂方法模式
IFactory factoryA = new ConcreteFactoryA();
IProduct productA1 = factoryA.CreateProduct(); // 将对象的创建进行了封装
IProduct productA2 = factoryA.CreateProduct();
productA1.Use();
productA2.Use();
IFactory factoryB = new ConcreteFactoryB();
IProduct productB = factoryB.CreateProduct();
productB.Use();
// 不用工厂方法模式的写法
ConcreteProductA concreteProductA1 = new ConcreteProductA(); // 直接创建对象
concreteProductA1.Use();
ConcreteProductA concreteProductA2 = new ConcreteProductA();
concreteProductA2.Use();
ConcreteProductB concreteProductB = new ConcreteProductB();
concreteProductB.Use();
由以上代码可见:通过工厂方法模式的实现,将对象的创建进行了封装,代码逻辑更清晰易读,当需要新增、删除或修改某个产品时,只需修改具体工厂类即可,既方便又安全。
依赖注入(Dependency Injection,简称DI)实际上是工厂方法模式的一种变体,通常与工厂方法模式一起使用。依赖注入可以帮助我们实现对象的创建和管理,使得对象的创建过程更加灵活和可控。
下面一个实例,在创建了语言接口 ILanguage、语言工厂抽象类 LanguageFactory 并实现后,又创建了一个 ClientCode 类来封装客户端代码的实现,并使用构造函数将具体工厂类作为参数传递给该类。客户端代码可以通过调用 Speak() 方法来创建相应的产品对象,并执行相关方法。
// 抽象语言类public interface ILanguage { void Speak();}// 英语类public class English : ILanguage { public void Speak() { Console.WriteLine("Speak English."); }}// 中文类public class Chinese : ILanguage { public void Speak() { Console.WriteLine("说中文。"); }}// 工厂方法抽象类public abstract class LanguageFactory { public abstract ILanguage CreateLanguage();}// 英语工厂public class EnglishFactory : LanguageFactory { public override ILanguage CreateLanguage() { return new English(); }}// 中文工厂public class ChineseFactory : LanguageFactory { public override ILanguage CreateLanguage() { return new Chinese(); }}// 客户端代码public class ClientCode { private readonly LanguageFactory _factory; public ClientCode(LanguageFactory factory) { // 依赖注入 LanguageFactory _factory = factory; } public void Speak() { ILanguage language = _factory.CreateLanguage(); language.Speak(); }}// 使用示例static void Main(string[] args) { ClientCode code1 = new ClientCode(new EnglishFactory()); // 依赖注入:英语工厂 code1.Speak(); // Speak English. ClientCode code2 = new ClientCode(new ChineseFactory()); // 依赖注入:中文工厂 code2.Speak(); // 说中文。}
// 抽象语言类
public interface ILanguage {
void Speak();
// 英语类
public class English : ILanguage {
public void Speak() {
Console.WriteLine("Speak English.");
// 中文类
public class Chinese : ILanguage {
Console.WriteLine("说中文。");
// 工厂方法抽象类
public abstract class LanguageFactory {
public abstract ILanguage CreateLanguage();
// 英语工厂
public class EnglishFactory : LanguageFactory {
public override ILanguage CreateLanguage() {
return new English();
// 中文工厂
public class ChineseFactory : LanguageFactory {
return new Chinese();
// 客户端代码
public class ClientCode {
private readonly LanguageFactory _factory;
public ClientCode(LanguageFactory factory) { // 依赖注入 LanguageFactory
_factory = factory;
ILanguage language = _factory.CreateLanguage();
language.Speak();
// 使用示例
static void Main(string[] args)
ClientCode code1 = new ClientCode(new EnglishFactory()); // 依赖注入:英语工厂
code1.Speak(); // Speak English.
ClientCode code2 = new ClientCode(new ChineseFactory()); // 依赖注入:中文工厂
code2.Speak(); // 说中文。
当然,如果后续有扩展需求,比如再新建一个俄语实现:
(只需增加两个独立的实现:语言接口 ILanguage、语言工厂抽象类 LanguageFactory)
// 俄语类public class Russian : ILanguage{ public void Speak() { Console.WriteLine("По-русски."); }}// 俄语工厂public class RussianFactory : LanguageFactory{ public override ILanguage CreateLanguage() { return new Russian(); }}
// 俄语类
public class Russian : ILanguage
public void Speak()
Console.WriteLine("По-русски.");
// 俄语工厂
public class RussianFactory : LanguageFactory
public override ILanguage CreateLanguage()
return new Russian();
然后直接使用,注入俄语工厂new RussianFactory()即可输出俄语,而对原有的实现没有任何影响。
new RussianFactory()
ClientCode code3 = new ClientCode(new RussianFactory()); // 依赖注入:俄语工厂code3.Speak();
ClientCode code3 = new ClientCode(new RussianFactory()); // 依赖注入:俄语工厂
code3.Speak();
实际输出,见第三行:
实际上在 .net 框架中,还有许多类似的用法,例如:
方式都是类似的,详情自行查看源码吧。
本文来自博客园,作者:橙子家,微信号:zfy1070491745,有任何疑问欢迎沟通,一起成长。
转载本文请注明原文链接:https://www.cnblogs.com/czzj/p/SJMSLL_FactoryMethod.html
原文链接:https://www.cnblogs.com/czzj/p/SJMSLL_FactoryMethod.html
本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728