当系统内的物件们各自沟通的情况日益严重时,建立一个负责沟通的集中所,让元件们不在「直接」,而是「间接」与他者沟通。
通常在程序刚开发的时候,为了快速达到开发目的,可能会出现物件们直接与其他物件沟通,像是:
随着物件的数量增长,交互沟通的情况宛如人际连结的网络般,越来越复杂,这在开发上绝对不是一件好事,日後如果有修改的需求,很容易变成上 Patch 的情况。
因此,可以建立一个负责沟通的物件,所有物件都要通过该物件才能完成沟通的工作,至少让复杂、混乱的沟通关系简化成星状图,
作法是:
以下范例以「自行车队的行动」为核心制作。
系统内的物件亲代:Player
public interface Player {
void setMediator(Mediator mediator);
String getName();
String getJob();
}
负责沟通的物件亲代:Mediator
public interface Mediator {
void registerPlayer(Player player);
void changeFormation(int type);
void accelerate();
void decelerate();
void notifyTeamMembers(String message, Player requester);
}
系统内的物件子代:Sprinter
、Domestique
、TimeTrialist
、ClimbingSpecialist
public class Sprinter implements Player {
private String name;
private String job = "Sprinter";
private Mediator mediator;
public Sprinter(String name) {
this.name = name;
}
@Override
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
@Override
public String getName() {
return name;
}
@Override
public String getJob() {
return job;
}
public void teamChangeFormation(int type) {
mediator.changeFormation(type);
}
public void changeFormation(int position) {
System.out.println(job + " 收到通知,移动到车队的第 " + position + " 个位置");
}
public void teamAccelerate() {
mediator.accelerate();
}
public void personalAccelerate() {
System.out.println("车手 " + name + " 收到通知,开始加速");
}
public void teamDecelerate() {
mediator.decelerate();
}
public void personalDecelerate() {
System.out.println("车手 " + name + " 收到通知,开始减速");
}
public void notifyTeamMembers(String message) {
mediator.notifyTeamMembers(message, this);
}
public void receiveMessage(String message) {
System.out.println("车手 " + name + " 收到: " + message);
}
}
public class Domestique implements Player {
private String name;
private String job = "Domestique";
private Mediator mediator;
public Domestique(String name) {
this.name = name;
}
@Override
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
@Override
public String getName() {
return name;
}
@Override
public String getJob() {
return job;
}
public void teamChangeFormation(int type) {
mediator.changeFormation(type);
}
public void changeFormation(int position) {
System.out.println(job + " 收到通知,移动到车队的第 " + position + " 个位置");
}
public void teamAccelerate() {
mediator.accelerate();
}
public void personalAccelerate() {
System.out.println("车手 " + name + " 收到通知,开始加速");
}
public void teamDecelerate() {
mediator.decelerate();
}
public void personalDecelerate() {
System.out.println("车手 " + name + " 收到通知,开始减速");
}
public void notifyTeamMembers(String message) {
mediator.notifyTeamMembers(message, this);
}
public void receiveMessage(String message) {
System.out.println("车手 " + name + " 收到: " + message);
}
}
public class TimeTrialist implements Player {
private String name;
private String job = "TimeTrialist";
private Mediator mediator;
public TimeTrialist(String name) {
this.name = name;
}
@Override
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
@Override
public String getName() {
return name;
}
@Override
public String getJob() {
return job;
}
public void teamChangeFormation(int type) {
mediator.changeFormation(type);
}
public void changeFormation(int position) {
System.out.println(job + " 收到通知,移动到车队的第 " + position + " 个位置");
}
public void teamAccelerate() {
mediator.accelerate();
}
public void personalAccelerate() {
System.out.println("车手 " + name + " 收到通知,开始加速");
}
public void teamDecelerate() {
mediator.decelerate();
}
public void personalDecelerate() {
System.out.println("车手 " + name + " 收到通知,开始减速");
}
public void notifyTeamMembers(String message) {
mediator.notifyTeamMembers(message, this);
}
public void receiveMessage(String message) {
System.out.println("车手 " + name + " 收到: " + message);
}
}
public class ClimbingSpecialist implements Player {
private String name;
private String job = "ClimbingSpecialist";
private Mediator mediator;
public ClimbingSpecialist(String name) {
this.name = name;
}
@Override
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
@Override
public String getName() {
return name;
}
@Override
public String getJob() {
return job;
}
public void teamChangeFormation(int type) {
mediator.changeFormation(type);
}
public void changeFormation(int position) {
System.out.println(job + " 收到通知,移动到车队的第 " + position + " 个位置");
}
public void teamAccelerate() {
mediator.accelerate();
}
public void personalAccelerate() {
System.out.println("车手 " + name + " 收到通知,开始加速");
}
public void teamDecelerate() {
mediator.decelerate();
}
public void personalDecelerate() {
System.out.println("车手 " + name + " 收到通知,开始减速");
}
public void notifyTeamMembers(String message) {
mediator.notifyTeamMembers(message, this);
}
public void receiveMessage(String message) {
System.out.println("车手 " + name + " 收到: " + message);
}
}
负责沟通的物件子代:PitStop
(Mediator 物件)
public class PitStop implements Mediator {
private Sprinter sprinter;
private Domestique domestique;
private TimeTrialist timeTrialist;
private ClimbingSpecialist climbingSpecialist;
@Override
public void registerPlayer(Player player) {
player.setMediator(this);
switch (player.getJob()) {
case "Sprinter":
sprinter = (Sprinter) player;
break;
case "Domestique":
domestique = (Domestique) player;
break;
case "TimeTrialist":
timeTrialist = (TimeTrialist) player;
break;
case "ClimbingSpecialist":
climbingSpecialist = (ClimbingSpecialist) player;
break;
}
}
@Override
public void changeFormation(int type) {
switch (type) {
case 1:
sprinter.changeFormation(1);
domestique.changeFormation(2);
timeTrialist.changeFormation(3);
climbingSpecialist.changeFormation(4);
break;
case 2:
domestique.changeFormation(1);
timeTrialist.changeFormation(2);
climbingSpecialist.changeFormation(3);
sprinter.changeFormation(4);
break;
case 3:
climbingSpecialist.changeFormation(1);
domestique.changeFormation(2);
sprinter.changeFormation(3);
timeTrialist.changeFormation(4);
break;
case 4:
timeTrialist.changeFormation(1);
climbingSpecialist.changeFormation(2);
sprinter.changeFormation(3);
domestique.changeFormation(4);
break;
}
System.out.println("");
}
@Override
public void accelerate() {
sprinter.personalAccelerate();
domestique.personalAccelerate();
timeTrialist.personalAccelerate();
climbingSpecialist.personalAccelerate();
System.out.println("");
}
@Override
public void decelerate() {
sprinter.personalDecelerate();
domestique.personalDecelerate();
timeTrialist.personalDecelerate();
climbingSpecialist.personalDecelerate();
System.out.println("");
}
@Override
public void notifyTeamMembers(String message, Player requester) {
String finalMessage = "车手: " + requester.getName() + " 通知: " + message;
switch (requester.getJob()) {
case "Sprinter":
domestique.receiveMessage(finalMessage);
timeTrialist.receiveMessage(finalMessage);
climbingSpecialist.receiveMessage(finalMessage);
break;
case "Domestique":
sprinter.receiveMessage(finalMessage);
timeTrialist.receiveMessage(finalMessage);
climbingSpecialist.receiveMessage(finalMessage);
break;
case "TimeTrialist":
sprinter.receiveMessage(finalMessage);
domestique.receiveMessage(finalMessage);
climbingSpecialist.receiveMessage(finalMessage);
break;
case "ClimbingSpecialist":
sprinter.receiveMessage(finalMessage);
domestique.receiveMessage(finalMessage);
timeTrialist.receiveMessage(finalMessage);
break;
}
System.out.println("");
}
}
测试,建立车队成员後,模拟沟通情境:BicycleRacingMediatorSample
public class BicycleRacingMediatorSample {
public static void main(String[] args) {
Mediator mediator = new PitStop();
Sprinter sprinter = new Sprinter("Roger");
Domestique domestique = new Domestique("Victor");
TimeTrialist timeTrialist = new TimeTrialist("David");
ClimbingSpecialist climbingSpecialist = new ClimbingSpecialist("Eric");
/** 注册队友 */
mediator.registerPlayer(sprinter);
mediator.registerPlayer(domestique);
mediator.registerPlayer(timeTrialist);
mediator.registerPlayer(climbingSpecialist);
/** 要求加速 */
sprinter.teamAccelerate();
domestique.teamAccelerate();
/** 要求减速 */
timeTrialist.teamDecelerate();
climbingSpecialist.teamChangeFormation(2);
/** 通知队友 */
domestique.notifyTeamMembers("前方有大弯道,向右");
/** 最後冲刺 */
sprinter.teamChangeFormation(1);
sprinter.notifyTeamMembers("抵达终点线");
}
}
系统内的物件亲代:Player
/** @interface */
class Player {
/** @param {Mediator} mediator */
setMediator(mediator) { return };
getName() { return ""; }
getJob() { return ""; }
}
负责沟通的物件亲代:Mediator
/** @interface */
class Mediator {
/** @param {Player} player */
registerPlayer(player) { return; }
/** @param {number} type */
changeFormation(type) { return; }
accelerate() { return; }
decelerate() { return; }
/**
* @param {string} message
* @param {Player} requester
*/
notifyTeamMembers(message, requester) { return; }
}
系统内的物件子代:Sprinter
、Domestique
、TimeTrialist
、ClimbingSpecialist
class Sprinter extends Player {
constructor(name) {
super();
/** @type {string} */
this.name = name;
this.job = "Sprinter";
/** @type {Mediator} */
this.mediator = null;
}
/**
* @override
* @param {Mediator} mediator
*/
setMediator(mediator) {
this.mediator = mediator;
}
/** @override */
getName() {
return this.name;
}
/** @override */
getJob() {
return this.job;
}
/** @param {number} type */
teamChangeFormation(type) {
this.mediator.changeFormation(type);
}
/** @param {number} position */
changeFormation(position) {
console.log(this.job + " 收到通知,移动到车队的第 " + position + " 个位置");
}
teamAccelerate() {
this.mediator.accelerate();
}
personalAccelerate() {
console.log("车手 " + this.name + " 收到通知,开始加速");
}
teamDecelerate() {
this.mediator.decelerate();
}
personalDecelerate() {
console.log("车手 " + this.name + " 收到通知,开始减速");
}
/** @param {string} message */
notifyTeamMembers(message) {
this.mediator.notifyTeamMembers(message, this);
}
/** @param {string} message */
receiveMessage(message) {
console.log("车手 " + this.name + " 收到: " + message);
}
}
class Domestique extends Player {
constructor(name) {
super();
/** @type {string} */
this.name = name;
this.job = "Domestique";
/** @type {Mediator} */
this.mediator = null;
}
/**
* @override
* @param {Mediator} mediator
*/
setMediator(mediator) {
this.mediator = mediator;
}
/** @override */
getName() {
return this.name;
}
/** @override */
getJob() {
return this.job;
}
/** @param {number} type */
teamChangeFormation(type) {
this.mediator.changeFormation(type);
}
/** @param {number} position */
changeFormation(position) {
console.log(this.job + " 收到通知,移动到车队的第 " + position + " 个位置");
}
teamAccelerate() {
this.mediator.accelerate();
}
personalAccelerate() {
console.log("车手 " + this.name + " 收到通知,开始加速");
}
teamDecelerate() {
this.mediator.decelerate();
}
personalDecelerate() {
console.log("车手 " + this.name + " 收到通知,开始减速");
}
/** @param {string} message */
notifyTeamMembers(message) {
this.mediator.notifyTeamMembers(message, this);
}
/** @param {string} message */
receiveMessage(message) {
console.log("车手 " + this.name + " 收到: " + message);
}
}
class TimeTrialist extends Player {
constructor(name) {
super();
/** @type {string} */
this.name = name;
this.job = "TimeTrialist";
/** @type {Mediator} */
this.mediator = null;
}
/**
* @override
* @param {Mediator} mediator
*/
setMediator(mediator) {
this.mediator = mediator;
}
/** @override */
getName() {
return this.name;
}
/** @override */
getJob() {
return this.job;
}
/** @param {number} type */
teamChangeFormation(type) {
this.mediator.changeFormation(type);
}
/** @param {number} position */
changeFormation(position) {
console.log(this.job + " 收到通知,移动到车队的第 " + position + " 个位置");
}
teamAccelerate() {
this.mediator.accelerate();
}
personalAccelerate() {
console.log("车手 " + this.name + " 收到通知,开始加速");
}
teamDecelerate() {
this.mediator.decelerate();
}
personalDecelerate() {
console.log("车手 " + this.name + " 收到通知,开始减速");
}
/** @param {string} message */
notifyTeamMembers(message) {
this.mediator.notifyTeamMembers(message, this);
}
/** @param {string} message */
receiveMessage(message) {
console.log("车手 " + this.name + " 收到: " + message);
}
}
class ClimbingSpecialist extends Player {
constructor(name) {
super();
/** @type {string} */
this.name = name;
this.job = "ClimbingSpecialist";
/** @type {Mediator} */
this.mediator = null;
}
/**
* @override
* @param {Mediator} mediator
*/
setMediator(mediator) {
this.mediator = mediator;
}
/** @override */
getName() {
return this.name;
}
/** @override */
getJob() {
return this.job;
}
/** @param {number} type */
teamChangeFormation(type) {
this.mediator.changeFormation(type);
}
/** @param {number} position */
changeFormation(position) {
console.log(this.job + " 收到通知,移动到车队的第 " + position + " 个位置");
}
teamAccelerate() {
this.mediator.accelerate();
}
personalAccelerate() {
console.log("车手 " + this.name + " 收到通知,开始加速");
}
teamDecelerate() {
this.mediator.decelerate();
}
personalDecelerate() {
console.log("车手 " + this.name + " 收到通知,开始减速");
}
/** @param {string} message */
notifyTeamMembers(message) {
this.mediator.notifyTeamMembers(message, this);
}
/** @param {string} message */
receiveMessage(message) {
console.log("车手 " + this.name + " 收到: " + message);
}
}
负责沟通的物件子代:PitStop
(Mediator 物件)
class PitStop extends Mediator {
constructor() {
super();
/** @type {Sprinter} */
this.sprinter = null;
/** @type {Domestique} */
this.domestique = null;
/** @type {TimeTrialist} */
this.timeTrialist = null;
/** @type {ClimbingSpecialist} */
this.climbingSpecialist = null;
}
/**
* @override
* @param {Player} player
*/
registerPlayer(player) {
player.setMediator(this);
switch (player.getJob()) {
case "Sprinter":
this.sprinter = player;
break;
case "Domestique":
this.domestique = player;
break;
case "TimeTrialist":
this.timeTrialist = player;
break;
case "ClimbingSpecialist":
this.climbingSpecialist = player;
break;
}
}
/**
* @override
* @param {number} type
*/
changeFormation(type) {
switch (type) {
case 1:
this.sprinter.changeFormation(1);
this.domestique.changeFormation(2);
this.timeTrialist.changeFormation(3);
this.climbingSpecialist.changeFormation(4);
break;
case 2:
this.domestique.changeFormation(1);
this.timeTrialist.changeFormation(2);
this.climbingSpecialist.changeFormation(3);
this.sprinter.changeFormation(4);
break;
case 3:
this.climbingSpecialist.changeFormation(1);
this.domestique.changeFormation(2);
this.sprinter.changeFormation(3);
this.timeTrialist.changeFormation(4);
break;
case 4:
this.timeTrialist.changeFormation(1);
this.climbingSpecialist.changeFormation(2);
this.sprinter.changeFormation(3);
this.domestique.changeFormation(4);
break;
}
console.log("");
}
/** @override */
accelerate() {
this.sprinter.personalAccelerate();
this.domestique.personalAccelerate();
this.timeTrialist.personalAccelerate();
this.climbingSpecialist.personalAccelerate();
console.log("");
}
/** @override */
decelerate() {
this.sprinter.personalDecelerate();
this.domestique.personalDecelerate();
this.timeTrialist.personalDecelerate();
this.climbingSpecialist.personalDecelerate();
console.log("");
}
/**
* @override
* @param {string} message
* @param {Player} requester
*/
notifyTeamMembers(message, requester) {
const finalMessage = "车手: " + requester.getName() + " 通知: " + message;
switch (requester.getJob()) {
case "Sprinter":
this.domestique.receiveMessage(finalMessage);
this.timeTrialist.receiveMessage(finalMessage);
this.climbingSpecialist.receiveMessage(finalMessage);
break;
case "Domestique":
this.sprinter.receiveMessage(finalMessage);
this.timeTrialist.receiveMessage(finalMessage);
this.climbingSpecialist.receiveMessage(finalMessage);
break;
case "TimeTrialist":
this.sprinter.receiveMessage(finalMessage);
this.domestique.receiveMessage(finalMessage);
this.climbingSpecialist.receiveMessage(finalMessage);
break;
case "ClimbingSpecialist":
this.sprinter.receiveMessage(finalMessage);
this.domestique.receiveMessage(finalMessage);
this.timeTrialist.receiveMessage(finalMessage);
break;
}
console.log("");
}
}
测试,建立车队成员後,模拟沟通情境:BicycleRacingMediatorSample
const bicycleRacingMediatorSample = () => {
const mediator = new PitStop();
const sprinter = new Sprinter("Roger");
const domestique = new Domestique("Victor");
const timeTrialist = new TimeTrialist("David");
const climbingSpecialist = new ClimbingSpecialist("Eric");
/** 注册队友 */
mediator.registerPlayer(sprinter);
mediator.registerPlayer(domestique);
mediator.registerPlayer(timeTrialist);
mediator.registerPlayer(climbingSpecialist);
/** 要求加速 */
sprinter.teamAccelerate();
domestique.teamAccelerate();
/** 要求减速 */
timeTrialist.teamDecelerate();
climbingSpecialist.teamChangeFormation(2);
/** 通知队友 */
domestique.notifyTeamMembers("前方有大弯道,向右");
/** 最後冲刺 */
sprinter.teamChangeFormation(1);
sprinter.notifyTeamMembers("抵达终点线");
};
bicycleRacingMediatorSample();
起初,我以为 Mediator 模式跟 React 或是 Redux 的中心式管理 Data 相似,实则完全不同。因为 Mediator 模式的中间人不负责储存变数,只负责「传递」,物件之间互相影响後的状态如何,中间人都不会知道。
该模式玩味之处还有一点,让所有物件都依赖中间人,造成该中间人成为超级重要的 God Class,变相增加物件的依赖性,这会在往後成为开发上的障碍。
因此,此模式适合在确定物件之间有着高度依赖性,并且往後的变动不多、不大,那就可以安心使用了。
明天将介绍 Behavioural patterns 的第六个模式:Memento 模式。
<<: [第二十二只羊] 迷雾森林舞会XVI 策略模式 Strategy Pattern
>>: Day22 Redis架构实战-高可用性使用Sentinel机制
经过这两天的介绍,相信大家对於 Cypress 应该已经有了一定程度的理解,有没有人已经开始用它来...
众所皆知:「不会写程序的人都认为程序语言是写给电脑看的, 会写程序的人都知道程序语言是写给人看的。...
废话不多说直接开始 在开启一个专案放以下两个cs DBconnection.cs: using My...
接下来我要来介绍到有关於当我们将专案打开来时,那最多人使用的配置是”Project”及”androi...
学习任何东西,都要把基础学的扎实,基础稳了,遇到问题就能迎刃而解。 而学习程序语言的基础就是数学逻...