`
mmdev
  • 浏览: 12952199 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

[连载] 用C#进行思考(一)生产者和消费者

阅读更多

  生产者和消费者的概念其实在我脑中形成得比较晚,但是却是所有其他思想的根本,所以写在最前面。目的是让读者理解我的思想,而不是我的思想的形成过程。(事实上,很多技术作者忽略了这一点,他们按照自己的思考顺序写文章,结果是,大家知道他是“如何思考的”,但不知道他“思考了什么”。)

  生产者和消费者这两个名词借鉴于生物学。在生物学中的食物链里,被当作食物、提供能量一方被称作“生产者”,而吃掉食物、获取能量的一方被称作“消费者”。比如“大鱼吃小鱼,小鱼吃虾米”,对于“大鱼吃小鱼”来说,小鱼是食物,提供热量(能量),是生产者;而大鱼吃掉小鱼,获取了热量,是消费者。在对于“小鱼吃虾米”来说,虾米是食物,是生产者;而小鱼则是消费者。由此我们还看到了,消费者和生产者的角色是有可能重叠的,但对于特定的、具有“吃”与“被吃”关系的两者来说,其角色是固定的。

  在面向对象的程序设计中,生产者和消费者用来表示类型的角色。当两个类型涉及到“使用”与“被使用”的关系时,便出现了这两种角色。

  我们称提供一系列功能供其他类型调用的类型为“生产者”,而称调用其它类型提供的功能的类型为“消费者”。

  (下划线用于帮助读者断句。)

  例如常见的Windows Forms程序设计中,往往在一个窗体类中使用某些控件类,就窗体类和它所使用的某一个特定的控件类而言,控件类提供了功能,是生产者;而窗体类使用控件的功能,是消费者。

  这里简单插一句,什么是“使用”,当一个类A中的某个域(Field)或属性(Property)的类型是类B时,称“A使用了B”。“使用”也称“关联”、“聚合”等。

  生产者/消费者模式中的一个重要原则就是,永远是消费者主动,由消费者调用生产者。如果不幸发生了生产者必须调用消费者的情形,则不能直接使用方法或属性调用,而是要通过委托(将委托对象当作参数进行传递)或事件(将委托用作一种特殊的域)来实现,而这种反方向的调用(生产者调用消费者),称为“回调”

  现在来聊一聊3层架构。三层架构,自下而上为数据层、逻辑层、表现层。3层架构(或多层架构)有一个很重要的原则,就是只能上层调用下层,反之不行,跨层调用也不行。只有符合这种规则,才能写出漂亮的三层架构;否则即使分了层,代码也是凌乱不堪。

  为什么呢?用生产者/消费者模式可以很方便地解释。对于数据层和逻辑层而言,数据层提供存储、获取数据的基本功能,是生产者;而逻辑层使用数据层的这些功能,对数据进行进一步加工,是消费者。因此,只能由逻辑层调用数据层。

  再看逻辑层与表现层,逻辑层提供了对数据进行的处理,得到了可供显示的数据,是生产者;而表现层通过调用逻辑层的功能,从逻辑层得到处理过的数据进行显示,是消费者。所以必须由表现层调用逻辑层。

  事实上,表现层还提供了展示数据和接受输入的功能啊,那么它是?实际上,这说的是系统与用户的关系,表现层提供这些功能是给用户(自然人或其他程序)用的,所以在这里,表现层是生产者而用户是消费者。

  最后,生产者/消费者的确定,不是取决于谁调用谁;恰恰相反,我们应该在系统设计期间,就确定哪些类型之间存在“使用”关系,并确定在这二者之间,谁是生产者、谁是消费者。一旦这个角色确定下来,那么在具体实现(编码)的过程中,就牢牢遵守这一原则,由消费者调用生产者的方法,而生产者通过委托或事件回调消费者。

  一旦理解了生产者/消费者模式,并牢牢遵守“消费者主动,调用生产者”这一原则,写出的代码自然是漂亮的。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics