数据底层操作告诉了我们接口,抽象类,继承与多态性的使用

这个问题困扰了我很久,很觉得设计的不完善,终于在今天把它彻底解决了,其实就是一个C#里的基础知识问题,主要涉及到了,接口,抽象类,接口继承,类继承,多态等知识。

事件是这样的,我有一个统一接口规范的接口,它可以由linq to sql,ado.net和ef等相关数据源去实现(只是举个例,不是实际中的代码)

复制代码
 1     /// <summary>
 2     /// 数据统一接口规范
 3     /// </summary>
 4     interface ITest
 5     {
 6         /// <summary>
 7         /// 插入方法
 8         /// </summary>
 9         void Insert();
10     }
复制代码

而在每一个子类中都去实现了这个接口,比如Testzzl这个实体,它去实现了这个ITest接口

复制代码
 1    /// <summary>
 2     /// Testzzl实体操作
 3     /// </summary>
 4     class Testzzl :  ITestzzl
 5     {
 6         /// <summary>
 7         /// 子类也可以去复写它
 8         /// </summary>
 9         public void Insert()
10         {
11             Console.WriteLine("子类实现Insert方法");
12         }
13     }
复制代码

好了,这样在使用时,可以定义接口类型的对象,通过具体的工具实现接口的多态性。

1   ITestzzl iTestzzl = new Testzzl();
2   iTestzzl.Insert();

这是我最初写的代码,我总觉得有些不爽,但又说不出来,我知道,我写了很多重复的代码,因为每个子类在实现Insert方法时,它们的代码都是相同的,除非自己逻辑上有需要,再会

真正去实现它。

在一次技术讨论中,终于被经理的所惊醒,“为何不把相同的实现逻辑放在一个基类中呢?”,于是,我改了一下代码,它变成了这样:

复制代码
 1     /// <summary>
 2     /// 统一实体基类
 3     /// 子类共同的操作逻辑
 4     /// </summary>
 5     abstract class TestBase : ITest
 6     {
 7 
 8         #region ITest 成员
 9 
10         public virtual void Insert()
11         {
12             Console.WriteLine("基类统一实现Insert方法");
13         }
14 
15         #endregion
16     }
复制代码

我们的子类去继承TestBase后,它可以使用基类的Insert()方法,如果子类自己的逻辑有需要,还可以去复写它,看似重复代码的问题解决了,可又有一个问题来了,我们在业务层使用

数据库对象时,一般会以接口对象进行声明,因为它可以帮助我们实现操作的多态性,下面代码出问题了

1  ITestzzl iTestzzl = new Testzzl();
2 
3  iTestzzl.Insert();

嘿,我们的Insert()方法,找不到了,这是为什么呢?原来在我们的ITestzzl接口中,并没有定义这个方法,实事上,如果希望的ITest的接口应用到ITestzzl接口上,需要去继承一个它,

于是ITestzzl接口变成了这样:

1  interface ITestzzl : ITest {
2   // Testzzl实体的一些操作逻辑
3  }

这时,我们在去调用Insert()方法,就正常了,呵呵,原来是子类接口没有继承统一操作接口的问题呀!

下面是实例的完整代码,供大家参考:

1     /// <summary>
 2     /// 数据统一接口规范
 3     /// </summary>
 4     interface ITest
 5     {
 6         /// <summary>
 7         /// 插入方法
 8         /// </summary>
 9         void Insert();
10     }
11     /// <summary>
12     /// 统一实体基类
13     /// 子类共同的操作逻辑
14     /// </summary>
15     abstract class TestBase : ITest
16     {
17 
18         #region ITest 成员
19 
20         public virtual void Insert()
21         {
22             Console.WriteLine("基类统一实现Insert方法");
23         }
24 
25         #endregion
26     }
27     interface ITestzzl : ITest { }
28     /// <summary>
29     /// Testzzl实体操作
30     /// </summary>
31     class Testzzl : TestBase, ITestzzl
32     {
33         /// <summary>
34         /// 子类也可以去复写它
35         /// </summary>
36         public override void Insert()
37         {
38             Console.WriteLine("子类实现Insert方法");
39         }
40     }
41 
42 class Program{
43  static void Main(string[] args)
44         {
45             ITestzzl iTestzzl = new Testzzl();
46 
47             iTestzzl.Insert();
48             Console.ReadKey();
49 }
50 }
 

收到了很多博友的回复,其中有一位博友提了一个问题,TestBase 继承了ITest是多余的,我认为,我有必要再写一篇文章来说明一下,TestBase为什么要继承ITest,当然各位也可以再次发表自己的看法。

复制代码
 1     /// <summary>
 2     /// 数据统一接口规范
 3     /// </summary>
 4     interface ITest
 5     {
 6         /// <summary>
 7         /// 插入方法
 8         /// </summary>
 9         void Insert();
10     }
复制代码

还是那个统一接口规范,这时,有个ADO.NET 的数据基类,它会去实现它,如下

复制代码
 1     /// <summary>
 2     /// 统一实体基类
 3     /// ADO.NET操作基类
 4     /// </summary>
 5     abstract class TestBase : ITest
 6     {
 7 
 8         #region ITest 成员
 9 
10         public virtual void Insert()
11         {
12             Console.WriteLine("使用ADO.NET操作方式去实现它");
13         }
14 
15         #endregion
16     }
复制代码

而我们的系统中,还有一种数据源,它叫Linq To SQL,同时它又是一个很好的ORM工具,它帮助我们很好的把实体数据库进行映射进来了。它作为由linq to sql产生的实体的基类,去实现统一接口,如下:

复制代码
 1     /// <summary>
 2     /// 统一实体基类
 3     /// Linq To SQL操作基类
 4     /// </summary>
 5     abstract class TestBase : ITest
 6     {
 7 
 8         #region ITest 成员
 9 
10         public virtual void Insert()
11         {
12             Console.WriteLine("使用Linq To SQL操作方式去实现它");
13         }
14 
15         #endregion
16     }
复制代码

这时,我们有两个数据基类去实现了这个统一操作接口,这时,如果有其它数据源,如为单元测试提供的内存流数据库,也是去实现统一操作规范。事实上,在DATA层提供了多种实现统一操作接口的方式,而它们的实体子类需要去分别继承各自的基类和自己的个性化接口接口,而最终使用哪种数据库去实现,我们可以通过IOC进行动态设定它。这只是最底层的层次,事实上,在每个实体操作的接口与实现中,还存在着这种关系,而这种关系一定会被约束在配置文件中,你可以根据配置的方式,在程序运行时去动态创建你的实例,当然这同样是IOC干的事。

 
分类: C#面向对象
分类: C#面向对象
原文地址:https://www.cnblogs.com/Leo_wl/p/2557048.html