简单工厂-基于接口的编程

昨天,老师给我们展示了简单工厂的设计模式。今天练习了一遍,体会了一下面向接口的编程的强大之处。今天总结一下,加深一下理解。

因为初学C#.net编程,之前做的几个例子都是使用的简单三层架构。而简单三层有个问题,业务操作类与数据操作类是强耦合关系,数据操作类的变动,会直接影响到业务操作类的正常运行,所以为了解决这个问题,需要解耦。怎么解耦,引入接口和工厂类,来将业务操作类与数据操作类的关系变为弱耦合关系。

 

如左图,图中每条线都代表一个类,图A是一种强耦合关系,一个类的变动就会影响其他类;图B在两个类有关系的地方定义了一个接口,这样类A如何改变都不会影响到类B,这样就达到了解耦的目的,这就是面向接口的编程模式。

 

 

 

 

 

 

下附上两个图来说明下思路:

图A为简单三层,如果数据访问类发生改变(比如:换个数据帮助类文件,就需要修改业务逻辑类里的代码),这样会重复写许多相同的代码。

图B为简单工厂,在业务逻辑类与UI层添加一个接口(I1),在数据访问层与业务逻辑层之间再添加一个接口(I2)。这样不同数据访问层只需要实现I2既可以

思路已经有了,如何用代码实现呢?下面以查询为例简单介绍:

数据访问层代码:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using Test.Model;
 6 using System.Data;
 7 using System.Data.SqlClient;
 8 namespace Test.SqlServerDAL
 9 {
10     //Student的数据访问层,实现IStudentDAL接口
11     public class StudentDAL : IDAL.IStudentDAL
12     {
13         //获取所有Student并加入List<Student>中
14         public List<Model.Student> GetAllStudent()
15         {
16             List<Student> list = new List<Student>();
17             Student stu;
18             string sqlText = "select stuId, stuName, stuAge, stuGender, stuPhone, stuEmail, stuAddress, stuSchool from Student";
19             using (SqlDataReader sdr = SQLHelper.ExecuteReader(sqlText, CommandType.Text))
20             {
21                 while (sdr.Read())
22                 {
23                     stu = new Student();
24                     stu.StuId = sdr.GetInt32(0);
25                     stu.StuName = sdr.GetString(1);
26                     stu.StuAge = sdr.GetInt32(2);
27                     stu.StuGender = sdr.GetString(3);
28                     stu.StuPhone = sdr.GetString(4);
29                     stu.StuEmail = sdr.GetString(5);
30                     stu.StuAddress = sdr.GetString(6);
31                     stu.StuSchool = sdr.GetString(7);
32 
33                     list.Add(stu);
34                 }
35             }
36             return list;
37         }
38     }
39 }
View Code

子类接口:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using Test.Model;
 6 
 7 namespace IDAL
 8 {
 9     //子类接口
10     public interface IStudentDAL:IBaseDAL<Student>
11     {
12         List<Student> GetAllStudent();//获取所有学生
13         //增删改方法
14     }
15 }

基类接口,可以封装增删改查方法(只写了查询的方法):

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace IDAL
 7 {
 8     //基类接口,可以封装增删改查方法,使用了泛型便于获取不同类型的实体,让有相同方法的子类继承,并且给出特定类型。where T:class,new()意思是一个限制,T是一个类,并且可以new(),有个无参的构造函数
 9     public interface IBaseDAL<T> where T:class,new()
10     {
11         List<T> GetAllStudent();
12     }
13 }

工厂类,用于创建数据访问层对象

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using Test.SqlServerDAL;
 6 namespace StudentFactoryDAL
 7 {
 8     public class FactoryDAL
 9     {
10         //静态工厂类,用来创建对应的DAL对象
11         public static IDAL.IStudentDAL CreateStudentDAL() 
12         {
13             return new StudentDAL();
14         }
15     }
16 }

业务逻辑层

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using Test.Model;
 6 
 7 namespace Test.BLL
 8 {
 9     public class StudentBLL:IBLL.IStudentBLL
10     {
11         //通过接口和工厂创建DAL对象
12         IDAL.IStudentDAL dal = StudentFactoryDAL.FactoryDAL.CreateStudentDAL();
13         //调用dal中的方法,获取所有的学生信息并传给UI层
14         public List<Student> GetAllStudent()
15         {
16             return dal.GetAllStudent();
17         }
18     }
19 }

同理,可以让业务逻辑层实现接口,并且通过工厂类在表示层后台创建BLL对象,实现业务逻辑层与表现层的解耦。

这样,面向接口的编程就实现了,无论数据访问层怎么修改,只要让它实现上述例子中的子接口就可以了。抽象工厂就是让工厂通过配置文件来动态创建相应的对象,这样更加增加了代码的灵活性。

以上是我自己的理解,如果有错误,还希望大牛们能给指出,谢谢。

原文地址:https://www.cnblogs.com/JokerYang/p/3422003.html