博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

第14章 对象间的协作与信息交换

【简介】:面向对象的程序 =  对象 + 对象之间的相互协作关系。在任何一个面向对象程序开发过程中,设计好对象之间的协作关系与信息交换方式都属于开发的核心任务,本章主要介绍了“一对一”对象之间、“一对多”对象之间的相互协作与信息交换的基本方式等。

第1节 对象间信息交换的基本方式 

1、 对象协作的本质:就是对象间信息交换的问题,体现为对象之间的相互访问,即设置对象属性与调用对象方法。

2、对象间信息交换的方法:获取要访问对象的引用,设置对象属性与调用对象方法。

3、案例:主窗体向从窗体传递信息。

 主窗体代码:

namespace MultiFormProgram1
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();


frm
= new frmOther(); //创建从窗体对象

frm.Show();
//显示从窗体
}
private frmOther frm = null; //◆定义私有字段,用于引用从窗体对象,很重要哟!

private void btnSend_Click(object sender, EventArgs e)
{
frm.SetValue(txtUserInput.Text); //◆调用从窗体方法,传递参数值。

}
}
}

 从窗体代码:

namespace MultiFormProgram1
{
    public partial class frmOther : Form
    {
        public frmOther()
        {
            InitializeComponent();
        }
      
        //对从窗体的Label设置值
        public void SetValue(string s)
        {
            lblInfo.Text = "老大说:" + s;
        }
    }
}

 4、思考

A、除了用方法参数传递信息外,还有何方式?
    【答】:当然是对象的属性这种更直接的方式。

B、如果需要在主窗体与从窗体双向传递怎么办?
   【答】:建立双向关联,即每个对象都拥有对方的引用。即主窗体有一个私有字段引用从窗体,从窗体也有一个私有字段引用主窗体。

C、如何有很多对象都需要相互传递信息,用此方法行不行吗?
    【答】:行,但不够好。这时用委托来实现。因此,此技术最适合的场所是对象的一对一通信且只有很少的对象。

  

第二节 多对象协作与信息交换--广播信息

1、原理:利用委托类型的变量可以引用多个方法构成的列表(委托调用列表)。

2、案例:利用委托“广而告之”

主窗体代码:

namespace UseDelegate
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        private Action<int> ReceiverMethods;   //定义委托变量,用于引用方法
        private void btnNewForm_Click(object sender, EventArgs e)
        {
            NewForm();
        }

        
        private  void NewForm()
        {
            frmOther frm = new frmOther();
            ReceiverMethods += frm.ShowCounter;  //挂接从窗口的方法
            frm.Show();
        }

        private int counter = 0;//计数器
        private void btnClickMe_Click(object sender, EventArgs e)
        {
            counter++;
            if (ReceiverMethods != null)   
                ReceiverMethods(counter);   //方法调用
        }
    }
}

从窗口代码:

namespace UseDelegate
{
    public partial class frmOther : Form
    {
        public frmOther()
        {
            InitializeComponent();
        }

        public void ShowCounter(int counter)   //显示消息
        {
            lblInfo.Text = counter.ToString();

        }
    }
}

3、思考:

    A、利于事件是否也能实现“广播消息”?
           【答】:可以,因为事件的本质就是多路委托。思路:主窗体定义一个事件,从窗体对象响应之。

      B、能否通知的是不同类型的对象?
            【答】:可以,只要不同类型的对象的实例方法符合委托所确定的方法签名即可。

       C、它实现的原理是什么?
            【答】:充分利用委托的"多路"特性,实现了消息的传播(具体是通过方法参数传递的)。 

 

第三节 多对象协作与信息交换--一个对象“监控”多个对象

 1、本节介绍的是“反方向”的信息传播问题,即多个对象向一个对象发送信息,可形象地比喻成:一个对象监控多个对象。

2、案例:从窗体向主窗体传递信息:

 

主窗口代码:

namespace ButtonCounterForMultiFormUseDelegate
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}

private int counter = 0;
/// <summary>
/// 显示累计按钮单击次数的结果
/// </summary>
private void ShowCounter()
{
counter
++;
lblInfo.Text
= counter.ToString();
}

private void btnShowOtherForm_Click(object sender, EventArgs e)
{
frmOther frm
= new frmOther();
//◆◆将主窗体的方法“挂接”到从窗体对象上
frm.CallBackMethod = this.ShowCounter;
//在屏幕上显示从窗体
frm.Show();
}

}
}

从窗体代码:

namespace ButtonCounterForMultiFormUseDelegate
{
public partial class frmOther : Form
{
public frmOther()
{
InitializeComponent();
}

public Action CallBackMethod = null; //◆定义委托变量,用于引用方法

private void btnClickMe_Click(object sender, EventArgs e)
{

//回调主窗体的方法,显示按钮计数
if (CallBackMethod != null)
CallBackMethod(); //◆回调主窗体的方法
}

}
}

3、思考:

   A、为什么在从窗体中定义委托变量,而不是在主窗体中定义?
      【答】:因为实际需求是:当点击从窗体的按钮时,回调主窗体的方法来显示次数。

   B、能否可以用事件机制实现?
      【答】:可以。

      C、除了利用委托或事件实现外,有无别的方法?
      【答】:有的,第一种就是利用组合关系,即让从窗体对象持有主窗体对象的引用,即第一节介绍的方法。
        第二种方式从窗体利用静态方法主动通知主窗体,这种方法本质上是定义了“全局”的字段与方法。
       用委托实现,可以不需要相互执有对方的引用,从而减少了对象之间的耦合度。