现实中的工厂负责生产产品,编程中的简单工厂顾名思义就是一个生产对象的类,它的主要作用是封装改变。我们在平时的工作必不可免的和各种数据库打交道,我们就以一个数据库服务类为例来分析简单工厂的作用。代码如下:
用户类:
// 用户类 public class User { public int Id { get; set; } public string Name { get; set; } }
数据库服务抽象类(DbUserService),主要对用户进行添加和删除,类中有两个抽象方法,AddUser()和RemoveUser():
//数据库服务抽象类 public abstract class DbUserService { public abstract void AddUser();//添加用户 public abstract void RemoveUser();//获取用户 }
数据库服务具体类(SqlserverUserService和MysqlUserService),实现类对用户进行添加和删除的具体操作:
//Sqlserver中对用户进行添加和删除 public class SqlserverUserService:DbUserService { public override void AddUser() { Console.WriteLine("sqlserver 添加一个用户"); } public override void RemoveUser() { Console.WriteLine("sqlserver 删除一个用户"); } } //mysql中对用户添加和删除 public class MysqlUserService : DbUserService { public override void AddUser() { Console.WriteLine("Mysql 添加一个用户"); } public override void RemoveUser() { Console.WriteLine("Mysql 删除一个用户"); } }
客户端代码:
class Program { static void Main(string[] args) { //我们的软件中用了很多new来获取SqlserverUserService的实例 DbUserService userService1 = new SqlserverUserService(); DbUserService userService2 = new SqlserverUserService(); DbUserService userService3 = new SqlserverUserService(); DbUserService userService4 = new SqlserverUserService(); DbUserService userService5 = new SqlserverUserService(); userService1.AddUser(); userService1.RemoveUser(); Console.ReadKey(); } }
运行程序结果如下:
我们可以看到程序运行没有问题,通过new一个sqlserverUserService服务类实例可以成功地添加和删除用户,但是如果我们想把数据库切换到Mysql怎么去做呢?最简单直接的方法就是把 new SqlserverUserService 全部替换成 new MysqlUserService 。如果我们的软件中new了100个SqlserverUserService实例呢?一个一个地去替换会是一个巨大的工作量,同时通过new的方式来创建SqlserverUserService的实例,会让DbUserService和客户端产生强耦合关系,这时候使用简单工厂就可以帮助我们降低耦合,减少工作量了。添加一个DbUserServiceFactory,这个工厂类专门来创建DbUserService的实例:
//数据库服务工厂 public class DbUserServiceFactory { public static DbUserService Create(string dbname) { DbUserService dbUserService = null; switch (dbname) { case "sqlserver": dbUserService = new SqlserverUserService(); break; case "mysql": dbUserService = new MysqlUserService(); break; default: break; } return dbUserService; } }
客户端的代码就可以改成:
class Program { static void Main(string[] args) { //我们的软件中用了很多new来获取SqlserverUserService的实例 DbUserService userService1 = DbUserServiceFactory.Create("sqlserver"); DbUserService userService2 = DbUserServiceFactory.Create("sqlserver"); DbUserService userService3 = DbUserServiceFactory.Create("sqlserver"); DbUserService userService4 = DbUserServiceFactory.Create("sqlserver"); DbUserService userService5 = DbUserServiceFactory.Create("sqlserver"); userService1.AddUser(); userService1.RemoveUser(); Console.ReadKey(); } }
运行程序结果一样的,这样做有什么好处呢?我们看到我们把以前的 new SqlserverUserService() 替换成了 DbUserServiceFactory.Create("sqlserver") ,客户端和SqlserverUserService的耦合变成了 客户端<-->DbUserServiceFactory<-->SqlserverUserService 形式,有效降低了客户端和数据库服务实现类的耦合。我们还用一个疑问,程序改成这样的话,如果我们想从SqlServer切换到Mysql就要把DbUserServiceFatroy.Create("sqlserver")中的sqlserver字符串全部替换成mysql字符串,不是还要改100次?任务量没有降低呀!对于这个问题,我们可以把dbname存放在一个地方,如配置文件中,这样我们想切换数据库就直接修改配置文件即可,如下:
配置文件:
<appSettings> <add key="dbname" value="sqlserver"/> </appSettings>
工厂类修改为:
//数据库服务工厂 public class DbUserServiceFactory { private static readonly string dbname = ConfigurationManager.AppSettings["dbname"]; public static DbUserService Create() { DbUserService dbUserService = null; switch (dbname) { case "sqlserver": dbUserService = new SqlserverUserService(); break; case "mysql": dbUserService = new MysqlUserService(); break; default: break; } return dbUserService; } }
客户端代码如下:
class Program { static void Main(string[] args) { DbUserService userService1 = DbUserServiceFactory.Create(); DbUserService userService2 = DbUserServiceFactory.Create(); DbUserService userService3 = DbUserServiceFactory.Create(); DbUserService userService4 = DbUserServiceFactory.Create(); DbUserService userService5 = DbUserServiceFactory.Create(); userService1.AddUser(); userService1.RemoveUser(); Console.ReadKey(); } }
现在我们想把数据库服务切换到mysql,只需要将配置文件中的sqlserver改成mysql即可,修改配置文件后运行结果如下:
大功告成!这时有一个问题,如果我们想添加一个mongodb服务怎么办呢?除了添加一个MongodbUserService类,还要在UserServiceFactory类中添加一段case 代码。按照开闭原则,添加一个实现类没什么问题,开闭原则中对添加开发;但是修改简单工厂类就违背了对修改闭合的原则了。后边的工厂模式就是专门用来解决这个问题的。
上边例子的类图:
简单工厂的优点:
1.简单工厂可以有效地降低客户端和具体对象的耦合,将new具体对象的任务交给了一个简单工厂类
2可以有效的进行代码复用,如客户端A和客户端B都需要一个具体对象,客户端A和客户端B都可以通过同一个简单工厂来获取具体类型的实例
简单工厂的缺点:
一定程度上违背了开闭原则,在新增产品时需要修改简单工厂类
原文:https://www.cnblogs.com/wyy1234/p/9978389.html