[连载] 用C#进行思考(三 之 前传)用委托实现回调

  前文提到过回调。也就是当发生不得不由生产者调用消费者时,不能直接使用方法调用,必须使用回调。

(插:虽然在这里我对回调提出了新的定义,但实际上与传统意义上的回调并不冲突。试想一下Windows中的回调,基本上都是系统为我们提供了一写功能[生产者],而我们在调用这些功能时,又必须为其提供一个操作,以便其进行调用,这时才会产生回调。)

  在.NET中,使用委托实现回调。委托有两种方式——将委托作为参数传递、将委托作为类的域(Field)成员。前者就是这里要说的,很简单;而后者,放在下一篇文章再说,作为域成员的委托直接导致了事件的诞生。

  考虑在老板(消费者)和员工(生产者)之间,老板希望在员工做完工作后进行检查。

//  Boss.cs
public   class  Boss
{
    Employee m_anEmployee 
= new Employee();

    
public viod DispatchJob()
    
{
        
try  // 异常处理在大多数情况下是需要的,因为工作不一定成功
        {
            m_anEmployee.DoJob();
            m_check();  
// 检查工作
            
// 将“工作状态”改为“完成”
        }

        
catch(Exception ex)
        
{
            
// 处理异常情况
            
// 将“工作状态”改为“错误”
        }

    }


    
private void m_check()
    
{
        
// 执行对工作的检查
    }

}


//  Employee.cs
public   class  Employee
{
    
public void DoJob()
    
{
        
// 完成工作,出错时抛异常
    }

}

  在这里,作为消费者的老板,做了太多的事情(无论出于实际生活,还是出于在编程中的体验,都是不合理的)。因此这里也暴露出一种经验,就是当你发现你的一个类型,作为生产者的角色时,其实现太过简单,那么说明你的设计一定是有问题的。

  考虑这样一个问题,如果在使用Employee时,忘记作异常处理怎么办?忘记了调用check,没有检查工作怎么办?又或者不忘,那么每写一个用到了员工的类型或方法时,都要添加这样的代码,重复工作也是不能忍的。尤其是当DoJob方法要消耗大量时间时,每个调用都要在Boss中单独开启后台线程,工作量繁重且易出错。注意在这种方式下不能在DoJob中开启后台线程,否则就不能保证m_check方法是在DoJob完成后调用的。

  考虑使用回调。

//  Boss.cs
public   class  Boss
{
    Employee m_anEmployee 
= new Employee();

    
public viod DispatchJob()
    
{
        JobFinishedCallback cb 
= new JobFinishedCallback(m_check);
        m_anEmployee.DoJob(cb);  
// 使用回调,简化了调用
    }


    
private void m_check(JobState s)
    
{
        
if(s = JobState.Finished)
            
// 进行具体的检查
        else
            
// 处理错误
    }

}


//  Employee.cs
public   delegate   void  JobFinishedCallback(JobState s);

public   enum  JobState
{
    Finised, Error
}


public   class  Employee
{
    
public void DoJob(JobFinishedCallback cb)
    
{
        
try  // 可以在DoJob内部处理错误
        {
            
// 完成工作,出错时抛异常
            if(cb != null)
                cb(JobState.Finished);
        }

        
catch(Exception)
        
{
            
if(cb != null)
                cb(JobState.Error);
        }

    }

}

  现在,Boss的实现变得非常简单。如果需要添加后台线程,也只需在Employee中添加即可。甚至,还可以将多个方法链接到cb回调中(别忘了C#使用多播委托),用一系列方法来处理JobFinished这件事。(咦,事件的概念是不是冒出来了?且听下回分解。)

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值