委托事件—机房收费系统(续一)

上篇博客写了我在机房下机时使用到的委托事件,这篇博客就上篇博客中的一些问题进行分析:

1.什么是委托?

      委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

      比如机房中下机事件中,下机前要进行各种判断:1.基本信息是否存在2.卡号是否存在3.卡号是否正在上机等4.余额是否足够,如果什么像之前那样写程序的话,我们肯定会使用if..else..一个状态一个状态的判断,但是用到委托可以省去这个判断。

      我们知道委托是一个引用类型,所以它具有引用类型所具有的通性。那它保存的是对什么的引用呢?委托保存的是对函数(function)的引用。

<span style="font-size:18px;"> off.offevent += new offLineDelegate(new VerifyBasicData().IsExist);
 off.offevent += new offLineDelegate(new OperateCard().isCardExist);</span>
比如:在上篇博客的下机中,客户端实例化委托并给其注册方法时,每次注册一个方法,委托就会保存一个此方法的引用。

      当我们用delegate关键字声明委托时,编译器自动为我们生成类。类的名字即为委托变量名,访问类型为定义的委托访问类型。

      如下机中, public delegate bool offLineDelegate(MainOff mainoff);;定义的委托对应的类为offLineDelegate,访问类型为public,该类继承自[mscorlib]System.MulticastDelegate。

      在使用委托的时候,你可以像对待一个类一样对待它。即先声明,再实例化。只是有点不同,类在实例化之后叫对象或实例,但委托在实例化后仍叫委托。

2.他们之间的关系?用事件的方式来调用的话有什么好处?

     事件是一种封装,就好像属性会封装字段一样,可以把定义和实现隔离开来,给你举个例子就是DateTime实际上你看那么多属性,其实里面只有一个字段存储时间,各种日期啊年啊属性都是根据这个时间算出来的。

     事件代表一个组件能够被关注的一种信号;委托是可以把一个过程封装成变量进行传递并且执行的对象。

     比如说,下面就可以把Name看做事件,把_name看做委托对象。 

<span style="font-size:18px;">    private string _name
        public virtual string Name
        {
            get { return _name; }
            set {_name = value; }
        }
</span>
     事件只能通过“+=”来注册新的订阅者,而不能通过“=”来注册(即不能覆盖之前的所有订阅者,委托可以),这样一定程度上保证了安全性。

<span style="font-size:18px;"> off.offevent += new offLineDelegate(new VerifyBasicData().IsExist);
 off.offevent += new offLineDelegate(new OperateCard().isCardExist);</span>

     在MainOff这个类里面定义了事件,在事件里封装了委托。客户端调用时,通过调用 OffLine来触发委托offevent,如果不用事件,offLineDelegate就会直接暴露出来,因为委托offLineDelegate默认为public类型,在任何地方都可以通过实例化而使用它,这样不安全,就类似于我们没有Name,直接把_name声明为public直接赋值使用一样。

     现在事件offevent封装在类MainOff中,虽然声明为public,但是编译后都会成为private,这样保证了触发事件的语句只能在定义事件的类内部执行,客户端不能自行触发事件,必须通过调用事件发布者已经定义好的方法来触发。所以,在客户端使用时必需先实例化MainOff这个类,才能调用OffLine方法。

<span style="font-size:18px;">public delegate bool offLineDelegate(MainOff mainoff);

    /// <summary>
    /// 通知者:正常下机,通过offLine触发事件
    /// </summary>
    public class MainOff
    {
        public int consumeTime;//消费时间
        public SetBasicData basicDataEntity=new SetBasicData();
        public Card cardEntity = new Card();
        public OnOffLineInfo onoffEntity = new OnOffLineInfo();
     
        public event offLineDelegate offevent; //声明事件,下机时的事件
       
        public void OffLine(string cardNo)     //声明函数,通过函数OffLine触发事件offLineDelegate
        {
            bool bl = true;
            cardEntity.CardNo = cardNo;
            if (offevent != null)
            {
                bl=offevent(this);
                
                if (bl == false) { return; };
            }
        }
    }</span>

3.添加了委托一定要再定义事件来调用么?

     看情况,你可以不用属性封装字段,但是在代码设计上来说,或者面向组件设计上来说,封装是一种设计原则,你学过设计模式,或者参与过大型系统的设计就会很容易理解这点。

4.什么情况下只要使用委托就可以,什么情况下必须配合事件使用?

     一般情况下建立组件模型都使用事件

      事件是组件中的抽象概念,同样包括状态和操作也是组件中的概念,对应到C#里面就是属性和方法。所以像控件之类的组件都会有事件。而委托代表一个代码的执行过程,C#3.0引入linq以后,用的就非常频繁了。

5.什么情况使用观察者模式
     当抽象个体有两个互相依赖的方面时。封装这些方面在单独的对象内可允许程序员单独地去变更与重复使用这些类,而不会产生两者之间交互的问题。
      当其中一个对象的变更会影响其他对象,却又不知道多少对象必须被同时变更时。
      当对象应该有能力通知其他对象,又不应该知道其他对象的内部细节时。
      观察者模式常用在MVC和三层架构中。在 MVC 中,观察者模式被用来降低 model 与 view的耦合程度。一般而言, model 的改变会触发通知其他身为观察者的 view 。具体实例,见一位网友的文章
http://www.cnblogs.com/c-delight/archive/2005/12/27/305694.html

有关三层,请参考两篇文章: 

http://blog.csdn.net/shan9liang/article/details/6836300

http://blog.csdn.net/shan9liang/article/details/6840837

6.何时使用委托而不使用接口?

    注明委托是对方法的包装 ,在不确定要调用什么方法时候而又不能用抽象或者多态实现的时候用委托。

            比如一个button,当点击肯定要触发事件,做一些处理,如果你是这个控件的开发者,你怎么知道当点击是要处理什么?你这个button会被什么容器所包含?所以你必须公布一个event出去,用控件的人具体去实现其功能。  
参考
         1、如下情况宜使用委托:     
    
                      只调用单个方法时.     
                      当一个类需要方法说明的多重执行时.     
                       期望使用静态方法执行规范时.     
                       期望得到一个类似事件的模式时.     
                       调用者无需知道无需获取定义方法的对象时     
                       只想给少数既定组件分发执行规范时.     
                       想要简单的组成结构时.     

          2、如下情况宜使用接口:   
    
                       当规范定义了一组需要调用的相关方法时.     
                       一个类仅代表性地执行一次规范时.     
                       接口的调用者想映射接口类型以获取其他类或接口时

           3、对函数指针以.net的方式进行的封装,其实就是一个class。   
    
                  应用最多的就是事件,在事件的情况下委托就变成了对回调函数指针的封装。

      这篇博客讲了委托与事件的关系,其实委托与事件也不难,我们很容易用上,但是我在机房下机使用后,觉得这个地方其实并不适合用,而且产生了一些问题,详见下篇博客。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 22
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值