委托和事件(一)

委托、事件、Lambda表达式,下一个难关,准备开闯。

什么是委托?

委托是持有一个或多个方法的对象。所以,委托是可以执行的对象,当执行委托的时候,就是执行委托所持有的方法

举个栗子

有主管和员工两个类,主管类里有个方法是扣钱,员工类里有个方法是偷懒,那么这个时候就可以创建一个委托,即员工一但偷懒,主管就执行扣钱

比如员工类这么写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Employee
{
    private int salary; //员工薪水
    private Manager theManager; //该员工的主管
    
    //构造函数,初始化员工薪水和实际主管
    public Employee(Manager manager)
    {
        theManager = manager;
        salary = 8000;
    }
    
    //薪水属性
    public int Salary
    {
        get{ return salary; }
        set{ salary = value; }
    }
    
    //偷懒方法
    public void PlayGame()
    {
        ConsoleWriteline("员工开始玩游戏了...");
        theManager.RemoveMoney(this);
    }
}

下面是主管类:

1
2
3
4
5
6
7
8
9
10
11
public class Manager
{
    public void RemoveMoney(Employee employee)
    {
        ConsoleWriteline("开始扣钱!");
        
        employee.Salary -= 20;
        
        ConsoleWriteline("扣完钱了,还剩" + employee.Salary);
    }
}

Main方法可以这么写:

1
2
3
4
5
6
7
public static void Main(string[] args)
{
    Manager currentManager = new Manager();
    Employee currentWorker = new Employee(currentManager);
    
    currentWorker.PlayGame();
}

现在运行程序,可以很好的输出结果。但是,以上程序有些问题:

  1. 必须先创建主管,然后才能创建员工,也就是说要创建有效的员工,必须先创建主管,耦合度太高了;
  2. 如果功能需求发生变化,例如不是主管监督,而是经理监督,那么不但要增加经理类,而且要修改员工类。

这个时候,可以考虑使用委托。可以理解为两步:

第一步,首先要定义一个委托,即让主管监视员工

第二步,员工类里要有个事件(员工是激发该事件的对象),而这个事件由主管去执行。

定义委托:

public delegate void Play(Object Sender, System.EventArgs e)

注意,这里声明的是一个委托类型,而不是委托对象。这个委托类型是一个事件。也可以将委托类型声明为其它类型,例如int等。比如:delegate void MyDel(int value);

员工类的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Employee
{
    public int salary = 8000; //省略属性
    public event Play play; //创建事件对象
    
    public Employee()
    {
    }
    
    public void PlayGame()
    {
        System.EventArgs e = new EventArgs();
        OnPlayGame(this, e);
    }
    
    void OnPlayGame(object Sender, EventArgs e)
    {
        if(play != null)
        {
            play(Sender, e);
        }
    }  
}

主管类里要实现一个方法,这个方法与委托的返回值和参数一样(相同签名),给委托调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Manager
{
    public Manager()
    {
    }
    
    public void RemoveMoney(Object Sender, System.EventArgs e)
    {
        Employee emp = Sender as Employee;
        emp.salary -= 20;
        ConsoleWriteline("扣钱后还剩" + emp.salary);
    }
}

调用方法:

1
2
3
4
5
6
7
Manager theManager = new Manager();
Employee theEmp = new Employee();

theEmployee.play += new play(theManager.Removemoney);

e.PlayGame();
e.Playgame(); //玩一次扣一次

脑子不好使了,妈的,改天再琢磨,睡觉。

留言