写给自己看的小设计7 - 对象设计过程之对象交互

  对象创建完了以后,就是互相协作完成系统的功能。对象的协作方式通常有如下方式:

直接引用,互通有无

  这种方式最为自然,最为直接,最为简单,也是通常情况下的首选。不管是传参数,还是直接创建后直接使用对象的方法,都是属于这种情况:

public class ComponentB
{
 public void Run(ComponentA componentA) { componentA.Say(); }
}

依靠中介通信

  当对象之间的交互复杂起来以后,直接的通信可能耦合度就太高了,这个时候要靠辅助对象来间接的传递信息,很多的设计模式其实都是该思想的衍生物,比如中介者模式,代理模式,外观模式等。

  这里看一个UI层的例子:程序的界面上有3个对象,分别是Panel,Timeline,Scrollbar;这些对象之间分属不同的层次结构,但是它们之间需要互相操作,比如Scrollbar动的时候,需要修改Timeline上的一些小控件,而且需要操作Panel的一些控件,操作Timeline上的内容的时候,需要检查是否需要滚动Scrollbar,是否需要操作Panel,总之就是这3个对象的其中一个动的话,另外两个都要有些操作需要进行。

  针对这个交互的问题,我大概有3种想法:

第一种:3个对象之间互相引用,当需要的时候就直接调用对方的方法。

  比如Panel类的伪代码就可能如下所示:

class Panel
{
  private Timeline m_timeline;
  private Scrollbar m_scrollbar;

  public void Action()
  {
    DoSomething();
    m_timeline.M1();
    m_scrollbar.M2();
  }
}

第二种:能否尝试使用事件来回调自己的方法。

  在脑海中就是那么一想,我决定放弃这个想法。

第三种:创建一个中介对象,所有交互的代码都放到这个中介中。

  中介者和Panel的伪代码如下:

class Mediator
{
  private Timeline m_timeline;
  private Scrollbar m_scrollbar;
  private Panel m_panel;

  public void Initialize(Timeline timeline, Scrollbar scrollbar, Panel panel)
  {
    m_timeline = timeline;
    m_scrollbar = scrollbar;
    m_panel = panel;
  }

  public void PanelAction()
  {
    m_timeline.M1();
    m_scrollbar.M2();
  }

  public void ScrollbarAction()
  {
    m_timeline.M1();
    m_panel.M3();
  }

  public void TimelineAction()
  {
    m_scrollbar.M2();
    m_panel.M3();
  }
}

class Panel
{
  Mediator m_mediator;
  public void Action()
  {
    DoSomething();
    m_mediator.PanelAction();
  }
}

如果说前两种实现是形成了3个对象之间的网状图的话,那么第三种实现其实是多加了中介者对象,4个对象形成了以中介者为中心的星状图。

  我实际采用了第三种实现来简化对象之间的交互关系。我这里并不想说第三种一定比前两种好,如果没有变化存在,只要是让系统正常工作的代码其实都是好代码。我总是认为,并不是任何时候状态模式就比分支语句更合适一个对象

  其实除了依靠进程内对象通信外,依靠程序外的媒介通信也属于这种情况,比如利用共享内存,Socket,文件系统中的文件,第三方消息队列(如MSMQ),分布式中间件等通信。

使用事件通信

  当对象之间通信方式同质化严重(工作方式基本类似,交互的方式也类似),特别是1对多的通信,而且交互对象数量较多,类型未知时,事件,或者说是观察者模式,或者说是发布订阅模式就可以使用起来了。

  让我再来回忆一下前面使用过的一个例子:

public class Program
{
 static void Main(string[] args)
 {
  User user = new User();
  View ui = new View(user);
  user.Name = "Hello";
 }
}

delegate void OnNameChange(string name);
class View
{
 public View(User user)
 {
  user.onNameChanged += user_onNameChanged;
 }

 void user_onNameChanged(string name)
 {
  Console.WriteLine(name);
 }
}

class User
{
 private string m_name;
 public string Name
 {
  get { return m_name; }
  set
  {
   m_name = value;
   onNameChanged(m_name);
  }
 }
 public event OnNameChange onNameChanged;
}

交互即耦合
  其实对象交互的方式,本质上就是描述了对象耦合的方式。强耦合的关系一旦面临变化,一般会引起较大范围的改动。众多模式的出现都是为了给对象解耦。
  对象之间的交互产生了对象之间的耦合,这是自然而有效的,对象之间就是要通过交互而形成流程,进而完成整个业务。除了上面这些描述的耦合方式,其实还有一个耦合方式更加紧密,那就是继承。
  看一段简单的代码:

class Base {}
class Derived : Base {}

这样简单的代码,其实就是形成了一个相当紧密的耦合:Base的任何修改都会毫无保留的传递给Derived。

  同时,给予这样的一个分析,我们可以解释一个常识:为什么基类要尽量的抽象,不完成特别具体的细节。这么做就是为了尽量维护基类的稳定,让基类尽量不变化

  总结来说,对象交互的常用方式就是:"继承+组合(直接引用)+中介+事件",而这些方式的耦合级别也是基本按这个顺序越来越弱

时间: 2024-08-02 14:30:09

写给自己看的小设计7 - 对象设计过程之对象交互的相关文章

写给自己看的小设计3 - 对象设计通用原则之核心原则

由于对象设计的核心是类,所以下面的原则也都基本都是讨论类的设计问题,其它类型的元素都比较简单,基本上也符合大多数这里列出的原则. 前面我们分析完了对象设计的基本原则,这里我将重新温习一下对象设计的核心原则 - SOLID原则.几乎所有的设计模式都可以看到这些原则的影子. 单一职责原则(SRP):做一个专一的人 单一职责原则的全称是Single Responsibility Principle,简称是SRP.SRP原则的定义很简单: 即不能存在多于一个导致类变更的原因.简单的说就是一个类只负责一项

写给自己看的小设计4 - 对象设计通用原则之扩展原则

除了前面学习的那些核心原则,还有一些衍生的原则,掌握它们,你将更好的面向对象.不妨称它们为"扩展原则"吧. 迪米特法则:尽量不与无关的类发生关系. 迪米特法则全称Law of Demeter,简称LoD,也称为最少知识原则(Least Knowledge Principle,LKP).这个原则没什么固定的定义,大体上有这么几种说法: 1. 只与你的朋友说话 2. 不和陌生人说话 3. 对象应该只与必须交互的对象通信 通俗地讲,一个类应该对自己需要调用的类知道得最少,你调用的类的内部是如

写给自己看的小设计5 - 对象设计过程之设计目标

浏览完代码设计中对象设计的核心准则和扩展原则后,最后我们再回头看看另外一个原则不像原则,规则不像规则,模式不像模式,实践不像实践的四不像原则 - GRASP原则. 说到对象设计原则,就不能不提GRASP原则,但是从我来看,这个原则完全不是原则,而是设计过程. GRASP,全称为General Responsibility Assignment Software Pattern,即通用职责分配软件模式,它由<UML和模式应用>(Applying UML and Patterns)一书作者Crai

写给自己看的小设计6 - 对象设计过程之对象创建

对象创建是面向对象程度的最常见活动之一.对象的创建通常有两种方式:直接创建,或者是间接创建. 直接创建对象 直接创建意味着由使用对象的元素直接创建对象,然后使用对象.这种方式最常用,也是对象之间建立耦合的最常见方式,也是如非必要,优先考虑的对象创建方式.例如下面的C#代码: public class ComponentA { // 类的成员直接new出来 ComponentB m_componentB = new ComponentB(); public ComponentA() { } pub

读书笔记:《写给大家看的设计书》

读书笔记:<写给大家看的设计书> <写给大家看的设计书>这本书本来是买给孩子看的,孩子对板报.杂志.名片等设计很感 兴趣,想看点基础的设计类的书籍,就给她找了一本.书到手后,我随手翻了翻发现对于我制作PPT还是很有帮助的,对于非专业设计人员来说,掌握4条设计原 则确实可以让设计感觉到非常专业,这几条原则应用于网站的设计也是同样有效. 全书三大部分,共14章,第一部分(第1-8章)最有用,讲述四大设计原则,第二部分(第9-11章)讲字体设计,第三部分有点像附录. 第一章 约书亚树 有

写给大家看的设计书(第3版)PDF下载高清完整扫描原版

这本书出自一位世界级设计师之手.复杂的设计原理在书中凝炼为亲密性.对齐.重复和对比4 个基本原则.作者以其简洁明快的风格,将优秀设计所必须遵循的这4 个基本原则及其背后的原理通俗易懂地展现在读者面前.本书包含大量的示例,让你了解怎样才能按照自己的方式设计出美观且内容丰富的产品. 此书适用于各行各业需要从事设计工作的读者,也适用于有经验的设计人员.需要学习的朋友可以通过网盘下载pdf版 http://putpan.com/fs/8y1i5bce5n5s1h8u0/ 作者简介 Robin Willi

写给大家看的设计书——读后笔记

<写给大家看的设计书>介绍了设计的四个基本原则:亲密性.对齐.重复.对比.作为一个软件"设计师",我也来聊聊读过这本书之后,我对这四个原则的一点理解. 亲密性 亲密性原则是指:内涵相关联的内容,在结构.关系上也应保持关联.        以软件设计的角度来说,一项业务所包含的功能.一个功能所包含的代码,应该在结构.关系上保持关联.例如把这些代码放到同一个包下.用同一套规则来命名.这样,当我们需要查阅.修改这个功能,需要处理哪些代码就"一望而知"了.   

读书笔记:《写给大家看的面向对象设计》,《程序员的职业素养》,《设计模式其实很简单》

按照上次的计划 看了三本书,笔记现在才贴出来. <写给大家看的面向对象设计>: 使用接口开发的作用 规范函数命名,特别在项目人数比较多,在设计时,定了接口命名与参数. 可以把前台与后台的脱离.定义接口后,实现接口并返回模拟的数据,例如DataTable等,前台不需等后台就可以做UI与交互,改善UI与需要的数据,发现问题并不断完善接口.后台按照需求把数据库设计好了(如果是领域驱动开发,是Model创建),按照这个接口来开发功能,完成之后前台切换过来即可.前后台是并行开发. 便于单元测试的编写,其

写给大家看的编程规范

(本文参加 2014 CSDN博文大赛,谢谢.) [文章摘要] "没有规矩,不成方圆",在实际的软件开发项目中,做任何事情都不是随心所欲的,我们编写代码需要遵守项目组约定的编程规范.很遗憾,在学校的计算机课程中,重在教导学生实现一定的程序功能,对程序的编写规范很少提及,这也就导致了从学校毕业踏上工作岗位之后一段艰辛的学习过程. 本文根据自身的软件开发实践,对实际的软件开发项目中编写C语言和SQL语言程序时所需遵守的规范进行了详细的介绍,旨在让广大即将从事软件开发工作的程序员们懂得编程规