设计模式:简单工厂、工厂方法、抽象工厂
简单工厂
简单工厂模式是属于创建型模式,又叫做静态工厂方法模式,但不属于23种设计模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例,简单工厂模式是工厂模式家族中最简单实用的模式。
代码演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | /// <summary> /// 抽象 功能 /// </summary> public interface ISqlHelper { void ExecuteSql(); } public enum SqlType { SqlServer = 0, MySql =1, Oracle = 2 } /// <summary> /// 具体实现 /// </summary> public class SqlServerHelper : ISqlHelper { public void ExecuteSql() { Console.WriteLine( "SqlServer 执行成功!" ); } } public class MySqlHelper : ISqlHelper { public void ExecuteSql() { Console.WriteLine( "MySql 执行成功!" ); } } public class OracleHelper : ISqlHelper { public void ExecuteSql() { Console.WriteLine( "Oracle 执行成功!" ); } } //简单工厂的核心代码 public class FactoryCore { public ISqlHelper ExecuteSql(SqlType sqlType) { ISqlHelper iSqlHelper = null ; switch (sqlType) { case SqlType.SqlServer: iSqlHelper = new SqlServerHelper(); break ; case SqlType.MySql: iSqlHelper = new MySqlHelper(); break ; case SqlType.Oracle: iSqlHelper = new OracleHelper(); break ; default : throw new Exception( "ExecuteSql -- 参数异常!" ); } return iSqlHelper; } } static void Main( string [] args) { //调用 ISqlHelper sqlHelper; try { FactoryCore fatory = new FactoryCore(); sqlHelper = fatory.ExecuteSql(SqlType.SqlServer); sqlHelper.ExecuteSql(); Console.ReadKey(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } |
简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。
但是,很明显工厂类集中了所有实例的创建逻辑,容易违反GRASPR的高内聚的责任分配原则。
工厂方法
工厂方法模式又称多态性工厂模式。在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触某一个具体类应当被实例化这种细节。
代码演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | /// <summary> /// 抽象功能 /// </summary> public interface ISqlHelper { void ExecuteSql(); } /// <summary> /// 抽象工厂 /// </summary> public interface IFactory { ISqlHelper CreateSqlHelper(); } /// <summary> /// 具体实现 /// </summary> public class SqlServerHelper : ISqlHelper { public void ExecuteSql() { Console.WriteLine( "SqlServer 执行成功!" ); } } public class MySqlHelper : ISqlHelper { public void ExecuteSql() { Console.WriteLine( "MySql 执行成功!" ); } } public class OracleHelper : ISqlHelper { public void ExecuteSql() { Console.WriteLine( "Oracle 执行成功!" ); } } /// <summary> /// 具体工厂 /// </summary> public class SqlServerFactory : IFactory { public ISqlHelper CreateSqlHelper() { return new SqlServerHelper(); } } public class MySqlFactory : IFactory { public ISqlHelper CreateSqlHelper() { return new MySqlHelper(); } } public class OracleFactory : IFactory { public ISqlHelper CreateSqlHelper() { return new OracleHelper(); } } internal class Program { static void Main( string [] args) { IFactory iFactory = new SqlServerFactory(); ISqlHelper iSqlHelper = iFactory.CreateSqlHelper(); iSqlHelper.ExecuteSql(); /* * 可以把工厂类名和dll名 放到配置文件中,然后利用反射来创建实例。 * 这样就实现了程序的可配置性。 * * string factoryType = ConfigurationManager.AppSettings["FactoryType"]; * string dllName = ConfigurationManager.AppSettings["DllName"]; * var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly(); * string codeBase = currentAssembly.CodeBase.ToLower().Replace(currentAssembly.ManifestModule.Name.ToLower(), string.Empty); * IFactory iFactory = Assembly.LoadFrom(Path.Combine(codeBase, dllName)).CreateInstance(factoryType) as IFactory; * ISqlHelper iSqlHelper = iFactory.CreateSqlHelper(); * iSqlHelper.ExecuteSql(); * */ Console.ReadKey(); } } |
工厂方法通过子类提供挂钩。基类为工厂方法提供缺省实现,子类可以重写新的实现,也可以继承父类的实现。 加一层间接性,增加了灵活性
屏蔽产品类。产品类的实现如何变化,调用者都不需要关心,只需关心产品的接口,只要接口保持不变,系统中的上层模块就不会发生变化。
典型的解耦框架。高层模块只需要知道产品的抽象类,其他的实现类都不需要关心,符合迪米特法则,符合依赖倒置原则,符合里氏替换原则。
多态性:客户代码可以做到与特定应用无关,适用于任何实体类。
抽象工厂
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。
代码演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | //抽象的产品 1 public interface IMobile { void Show(); } public interface INotebook { void Show(); } //抽象工厂 2 public interface IAbstractFactory { IMobile CtreateMobile(); INotebook CreateNotebook(); } //具体的产品 3 public class HuWeiMobile:IMobile { public void Show() { Console.WriteLine( "华为手机!" ); } } public class HuWeiNotebook : INotebook { public void Show() { Console.WriteLine( "华为笔记本!" ); } } public class AppleMobile : IMobile { public void Show() { Console.WriteLine( "苹果手机!" ); } } public class AppleNotebook : INotebook { public void Show() { Console.WriteLine( "苹果笔记本!" ); } } //具体工厂 4 public class HuWeiFactory:IAbstractFactory { public IMobile CtreateMobile() { return new HuWeiMobile(); } public INotebook CreateNotebook() { return new HuWeiNotebook(); } } public class AppleFactory : IAbstractFactory { public IMobile CtreateMobile() { return new AppleMobile(); } public INotebook CreateNotebook() { return new AppleNotebook(); } } internal class Program { static void Main( string [] args) { //调用 5 IAbstractFactory abstractFactory = null ; abstractFactory = new HuWeiFactory(); IMobile mobile = abstractFactory.CtreateMobile(); INotebook notebook = abstractFactory.CreateNotebook(); mobile.Show(); notebook.Show(); Console.ReadKey(); } } |
抽象工厂模式隔离了具体类的生产,使得客户并不需要知道什么被创建。
当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
但是,增加新的产品等级结构很麻烦!!!因为需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这必然会带来较大的不便,在这个角度,它违背了开闭(对扩展开放,对修改封闭)原则。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了