探讨继承与实现(二)

前文 探讨继承与实现(一)  根据双鱼座的提示已经更新。很不巧,我也是双鱼座的。 teeth_smile.gif由于水平有限,有什么不足还请大家指教。

2007年2月1日
http://www.cnblogs.com/birdshover/

目录:
一、抽象的产生
二、依赖抽象
三、抽象的损耗


一、抽象的产生

你不知道你要实现的是个什么东西,你能很好的抽象出来么?我不是天才,所以我是不能。如果是那些天才至少也要是白痴天才型的人才能在毫无根据的情况下,假设出真是的存在。尔后居然被伟人证实居然是真的。比如说那个什么××××猜想。 tongue_smile.gif

我认为,抽象要么是在建立模型后的产物,要么是重构的结果。而抽象是为了解决程序未来面临的变动。但是你即便把实体抽象出来了,不使用也是没有效果的。而前人总结出经验如何使用这些抽象产物——依赖倒置(Dependence Inversion Principle)。讲的是:要依赖于抽象,不要依赖于具体。也就是经常说的面向接口编程。(这地方的接口是广义上的接口)

DIP.gif


图2.1 抽象的产生与运用

上图描绘了先是根据细节得出抽象描述,然后又把抽象描述运用于实例。从种看出,如果没有3,4两步,抽下是没有意义的。就好比先发现了电,然后发现两根电线能传输电,再后来把电器接在电线上。但是这样很麻烦,于是发明了插座。再把插座实际应用到流程中去。

假设公司装了一扇自动门,有人来会开,人走了就关上。
 1       public   class  Door
 2      {
 3           private   bool  HavaPeson  =   false ;   //是否有人,默认没有。自动门,该状态会自动改变。
 4 
 5           public   void  Open()
 6          {
 7               if  (HavaPeson)
 8                  Console.WriteLine( " Opend " );
 9          }
10 
11           public   void  Close()
12          {
13               if  ( ! HavaPeson)
14                  Console.WriteLine( " Closed " );
15          }
16      }

我们把它抽象出来
1       interface  IDoor
2      {
3           void  Close();
4           void  Open();
5      }

 1       public   class  Door : IDoor
 2      {
 3           private   bool  HavaPeson  =   false ;
 4 
 5           public   void  Open()
 6          {
 7               if  (HavaPeson)
 8                  Console.WriteLine( " Opend " );
 9          }
10 
11           public   void  Close()
12          {
13               if  ( ! HavaPeson)
14                  Console.WriteLine( " Closed " );
15          }
16      }

但是这对我们好像并没有用。
这个时候公司又要装一扇门,手推才会开,不推自动关上。

二、依赖抽象

 1       public   class  Door2
 2      {
 3           private   bool  IsPush  =   false ;
 4 
 5           public   void  Open()
 6          {
 7               if  (IsPush)
 8                  Console.WriteLine( " Opend " );
 9          }
10 
11           public   void  Close()
12          {
13               if  ( ! IsPush)
14                  Console.WriteLine( " Closed " );
15          }
16      }


Door2也实现了IDoor接口啊!
所以改成
public class Door2 : IDoor
{}

老总感觉这两扇门不错,所以要全大楼装上这样的门,并且采用电脑控制。
如果每个门一个控制端,那累也累死了。所以可以实现如下。

Door.gif


图2.2 抽象关系

就是让ControlDoor依赖于IDoor。代码如下:

 1       public   class  ContorlDoor
 2      {
 3           private  IDoor[] door  =   new  IDoor[ 100 ];
 4           private   bool  flag  =   false ;       // 判断门和人的关系状态
 5 
 6           public   void  CDoor( int  i)
 7          {
 8              door[i]  =  (IDoor) new  Door();
 9              Contorl(door[i]);
10          }
11 
12           public   void  CDoor2( int  i)
13          {
14              door[i]  =  (IDoor) new  Door2();
15              Contorl(door[i]);
16          }
17 
18           public   void  Contorl(IDoor d)
19          {
20               if  (flag)
21                  d.Open();
22               else
23                  d.Close();
24          }
25      }

现在即使要加新的门,只要让新型号的门实现接口IDoor就可以了。当然,这地方使用接口而不是抽象类,是根据第一篇文章决定的。 探讨继承与实现(一) 
至于使用抽象类也是一样的道理。

三、抽象的损耗

所谓有所得必有所失,灵活的架构必然会带来性能上的损耗。

损耗的第一点,大家应该都看出来了,就是类型转换。需要把类的实例转换成接口或者抽象类。而转换除了带来灵活以外,并没有其它的收获。
 1    public   class  Test : ITest
 2      {
 3 
 4           #region  ITest 成员
 5           private   int  myint;
 6           private   string  s;
 7 
 8           public   string  otherStr
 9          {
10               get
11              {
12                   return  s;
13              }
14 
15               set
16              {
17                  s  =  value;
18              }
19          }
20 
21 
22 
23           public   int  MyInt
24          {
25               get
26              {
27                   return  myint;
28              }
29               set
30              {
31                  myint  =  value;
32              }
33          }
34 
35           public   string  MyStr()
36          {
37               return   " myStr " ;
38          }
39 
40           #endregion
41 
42           public   string  OtherStr()
43          {
44               return  otherStr;
45          }
46      }
 1       public   interface  ITest
 2      {
 3           int  MyInt
 4          {
 5               get ;
 6               set ;
 7          }
 8 
 9           string  otherStr {  get ; set ;}
10           string  MyStr();
11      }
1           static   void  Main( string [] args)
2          {
3              ITest it  =  (ITest) new  Test();
4              Test t  =  (Test)it;
5              t.otherStr  =   " 1 " ;
6              it.otherStr  =   " 2 " ;
7              Console.WriteLine(t.OtherStr());
8              Console.ReadKey();
9          }
以上代码输出值 2

实例it不能使用方法OtherStr,而再转化回来后还能使用,证明内存种存在的是Test的实例。并没有因为ITest 没有OtherStr而砍掉。只是再it实例中屏蔽(简化)了我们的访问。

Translation.gif
图2.3 类的转换前后


从图中可以看出,转换只是给了我们一个望远镜,一面能看到很大的视野,一面看到的小。就和古人写的管中窥豹是一个道理吧。

而为什么输出的是2而不是1,那是因为类是引用类型。而转换后还是引用类型。it和t看似两个实例,实际上指向的是同一段内存地址,只是留给你的看台不一样。

转载于:https://www.cnblogs.com/birdshover/archive/2007/02/02/637497.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值