Design Pattern----20.Behavioral.Mediator.Pattern (Delphi Sample)

Intent

  • Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.
  • Design an intermediary to decouple many peers.
  • Promote the many-to-many relationships between interacting peers to “full object status”.

Problem

We want to design reusable components, but dependencies between the potentially reusable pieces demonstrates the “spaghetti code” phenomenon (trying to scoop a single serving results in an “all or nothing clump”).

Discussion

In Unix, permission to access system resources is managed at three levels of granularity: world, group, and owner. A group is a collection of users intended to model some functional affiliation. Each user on the system can be a member of one or more groups, and each group can have zero or more users assigned to it. Next figure shows three users that are assigned to all three groups.

Mediator example

If we were to model this in software, we could decide to have User objects coupled to Group objects, and Group objects coupled to User objects. Then when changes occur, both classes and all their instances would be affected.

An alternate approach would be to introduce “an additional level of indirection” - take the mapping of users to groups and groups to users, and make it an abstraction unto itself. This offers several advantages: Users and Groups are decoupled from one another, many mappings can easily be maintained and manipulated simultaneously, and the mapping abstraction can be extended in the future by defining derived classes.

Mediator example

Partitioning a system into many objects generally enhances reusability, but proliferating interconnections between those objects tend to reduce it again. The mediator object: encapsulates all interconnections, acts as the hub of communication, is responsible for controlling and coordinating the interactions of its clients, and promotes loose coupling by keeping objects from referring to each other explicitly.

The Mediator pattern promotes a “many-to-many relationship network” to “full object status”. Modelling the inter-relationships with an object enhances encapsulation, and allows the behavior of those inter-relationships to be modified or extended through subclassing.

An example where Mediator is useful is the design of a user and group capability in an operating system. A group can have zero or more users, and, a user can be a member of zero or more groups. The Mediator pattern provides a flexible and non-invasive way to associate and manage users and groups.

Structure

Mediator scheme

Colleagues (or peers) are not coupled to one another. Each talks to the Mediator, which in turn knows and conducts the orchestration of the others. The “many to many” mapping between colleagues that would otherwise exist, has been “promoted to full object status”. This new abstraction provides a locus of indirection where additional leverage can be hosted.

Mediator scheme

Example

The Mediator defines an object that controls how a set of objects interact. Loose coupling between colleague objects is achieved by having colleagues communicate with the Mediator, rather than with each other. The control tower at a controlled airport demonstrates this pattern very well. The pilots of the planes approaching or departing the terminal area communicate with the tower rather than explicitly communicating with one another. The constraints on who can take off or land are enforced by the tower. It is important to note that the tower does not control the whole flight. It exists only to enforce constraints in the terminal area.

Mediator example

Check list

  1. Identify a collection of interacting objects that would benefit from mutual decoupling.
  2. Encapsulate those interactions in the abstraction of a new class.
  3. Create an instance of that new class and rework all “peer” objects to interact with the Mediator only.
  4. Balance the principle of decoupling with the principle of distributing responsibility evenly.
  5. Be careful not to create a “controller” or “god” object.

Rules of thumb

  • Chain of Responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. Chain of Responsibility passes a sender request along a chain of potential receivers. Command normally specifies a sender-receiver connection with a subclass. Mediator has senders and receivers reference each other indirectly. Observer defines a very decoupled interface that allows for multiple receivers to be configured at run-time.
  • Mediator and Observer are competing patterns. The difference between them is that Observer distributes communication by introducing “observer” and “subject” objects, whereas a Mediator object encapsulates the communication between other objects. We’ve found it easier to make reusable Observers and Subjects than to make reusable Mediators.
  • On the other hand, Mediator can leverage Observer for dynamically registering colleagues and communicating with them.
  • Mediator is similar to Facade in that it abstracts functionality of existing classes. Mediator abstracts/centralizes arbitrary communication between colleague objects, it routinely “adds value”, and it is known/referenced by the colleague objects (i.e. it defines a multidirectional protocol). In contrast, Facade defines a simpler interface to a subsystem, it doesn’t add new functionality, and it is not known by the subsystem classes (i.e. it defines a unidirectional protocol where it makes requests of the subsystem classes but not vice versa).

Mediator in Delphi

Object oriented design encourages the distribution of behaviour among objects. Such distribution can result in an object structure with many connections between objects; in the worst case, every object ends up knowing about every other.

Though partitioning a system into many objects generally enhances reusability, proliferating interconnections tend to reduce it again. Lots of interconnections make it less likely that an object can work without the support of others - the system acts as though it were monolithic. Moreover it can be difficult to change the systems’ behaviour in any significant way, since behaviour is distributed among many objects. As a result, you may be forced to define many subclasses to customise the system’s behaviour.

Developers at Borland probably were aware of the above mentioned paragraphs when designing the Delphi Object Pascal language and the VCL components. Their solution to this problem is essentially: events (or method pointers). The use of events makes de-coupling of objects possible. The class TForm is their standard mediator class which handles (wires) events from components put on the form.

They even delivered a great tool with it: the Object Inspector. Being able to delegate behaviour to another class using events, saves you, for example, from subclassing TButton when you need a button that interacts with an TEdit control. The mediator is the form which handles all events and takes corresponding actions, coupling all related components together with snippets of code. Great. So what’s the need for a Mediator pattern?

Delphi’s Object Inspector uses RTTI and form designers to create event handlers on forms and Delphi’s component streaming mechanism takes care of actually wiring these events at run time.

If you ever manually created event handlers you know that you have to:

  • Create a event handler method with the correct parameter list and possibly the correct function result. Wire the event handler to the event with code like:
    FSample.OnChange := SampleChange;
  • Make sure you unwire the event again in appropriate cases to avoid wired objects from calling destroyed or otherwise illegal objects.

In order to construct a correct event handler method it needs the event type definition. The mediator pattern relies on these event type definitions to construct and update event handlers.

Implementation

Suppose we’ve created a class TComPort which encapsulates a serial port device driver. This class defines a series of events to asynchronously inform clients of state changes: data triggers, line errors etc. A TController class could ‘use a’ TComPort class to transmit data through a serial port.

This TController class would typically wire and handle the Comport events to update it’s internal state. Here’s an abstract of the interface and implementation of TComport and TController without the mediator:

 
 
  1: type 
  2:   TLineEvent = procedure (Sender: TObject; Error: TLineError) of object; 
  3:   TTriggerEvent = procedure (Sender: TObject; Trigger: TTrigger) of object; 
  4: 
  5:   TComPort = class (TObject) 
  6:   published 
  7:       property OnDataReceived: TTriggerEvent read FOnDataReceived write FOnDataReceived; 
  8:       property OnLineEvent: TLineEvent read FOnLineEvent write FOnLineEvent; 
  9:       property OnTimeOut: TNotifyEvent read FOnTimeOut write FOnTimeOut; 
 10:       property OnTransmitted: TNotifyEvent read FOnTransmitted write FOnTransmitted; 
 11:   end; 
 12: 
 13:   TController = class (TObject) 
 14:   private 
 15:     FComPort: TComPort; 
 16:   public 
 17:     constructor Create; 
 18:     destructor Destroy; override; 
 19:     property ComPort: TComPort read FComPort; 
 20:   end; 
 21: 
 22:   implementation 
 23: 
 24:   constructor TController.Create; 
 25:   begin 
 26:     inherited Create; 
 27:     FComPort := TComPort.Create; 
 28:   end; 
 29:  
 30:   destructor TController.Destroy; 
 31:   begin 
 32:     FComPort.Free; 
 33:     inherited Destroy; 
 34:   end; 
Now have a look at the same abstract for class TController with the mediator applied to this structure:
 
 
  1: TController = class (TObject) 
  2: private 
  3:   FComPort: TComPort; 
  4: protected 
  5:   procedure ComPortDataReceived(Sender: TObject; Trigger: TTrigger); 
  6:   procedure ComPortLineEvent(Sender: TObject; Error: TLineError); 
  7:   procedure ComPortTimeOut(Sender: TObject); 
  8:   procedure ComPortTransmitted(Sender: TObject); 
  9:   procedure UnwireComPort; 
 10:   procedure WireComPort; 
 11: public 
 12:   constructor Create; 
 13:   destructor Destroy; override; 
 14:   property ComPort: TComPort read FComPort; 
 15: end; 
 16: 
 17: implementation 
 18: 
 19: constructor TController.Create; 
 20: begin 
 21:   inherited Create; 
 22:   FComPort := TComPort.Create; 
 23:   //now wire comport calling the method created by the mediator
 24:   WireComport; 
 25: end; 
 26: 
 27: destructor TController.Destroy; 
 28: begin 
 29:   //make sure the comport is unwired again
 30:   UnwireComport; 
 31:   FComPort.Free; 
 32:   inherited Destroy; 
 33: end; 
 34: 
 35: procedure TController.ComPortDataReceived(Sender: TObject; Trigger: TTrigger); 
 36: begin 
 37: end; 
 38: 
 39: procedure TController.ComPortLineEvent(Sender: TObject; Error: TLineError); 
 40: begin 
 41: end; 
 42: 
 43: procedure TController.ComPortTimeOut(Sender: TObject); 
 44: begin 
 45: end; 
 46: 
 47: procedure TController.ComPortTransmitted(Sender: TObject); 
 48: begin 
 49: end; 
 50: 
 51: procedure TController.UnwireComPort; 
 52: begin 
 53:   FComPort.OnDataReceived := nil; 
 54:   FComPort.OnLineEvent := nil; 
 55:   FComPort.OnTimeOut := nil; 
 56:   FComPort.OnTransmitted := nil; 
 57: end; 
 58: 
 59: procedure TController.WireComPort; 
 60: begin 
 61:   FComPort.OnDataReceived := ComPortDataReceived; 
 62:   FComPort.OnLineEvent := ComPortLineEvent; 
 63:   FComPort.OnTimeOut := ComPortTimeOut; 
 64:   FComPort.OnTransmitted := ComPortTransmitted; 
 65: end; 
In this example notice: The wiring of the comport in constructor Create by a call to WireComPort. This method is optionally created by the mediator. The corresponding unwiring in destructor Destroy by a call to UnwireComPort. This method is optionally created by the mediator. The event handler methods which all have the correct signature (as defined in the event library), just like the Object Inspector would do.

转载于:https://www.cnblogs.com/xiuyusoft/archive/2011/07/01/2095417.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
未来社区的建设背景和需求分析指出,随着智能经济、大数据、人工智能、物联网、区块链、云计算等技术的发展,社区服务正朝着数字化、智能化转型。社区服务渠道由分散向统一融合转变,服务内容由通用庞杂向个性化、服务导向转变。未来社区将构建数字化生态,实现数据在线、组织在线、服务在线、产品智能和决策智能,赋能企业创新,同时注重人才培养和科研平台建设。 规划设计方面,未来社区将基于居民需求,打造以服务为中心的社区管理模式。通过统一的服务平台和应用,实现服务内容的整合和优化,提供灵活多样的服务方式,如推送式、订阅式、热点式等。社区将构建数据与应用的良性循环,提高服务效率,同时注重生态优美、绿色低碳、社会和谐,以实现幸福民生和产业发展。 建设运营上,未来社区强调科学规划、以人为本,创新引领、重点突破,统筹推进、整体提升。通过实施院落+社团自治工程,转变政府职能,深化社区自治法制化、信息化,解决社区治理中的重点问题。目标是培养有活力的社会组织,提高社区居民参与度和满意度,实现社区治理服务的制度机制创新。 未来社区的数字化解决方案包括信息发布系统、服务系统和管理系统。信息发布系统涵盖公共服务类和社会化服务类信息,提供政策宣传、家政服务、健康医疗咨询等功能。服务系统功能需求包括办事指南、公共服务、社区工作参与互动等,旨在提高社区服务能力。管理系统功能需求则涉及院落管理、社团管理、社工队伍管理等,以实现社区治理的现代化。 最后,未来社区建设注重整合政府、社会组织、企业等多方资源,以提高社区服务的效率和质量。通过建立社区管理服务综合信息平台,提供社区公共服务、社区社会组织管理服务和社区便民服务,实现管理精简、高效、透明,服务快速、便捷。同时,通过培育和发展社区协会、社团等组织,激发社会化组织活力,为居民提供综合性的咨询和服务,促进社区的和谐发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值