// 具体中介者类可解开各组件之间相互交叉的连接关系并将其转移到中介者中。 class AuthenticationDialog implements Mediator is private field title: string private field loginOrRegisterChkBx: Checkbox private field loginUsername, loginPassword: Textbox private field registrationUsername, registrationPassword, registrationEmail: Textbox private field okBtn, cancelBtn: Button
namespaceRefactoringGuru.DesignPatterns.Mediator.Conceptual { // The Mediator interface declares a method used by components to notify the // mediator about various events. The Mediator may react to these events and // pass the execution to other components. publicinterfaceIMediator { voidNotify(object sender, string ev); }
// Concrete Mediators implement cooperative behavior by coordinating several // components. classConcreteMediator : IMediator { private Component1 _component1;
publicvoidNotify(object sender, string ev) { if (ev == "A") { Console.WriteLine("Mediator reacts on A and triggers folowing operations:"); this._component2.DoC(); } if (ev == "D") { Console.WriteLine("Mediator reacts on D and triggers following operations:"); this._component1.DoB(); this._component2.DoC(); } } }
// The Base Component provides the basic functionality of storing a // mediator's instance inside component objects. classBaseComponent { protected IMediator _mediator;
// Concrete Components implement various functionality. They don't depend on // other components. They also don't depend on any concrete mediator // classes. classComponent1 : BaseComponent { publicvoidDoA() { Console.WriteLine("Component 1 does A.");
this._mediator.Notify(this, "A"); }
publicvoidDoB() { Console.WriteLine("Component 1 does B.");
this._mediator.Notify(this, "B"); } }
classComponent2 : BaseComponent { publicvoidDoC() { Console.WriteLine("Component 2 does C.");
this._mediator.Notify(this, "C"); }
publicvoidDoD() { Console.WriteLine("Component 2 does D.");
this._mediator.Notify(this, "D"); } } classProgram { staticvoidMain(string[] args) { // The client code. Component1 component1 = new Component1(); Component2 component2 = new Component2(); new ConcreteMediator(component1, component2);
#include<iostream> #include<string> /** * The Mediator interface declares a method used by components to notify the * mediator about various events. The Mediator may react to these events and * pass the execution to other components. */ classBaseComponent; classMediator { public: virtualvoidNotify(BaseComponent *sender, std::string event)const= 0; };
/** * The Base Component provides the basic functionality of storing a mediator's * instance inside component objects. */ classBaseComponent { protected: Mediator *mediator_;
/** * Concrete Components implement various functionality. They don't depend on * other components. They also don't depend on any concrete mediator classes. */ classComponent1 : public BaseComponent { public: voidDoA(){ std::cout << "Component 1 does A.\n"; this->mediator_->Notify(this, "A"); } voidDoB(){ std::cout << "Component 1 does B.\n"; this->mediator_->Notify(this, "B"); } };
classComponent2 : public BaseComponent { public: voidDoC(){ std::cout << "Component 2 does C.\n"; this->mediator_->Notify(this, "C"); } voidDoD(){ std::cout << "Component 2 does D.\n"; this->mediator_->Notify(this, "D"); } };
/** * Concrete Mediators implement cooperative behavior by coordinating several * components. */ classConcreteMediator : public Mediator { private: Component1 *component1_; Component2 *component2_;
public: ConcreteMediator(Component1 *c1, Component2 *c2) : component1_(c1), component2_(c2) { this->component1_->set_mediator(this); this->component2_->set_mediator(this); } voidNotify(BaseComponent *sender, std::string event)constoverride{ if (event == "A") { std::cout << "Mediator reacts on A and triggers following operations:\n"; this->component2_->DoC(); } if (event == "D") { std::cout << "Mediator reacts on D and triggers following operations:\n"; this->component1_->DoB(); this->component2_->DoC(); } } };
/** * Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. */ publicclassAddButtonextendsJButtonimplementsComponent { private Mediator mediator;
/** * Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. */ publicclassDeleteButtonextendsJButtonimplementsComponent { private Mediator mediator;
/** * Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. */ publicclassFilterextendsJTextFieldimplementsComponent { private Mediator mediator; private ListModel listModel;
/** * Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. */ @SuppressWarnings("unchecked") publicclassListextendsJListimplementsComponent { private Mediator mediator; privatefinal DefaultListModel LIST_MODEL;
/** * Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. */ publicclassSaveButtonextendsJButtonimplementsComponent { private Mediator mediator;
/** * Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. */ publicclassTextBoxextendsJTextAreaimplementsComponent { private Mediator mediator;
/** * Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. */ publicclassTitleextendsJTextFieldimplementsComponent { private Mediator mediator;
/** * Concrete mediator. All chaotic communications between concrete components * have been extracted to the mediator. Now components only talk with the * mediator, which knows who has to handle a request. */ publicclassEditorimplementsMediator { private Title title; private TextBox textBox; private AddButton add; private DeleteButton del; private SaveButton save; private List list; private Filter filter;
privateJLabeltitleLabel=newJLabel("Title:"); privateJLabeltextLabel=newJLabel("Text:"); privateJLabellabel=newJLabel("Add or select existing note to proceed..."); /** * Here the registration of components by the mediator. */ @Override publicvoidregisterComponent(Component component) { component.setMediator(this); switch (component.getName()) { case"AddButton": add = (AddButton)component; break; case"DelButton": del = (DeleteButton)component; break; case"Filter": filter = (Filter)component; break; case"List": list = (List)component; this.list.addListSelectionListener(listSelectionEvent -> { Notenote= (Note)list.getSelectedValue(); if (note != null) { getInfoFromList(note); } else { clear(); } }); break; case"SaveButton": save = (SaveButton)component; break; case"TextBox": textBox = (TextBox)component; break; case"Title": title = (Title)component; break; } }
/** * Various methods to handle requests from particular components. */ @Override publicvoidaddNewNote(Note note) { title.setText(""); textBox.setText(""); list.addElement(note); }
/** * The Mediator interface declares a method used by components to notify the * mediator about various events. The Mediator may react to these events and * pass the execution to other components. */ interfaceMediator { publicfunctionnotify(object$sender, string$event): void; }
/** * Concrete Mediators implement cooperative behavior by coordinating several * components. */ classConcreteMediatorimplementsMediator { private$component1;
publicfunctionnotify(object$sender, string$event): void { if ($event == "A") { echo"Mediator reacts on A and triggers following operations:\n"; $this->component2->doC(); }
if ($event == "D") { echo"Mediator reacts on D and triggers following operations:\n"; $this->component1->doB(); $this->component2->doC(); } } }
/** * The Base Component provides the basic functionality of storing a mediator's * instance inside component objects. */ classBaseComponent { protected$mediator;
/** * Concrete Components implement various functionality. They don't depend on * other components. They also don't depend on any concrete mediator classes. */ classComponent1extendsBaseComponent { publicfunctiondoA(): void { echo"Component 1 does A.\n"; $this->mediator->notify($this, "A"); }
/** * The Event Dispatcher class acts as a Mediator and contains the subscription * and notification logic. While a classic Mediator often depends on concrete * component classes, this one is only tied to their abstract interfaces. * * We are able to achieve this level of indirection thanks to the way the * connections between components are established. The components themselves may * subscribe to specific events that they are interested in via the Mediator's * subscription interface. * * Note, we can't use the PHP's built-in Subject/Observer interfaces here * because we'll be stretching them too far from what they were designed for. */ classEventDispatcher { /** * @var array */ private$observers = [];
publicfunction__construct() { // The special event group for observers that want to listen to all // events. $this->observers["*"] = []; }
/** * A simple helper function to provide global access to the event dispatcher. */ functionevents(): EventDispatcher { static$eventDispatcher; if (!$eventDispatcher) { $eventDispatcher = newEventDispatcher(); }
return$eventDispatcher; }
/** * The Observer interface defines how components receive the event * notifications. */ interfaceObserver { publicfunctionupdate(string$event, object$emitter, $data = null); }
/** * Unlike our Observer pattern example, this example makes the UserRepository * act as a regular component that doesn't have any special event-related * methods. Like any other component, this class relies on the EventDispatcher * to broadcast its events and listen for the other ones. * * @see \RefactoringGuru\Observer\RealWorld\UserRepository */ classUserRepositoryimplementsObserver { /** * @var array List of application's users. */ private$users = [];
/** * Components can subscribe to events by themselves or by client code. */ publicfunction__construct() { events()->attach($this, "users:deleted"); }
/** * Components can decide whether they'd like to process an event using its * name, emitter or any contextual data passed along with the event. */ publicfunctionupdate(string$event, object$emitter, $data = null): void { switch ($event) { case"users:deleted": if ($emitter === $this) { return; } $this->deleteUser($data, true); break; } }
// These methods represent the business logic of the class.
publicfunctioninitialize(string$filename): void { echo"UserRepository: Loading user records from a file.\n"; // ... events()->trigger("users:init", $this, $filename); }
publicfunctioncreateUser(array$data, bool$silent = false): User { echo"UserRepository: Creating a user.\n";
/** * All objects can trigger events. */ publicfunctiondelete(): void { echo"User: I can now delete myself without worrying about the repository.\n"; events()->trigger("users:deleted", $this, $this); } }
/** * This Concrete Component logs any events it's subscribed to. */ classLoggerimplementsObserver { private$filename;
echo"Logger: I've written '$event' entry to the log.\n"; } }
/** * This Concrete Component sends initial instructions to new users. The client * is responsible for attaching this component to a proper user creation event. */ classOnboardingNotificationimplementsObserver { private$adminEmail;
UserRepository: Loading user records from a file. EventDispatcher: Broadcasting the 'users:init' event. Logger: I've written 'users:init' entry to the log. UserRepository: Creating a user. EventDispatcher: Broadcasting the 'users:created' event. OnboardingNotification: The notification has been emailed! Logger: I've written 'users:created' entry to the log. User: I can now delete myself without worrying about the repository. EventDispatcher: Broadcasting the 'users:deleted' event. UserRepository: Deleting a user. Logger: I've written 'users:deleted' entry to the log.
from __future__ import annotations from abc import ABC
classMediator(ABC): """ The Mediator interface declares a method used by components to notify the mediator about various events. The Mediator may react to these events and pass the execution to other components. """
defnotify(self, sender: object, event: str) -> None: if event == "A": print("Mediator reacts on A and triggers following operations:") self._component2.do_c() elif event == "D": print("Mediator reacts on D and triggers following operations:") self._component1.do_b() self._component2.do_c()
classBaseComponent: """ The Base Component provides the basic functionality of storing a mediator's instance inside component objects. """
""" Concrete Components implement various functionality. They don't depend on other components. They also don't depend on any concrete mediator classes. """
classComponent1(BaseComponent): defdo_a(self) -> None: print("Component 1 does A.") self.mediator.notify(self, "A")
defdo_b(self) -> None: print("Component 1 does B.") self.mediator.notify(self, "B")
classComponent2(BaseComponent): defdo_c(self) -> None: print("Component 2 does C.") self.mediator.notify(self, "C")
defdo_d(self) -> None: print("Component 2 does D.") self.mediator.notify(self, "D")
if __name__ == "__main__": # The client code. c1 = Component1() c2 = Component2() mediator = ConcreteMediator(c1, c2)
print("Client triggers operation A.") c1.do_a()
print("\n", end="")
print("Client triggers operation D.") c2.do_d()
Output.txt: 执行结果
1 2 3 4 5 6 7 8 9 10 11
Client triggers operation A. Component 1 does A. Mediator reacts on A and triggers following operations: Component 2 does C.
Client triggers operation D. Component 2 does D. Mediator reacts on D and triggers following operations: Component 1 does B. Component 2 does C.
# The Mediator interface declares a method used by components to notify the # mediator about various events. The Mediator may react to these events and pass # the execution to other components. classMediator # @abstract # # @param [Object] sender # @param [String] event defnotify(_sender, _event) raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'" end end
# @param [Object] sender # @param [String] event defnotify(_sender, event) if event == 'A' puts 'Mediator reacts on A and triggers following operations:' @component2.do_c elsif event == 'D' puts 'Mediator reacts on D and triggers following operations:' @component1.do_b @component2.do_c end end end
# The Base Component provides the basic functionality of storing a mediator's # instance inside component objects. classBaseComponent # @return [Mediator] attr_accessor:mediator
# @param [Mediator] mediator definitialize(mediator = nil) @mediator = mediator end end
# Concrete Components implement various functionality. They don't depend on # other components. They also don't depend on any concrete mediator classes. classComponent1 < BaseComponent defdo_a puts 'Component 1 does A.' @mediator.notify(self, 'A') end
defdo_b puts 'Component 1 does B.' @mediator.notify(self, 'B') end end
classComponent2 < BaseComponent defdo_c puts 'Component 2 does C.' @mediator.notify(self, 'C') end
defdo_d puts 'Component 2 does D.' @mediator.notify(self, 'D') end end
/// The Mediator interface declares a method used by components to notify the /// mediator about various events. The Mediator may react to these events and /// pass the execution to other components. protocolMediator: AnyObject {
funcnotify(sender: BaseComponent, event: String) { if event =="A" { print("Mediator reacts on A and triggers following operations:") self.component2.doC() } elseif (event =="D") { print("Mediator reacts on D and triggers following operations:") self.component1.doB() self.component2.doC() } } }
/// The Base Component provides the basic functionality of storing a mediator's /// instance inside component objects. classBaseComponent {
/// Concrete Components implement various functionality. They don't depend on /// other components. They also don't depend on any concrete mediator classes. classComponent1: BaseComponent {
let numberOfGivenLikes = newsArray.reduce(0, { $0+$1.likesCount })
let mediator =ScreenMediator()
let feedVC =NewsFeedViewController(mediator, newsArray) let newsDetailVC =NewsDetailViewController(mediator, newsArray.first!) let profileVC =ProfileViewController(mediator, numberOfGivenLikes)
print("News Feed: Received a liked news model with id \(news.id)")
forvar item in newsArray { if item == news { item.likesCount +=1 } } }
funclikeRemoved(fromnews: News) {
print("News Feed: Received a disliked news model with id \(news.id)")
forvar item in newsArray { if item == news { item.likesCount -=1 } } }
funcuserLikedAllNews() { print("\n\nNews Feed: User LIKED all news models") print("News Feed: I am telling to mediator about it...\n") newsArray.forEach({ mediator?.likeAdded(to: $0) }) }
funcuserDislikedAllNews() { print("\n\nNews Feed: User DISLIKED all news models") print("News Feed: I am telling to mediator about it...\n") newsArray.forEach({ mediator?.likeRemoved(from: $0) }) } }
funclikeAdded(tonews: News) { print("News Detail: Received a liked news model with id \(news.id)") ifself.news == news { self.news.likesCount +=1 } }
funclikeRemoved(fromnews: News) { print("News Detail: Received a disliked news model with id \(news.id)") ifself.news == news { self.news.likesCount -=1 } } }
classProfileViewController: ScreenUpdatable {
privatevar numberOfGivenLikes: Int privateweakvar mediator: ScreenUpdatable?
funclikeAdded(tonews: News) { print("Screen Mediator: Received a liked news model with id \(news.id)") screens?.forEach({ $0.likeAdded(to: news) }) }
funclikeRemoved(fromnews: News) { print("ScreenMediator: Received a disliked news model with id \(news.id)") screens?.forEach({ $0.likeRemoved(from: news) }) } }
News Feed: User LIKED all news models News Feed: I am telling to mediator about it...
Screen Mediator: Received a liked news model with id 1 News Feed: Received a liked news model with id 1 News Detail: Received a liked news model with id 1 Profile: Received a liked news model with id 1 Screen Mediator: Received a liked news model with id 2 News Feed: Received a liked news model with id 2 News Detail: Received a liked news model with id 2 Profile: Received a liked news model with id 2
News Feed: User DISLIKED all news models News Feed: I am telling to mediator about it...
ScreenMediator: Received a disliked news model with id 1 News Feed: Received a disliked news model with id 1 News Detail: Received a disliked news model with id 1 Profile: Received a disliked news model with id 1 ScreenMediator: Received a disliked news model with id 2 News Feed: Received a disliked news model with id 2 News Detail: Received a disliked news model with id 2 Profile: Received a disliked news model with id 2
/** * The Mediator interface declares a method used by components to notify the * mediator about various events. The Mediator may react to these events and * pass the execution to other components. */ interfaceMediator { notify(sender: object, event: string): void; }
/** * Concrete Mediators implement cooperative behavior by coordinating several * components. */ classConcreteMediatorimplementsMediator { privatecomponent1: Component1;
publicnotify(sender: object, event: string): void { if (event === 'A') { console.log('Mediator reacts on A and triggers following operations:'); this.component2.doC(); }
if (event === 'D') { console.log('Mediator reacts on D and triggers following operations:'); this.component1.doB(); this.component2.doC(); } } }
/** * The Base Component provides the basic functionality of storing a mediator's * instance inside component objects. */ classBaseComponent { protectedmediator: Mediator;
/** * Concrete Components implement various functionality. They don't depend on * other components. They also don't depend on any concrete mediator classes. */ classComponent1extendsBaseComponent { publicdoA(): void { console.log('Component 1 does A.'); this.mediator.notify(this, 'A'); }