抽象工厂模式(13)
来源:互联网 发布:excel表格数据透视表 编辑:程序博客网 时间:2024/06/03 21:40
今天呢,给大家来讲一下抽象工厂模式,说到这里,大家会想到好多种关于工厂的模式,前面已经讲了两种了 简单工厂模式和工厂方法模式。好,下面我们来看一下抽象工厂模式。
同样,我们来举一个案例
一、案例
我们在做项目的时候,肯定会与数据库打交道,那么我们用简单的控制台应用程序来模拟一个向SqlServer数据库表中插入和读取的情况。
1 /// <summary> 2 /// User中的字段 3 /// </summary> 4 class User 5 { 6 private int _id; 7 8 public int Id 9 {10 get11 {12 return _id;13 }14 15 set16 {17 _id = value;18 }19 }20 21 public string Name22 {23 get24 {25 return _name;26 }27 28 set29 {30 _name = value;31 }32 }33 34 private string _name;35 }36 /// <summary>37 /// SqlServer类38 /// </summary>39 class SqlserverUser40 {41 public void Insert(User user)42 {43 Console.WriteLine("在Sql server 中 给User 表增加一条记录");44 }45 46 public User GetUser(int id)47 {48 Console.WriteLine($"在Sql server 中根据ID获取User表中的一条记录");49 return null;50 }51 }
客户端调用:
1 internal class Program 2 { 3 public static void Main() 4 { 5 User user = new User(); 6 SqlserverUser su = new SqlserverUser(); 7 su.Insert(user); 8 su.GetUser(1); 9 Console.ReadKey();10 }
二、演绎
1、第一步演绎
那么问题来了,如果我这个项目数据库换成Oracle,那么我岂不是都要改了,如果想实现自由的切换数据库,我们想到了一个不错的模式,对,工厂方法模式。
让他们都依赖于抽象,所以我们在这里增加两个接口
1 interface IUser 2 { 3 void Insert(User user); 4 User GetUser(int id); 5 } 6 7 interface IFactory 8 { 9 IUser CraeteUser();10 }
让User 和 SqlServer 等类继承相应的接口
1 /// <summary> 2 /// SqlServer类 3 /// </summary> 4 class SqlserverUser :IUser 5 { 6 public void Insert(User user) 7 { 8 Console.WriteLine("在Sql server 中 给User 表增加一条记录"); 9 }10 11 public User GetUser(int id)12 {13 Console.WriteLine($"在Sql server 中根据ID获取User表中的一条记录");14 return null;15 }16 }17 18 class OracleUser:IUser19 {20 public void Insert(User user)21 {22 Console.WriteLine("在Oracle 中 给User 表增加一条记录");23 }24 25 public User GetUser(int id)26 {27 Console.WriteLine($"在Oracle 中根据ID获取User表中的一条记录");28 return null;29 }30 }
1 class SqlServerFactory:IFactory 2 { 3 public IUser CraeteUser() 4 { 5 return new SqlserverUser(); 6 } 7 } 8 class OracleFactory : IFactory 9 {10 public IUser CraeteUser()11 {12 return new OracleUser();13 }14 }
客户端
1 public static void Main()2 {3 User user = new User();4 IFactory factory = new SqlServerFactory();5 IUser su = factory.CraeteUser();6 su.Insert(user);7 su.GetUser(1);8 Console.ReadKey();9 }
以上,我们将案例用工厂方法模式写出来了。
2、第二步演绎
我们的数据库中,不可能之后User表,还有很多其他的表,这样就会产生好多的类哦。
下面,我们在增加一个表(Department)
那么,按照上面的模式就会产生一下面的一坨代码
1 class Department 2 { 3 private int _id; 4 5 public int Id 6 { 7 get 8 { 9 return _id;10 }11 12 set13 {14 _id = value;15 }16 }17 18 public string Name19 {20 get21 {22 return _name;23 }24 25 set26 {27 _name = value;28 }29 }30 31 private string _name;32 }33 interface IDepartment34 {35 void Insert(Department department);36 Department GetDepartment(int id);37 }38 39 class SqlServerDepartment:IDepartment40 {41 public void Insert(Department department)42 {43 Console.WriteLine("在SqlServer 中 给Department 表增加一条记录");44 }45 46 public Department GetDepartment(int id)47 {48 Console.WriteLine("在SqlServer 中 根据ID 获取Department 表一条记录");49 return null;50 }51 }52 53 class OracleDepartment : IDepartment54 {55 public void Insert(Department department)56 {57 Console.WriteLine("在Oracle 中 给Department 表增加一条记录");58 }59 60 public Department GetDepartment(int id)61 {62 Console.WriteLine("在Oracle 中 根据ID 获取Department 表一条记录");63 return null;64 }65 }
工厂接口与实现中也新增了方法
1 interface IFactory 2 { 3 IUser CraeteUser(); 4 IDepartment CreateDepartment(); 5 } 6 7 class SqlServerFactory:IFactory 8 { 9 public IUser CraeteUser()10 {11 return new SqlserverUser();12 }13 14 public IDepartment CreateDepartment()15 {16 return new SqlServerDepartment();17 }18 }19 class OracleFactory : IFactory20 {21 public IUser CraeteUser()22 {23 return new OracleUser();24 }25 26 public IDepartment CreateDepartment()27 {28 return new OracleDepartment();29 }30 }
经过我们这么一步一步的演化,我们重构出了一个非常重要的设计模式,抽象工厂模式。小伙伴们会说,刚刚这不是工厂方法模式吗。
只有一个User表的时候,是只需要工厂方法模式的,但是我们数据库中显然有非常多的表,还SqlServer 和Oracle 这两大分支,所以涉及到解决多种产品分支的问题,有一个专门的工厂模式,叫抽象工厂模式。
什么叫抽象工厂模式呢?提供一系列相关或相互依赖的接口,而无需指定他们具体的类。
这就是抽象工厂模式,他的优缺点很明显。
优点:灵活,产品系列零活切换。
缺点:如果我们再增加一个表,需要改动的地方太多了,需要增加三个类,需要修改三个类,靠,太麻烦了吧。
客户端每一次使用时,需要new 一下,如果客户端有好多处调用的,那么就需要new 好多次。 这些都是他的缺点。
编程是一门艺术,这样大批量的改动,显然是非常丑陋的做法。
我们这里有一个改进的方法,就是用简单工厂方法改进抽象工厂模式。
我们新增加一个类
1 class DataAccess 2 { 3 private static readonly string db = "SqlServer"; 4 // private static readonly string db = "Oracle"; 5 public static IUser CreateUser() 6 { 7 IUser result = null; 8 switch (db) 9 {10 case "SqlServer":11 result = new SqlserverUser();12 break;13 case "Oracle":14 result = new OracleUser();15 break;16 }17 return result;18 }19 20 public static IDepartment CreateDepartment()21 {22 IDepartment result = null;23 switch (db)24 {25 case "SqlServer":26 result = new SqlServerDepartment();27 break;28 case "Oracle":29 result = new OracleDepartment();30 break;31 }32 return result;33 }34 }
嗯,这样,客户端调用的时候就好调用了。
1 public static void Main() 2 { 3 User user = new User(); 4 Department dept = new Department(); 5 IUser iu = DataAccess.CreateUser(); 6 iu.Insert(user); 7 iu.GetUser(1); 8 IDepartment d = DataAccess.CreateDepartment(); 9 d.Insert(dept);10 d.GetDepartment(1);11 Console.ReadKey();12 }
ok,那么如果我还想增加一个数据库类型的分支,比如Access数据库,那么需要在DataAccess类的方法中增加一个case 分支。
之前我们也曾提到过相关的问题,就是用 反射 来解决,但一直没有展开来讲,那么下篇博文,我们来给大家讲一讲如何用反射的技术来解决这些问题。
反射反射,程序员的快乐~
好了,今天我们先讲到这里,下一篇我们将用反射技术来解决相关的问题~
本系列将持续更新,喜欢的小伙伴可以点一下关注和推荐,谢谢大家的支持。
- 抽象工厂模式(13)
- 抽象工厂模式(13)
- 工厂模式(三)--抽象工厂模式
- 抽象工厂模式(工厂模式5)
- 工厂模式(工厂方法模式,抽象工厂模式) Java
- 抽象工厂模式(三):抽象工厂模式概述
- 工厂模式(简单工厂、工厂和抽象工厂) C++
- 工厂模式(简单工厂,工厂方法,抽象工厂)
- 工厂模式(简单工厂+工厂方法+抽象工厂)
- 工厂模式(简单工厂、工厂方法、抽象工厂)
- 工厂模式(简单工厂、工厂方法、抽象工厂)
- 工厂模式详解(简单工厂+工厂方法+抽象工厂)
- 工厂模式详解(简单工厂+工厂方法+抽象工厂)
- Java工厂模式(简单工厂、工厂方法、抽象工厂)
- 工厂模式(简单工厂,工厂方法,抽象工厂)
- 工厂模式(简单工厂+工厂方法+抽象工厂)
- (10)抽象工厂模式
- 抽象工厂模式(C#)
- WEB FRONT DEV STUDY
- maven集成jetty插件发布web项目
- 第七章上机答案
- 算法导论之钢条切割
- HDU 1411 校庆神秘建筑【欧拉四面体公式】
- 抽象工厂模式(13)
- File操作(1)
- maven集成tomcat插件发布web项目
- Lucene 6.2.1入门教程(二) 添加索引时新API与旧API的一些不同之处
- Vector
- POJ 1125-Stockbroker Grapevine(最短路-含孤立点)
- Day_6.
- View工作原理笔记
- gulp-autoprefixer