18-调停者模式Quarkus实现

摘要:本文用一个实例场景描述Gof 23设计模式中的调停者模式,并用Quarkus程序代码给予实现,同时也给出实现代码的UML模型。
关键字:Gof 23 设计模式 调停者模式 Quarkus

1 基础知识
1.1 标准定义
调停者(Mediator)模式标准定义:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
1.2 分析和说明
调停者(Mediator)模式也叫中介者模式,属于对象行为型模式。调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用,将类与类之间的复杂的相互关系封装到一个调停者类中。调停者模式将对象的行为和协作抽象化,把对象在小尺度的行为上与其他对象的相互作用分开处理。
调停者(Mediator)模式结构如图1所示,其角色包括抽象调停者(Mediator)角色、具体调停者(Concrete Mediator)角色、抽象同事类(Colleague)角色和具体同事类(Concrete Colleague)角色等。 在这里插入图片描述
图1调停者模式结构
 抽象调停者(Mediator)角色:定义出同事对象到调停者对象的接口,其中主要的方法是一个(或者多个)事件方法。在有些情况下,这个抽象对象可以省略。一般而言,这个角色由一个抽象类或者接口实现。
 具体调停者(Concrete Mediator)角色:从抽象调停者继承而来,实现了抽象超类所声明的事件方法。具体调停者知晓所有的具体同事类,它从具体同事对象接收消息、向具体同事对象发出命令。一般而言,这个角色由一个具体类实现。
 抽象同事类(Colleague)角色:定义出调停者到同事对象的接口。同事对象只知道调停者而不知道其余的同事对象。一般而言,这个角色由一个抽象类或者对象实现。
 具体同事类(Concrete Colleague)角色:所有的具体同事类均从抽象同事类继承而来。每一个具体同事类都很清楚它自己在小范围的行为,而不知道它在大范围内的目的。在示意性的类图中,具体同事类是Colleague1和Colleague2。一般而言,这个角色由一个具体类实现。

2 应用场景举例
比如公司有很多项目,项目包括项目工作和项目人员。但有的时候,一些项目人员过多,一些项目人员过少。一些项目工作量大,一些项目工作量小,这就需要技术总监充当协调者,把一些项目的人员调到另一些项目上,或者把一些项目的工作安排到另外的项目中。规则中不允许项目经理之间自我调整,而必须要技术总监来调停,这就是调停者模式。用例图见图2。 在这里插入图片描述
图2 调停者模式用例图
在这里可以把Mediator抽象类理解为抽象调停者(Mediator)角色。TechnicalDirector类理解为具体调停者(Concrete Mediator)角色。AbstractProject抽象类理解为抽象同事类(Colleague)角色。ProjectA类和ProjectB类是具体同事类(Concrete Colleague)角色。其实现类图如图3所示。TechnicalDirector类一方面继承Mediator抽象类,另一方面被AbstractProject抽象类关联。ProjectA类和ProjectB类继承AbstractProject抽象类,同时被TechnicalDirector类关联。 在这里插入图片描述
图3 调停者模式类图
调停者模式实现顺序图见图4,实现顺序描述:① 基于TechnicalDirector类创建一个leader对象;②基于ProjectA类创建一个projectA对象;③基于ProjectB类创建一个projectB对象;④ 调用leader对象setProjectA方法,把projectA对象赋值给leader对象。⑤ 调用leader对象setProjectB方法,把projectB对象赋值给leader对象。⑥ 调用leader对象changMember方法,实现projectA对象和projectB对象的人员调动;⑦ 调用leader对象changTask方法,实现projectA对象和projectB对象的任务调动;⑧ 调用projectA对象的showProjectContent方法,显示projectA内部人员和任务情况;⑨ 调用projectB对象的showProjectContent方法,显示projectB内部人员和任务情况; 在这里插入图片描述
图4 调停者模式实现顺序图
leader对象就是一个调停者,projectA对象和projectB对象内部的人员和任务交换和协调,都通过leader对象的方法来实现。

3.Quarkus的实现程序代码
Quarkus程序实现主要包括AbstractProject抽象类文件,Mediator抽象类文件,TechnicalDirector类文件,ProjectA类文件,ProjectB类文件,Member类文件和Task类文件等7个文件。其关系如图3所示。下面分别列出这7个文件的程序代码,最后列出测试代码并显示输出结果。
AbstractProject抽象类程序代码清单01所示。
程序代码清单01

public abstract class {	
	protected String projectName ;
	protected TechnicalDirector leader;
	protected Map<String,Member> memberMap = new HashMap<String,Member>();
	protected Map<String,Task> taskMap = new HashMap<String,Task>();
	
	protected void initizeTask(Map<String,Task> map){taskMap = map;}
	
	protected void initizeMember(Map<String,Member> map){memberMap = map;}
	
	public void addMember(Member member){memberMap.put(member.getMemberName(), member);}
	public void removeMember(Member member){memberMap.remove(member.getMemberName());	}
	
	public void addTask(Task task){taskMap.put(task.getTaskName(), task);}
	
	public void reduceTask(Task task){taskMap.remove(task.getTaskName());	}
	
	public String getProjectName() {return projectName;}
	public void setProjectName(String projectName) {this.projectName = projectName;	}
	public TechnicalDirector getLeader() {return leader;	}
	public void setLeader(TechnicalDirector leader) {	this.leader = leader;}
	
	public void showProjectContent(){
		System.out.println("显示"+getProjectName()+"项目成员和任务情况:");
		System.out.print("项目成员:");
		String memberName;
		Iterator it = memberMap.keySet().iterator();
		while (it.hasNext()){
			memberName = (String)it.next();			
			System.out.print(memberName+";");
		}
		System.out.println();
		
		String taskName;
		System.out.print("项目任务:");
		it = taskMap.keySet().iterator();
		while (it.hasNext()){
			taskName = (String)it.next();			
			System.out.print(taskName+";");
		}
		System.out.println();		
	}
}

Mediator抽象类程序代码清单02所示。
程序代码清单02

public abstract class Mediator {	
	public void changMember(AbstractProject project1,AbstractProject project2,Member member){
		project1.removeMember(member);
		project2.addMember(member);
	}
	
	public void changTask(AbstractProject project1,AbstractProject project2,Task task){
		project1.reduceTask(task);
		project2.addTask(task);
	}
	
	public void doCoordination(){}
}

TechnicalDirector继承Mediator抽象类,其程序代码清单03所示。
程序代码清单03

@ApplicationScoped
public class TechnicalDirector extends Mediator {

	private ProjectA projectA;
	private ProjectB projectB;
	private String directorName;

	public TechnicalDirector(){}
	
	public String getDirectorName() {
		return directorName;
	}

	public void setDirectorName(String directorName) {
		this.directorName = directorName;
	}

	public ProjectA getProjectA() {
		return projectA;
	}

	public void setProjectA(ProjectA projectA) {
		this.projectA = projectA;
	}

	public ProjectB getProjectB() {
		return projectB;
	}

	public void setProjectB(ProjectB projectB) {
		this.projectB = projectB;
	}

	public void doCoordination() {
		

	}

}

ProjectA类和ProjectB类继承AbstractProject抽象类,其程序代码清单04所示。
程序代码清单04

@ApplicationScoped
public class ProjectA extends AbstractProject{
	
	public ProjectA(){
		projectName = "ProjectA";
	}
	
	public ProjectA(Map<String,Member> members,Map<String,Task> tasks){
		initizeMember(members);
		initizeTask(tasks);
		projectName = "ProjectA";
	}
	
	public ProjectA setMembers(Map<String,Member> members){
		initizeMember(members);
		return this;
	}
	
	public ProjectA setTasks(Map<String,Task> tasks){
		initizeTask(tasks);
		return this;
	}
}

@ApplicationScoped
public class ProjectB extends AbstractProject {

	public ProjectB(){
		projectName = "ProjectB";
	}
	
	public ProjectB(Map<String, Member> members, Map<String, Task> tasks) {
		initizeMember(members);
		initizeTask(tasks);
		projectName = "ProjectB";
	}
	
	public ProjectB setMembers(Map<String,Member> members){
		initizeMember(members);
		return this;
	}
	
	public ProjectB setTasks(Map<String,Task> tasks){
		initizeTask(tasks);
		return this;
	}	
}

Member类和Task类程序代码清单05所示。
程序代码清单05

@Dependent
public class Member {
	private String memberName ;
	
	public Member(){}
	
	public Member(String name){
		setMemberName(name);
	}

	public String getMemberName() {
		return memberName;
	}

	public void setMemberName(String memberName) {
		this.memberName = memberName;
	}
}

@Dependent
public class Task {
	private String taskName ;
	
	public Task(){}
	
	public Task(String name){
		setTaskName(name);
	}

	public String getTaskName() {
		return taskName;
	}

	public void setTaskName(String taskName) {
		this.taskName = taskName;
	}
}

调停者模式测试程序的代码清单06如下:
程序代码清单06

public class MediatorClient implements QuarkusApplication {

	@ConfigProperty(name = "gof23.behavioralpattern.mediator.title", defaultValue = "gof23")
	String title;
	
	@Inject	Member Programmer1,Programmer2,Designer1,Designer2;	
	@Inject	Task ProgramTask1,ProgramTask2,DesignTask1,DesignTask2;	
	@Inject	ProjectA projectA;	
	@Inject	ProjectB projectB;	
	@Inject	TechnicalDirector leader ;
	
	@Override
	public int run(String... args)  {
		
		System.out.println("————————" + title + "演示输出—————————");	

		// 初始化项目人员和任务信息		
		Programmer1.setMemberName("程序员1");
		Programmer2.setMemberName("程序员2");
		Designer1.setMemberName("设计师1");
		Designer2.setMemberName("设计师2");
				
		ProgramTask1.setTaskName("编程工作1");
		ProgramTask2.setTaskName("编程工作2");
		DesignTask1.setTaskName("设计工作1");
		DesignTask2.setTaskName("设计工作2");

		Map<String, Member> ProgrammerMap = new HashMap<String, Member>();
		ProgrammerMap.put(Programmer1.getMemberName(), Programmer1);
		ProgrammerMap.put(Programmer2.getMemberName(), Programmer2);

		Map<String, Member> DesignerMap = new HashMap<String, Member>();
		DesignerMap.put(Designer1.getMemberName(), Designer1);
		DesignerMap.put(Designer2.getMemberName(), Designer2);

		Map<String, Task> ProgramTaskMap = new HashMap<String, Task>();
		ProgramTaskMap.put(ProgramTask1.getTaskName(), ProgramTask1);
		ProgramTaskMap.put(ProgramTask2.getTaskName(), ProgramTask2);

		Map<String, Task> DesignTaskMap = new HashMap<String, Task>();
		DesignTaskMap.put(DesignTask1.getTaskName(), DesignTask1);
		DesignTaskMap.put(DesignTask2.getTaskName(), DesignTask2);
				
		projectA.setMembers(ProgrammerMap).setTasks(ProgramTaskMap);
		projectB.setMembers(DesignerMap).setTasks(DesignTaskMap);

		// 进行项目人员和工作的协调
		System.out.println("—————————协调前的情况—————————");
		projectA.showProjectContent();
		projectB.showProjectContent();

		leader.setProjectA(projectA);
		leader.setProjectB(projectB);

		// 协调两个项目的人员
		leader.changMember(projectA, projectB, Programmer1);
		leader.changMember(projectB, projectA, Designer1);

		// 协调两个项目的任务
		leader.changTask(projectA, projectB, ProgramTask1);
		leader.changTask(projectB, projectA, DesignTask1);

		System.out.println("—————————协调后的情况—————————");
		projectA.showProjectContent();
		projectB.showProjectContent();
		return 0;
	}
	
	public static void main(String... args) {
		Quarkus.run(MediatorClient.class, args);
	}

}

调停者模式测试类输出结果如下所示:

—————————协调前的情况—————————
显示ProjectA项目成员和任务情况:
项目成员:程序员2;程序员1;
项目任务:编程工作1;编程工作2;
显示ProjectB项目成员和任务情况:
项目成员:设计师1;设计师2;
项目任务:设计工作2;设计工作1;
—————————协调后的情况—————————
显示ProjectA项目成员和任务情况:
项目成员:设计师1;程序员2;
项目任务:设计工作1;编程工作2;
显示ProjectB项目成员和任务情况:
项目成员:程序员1;设计师2;
项目任务:设计工作2;编程工作1;

4. 相关Quarkus程序源码下载
可以直接从github上获取代码,读者可以从github上clone预先准备好的示例代码。

git clone https://github.com/rengang66/quarkus-sample-gof23.git

这是一个Maven项目,然后Maven导入工程。该程序位于“src\main\java\com\iiit\quarkus\sample\gof23\behavioralpattern\mediator”目录中。
同时也可以从gitee上clone预先准备好的示例代码,命令如下:

git clone https://gitee.com/rengang66/quarkus-sample-gof23.git

参考文献

[1] E.Gamma, R.Helm, R.Johnson, and Vlissides. Design Patterns Elements of Reusable Object Oriented Software. Addison-Wesley, 1995
[2] E.Gamma, R.Helm, R.Johnson, and Vlissides.著,李英军等译,设计模式:可复用面向对象软件的基础,北京:机械工业出版社.2000.9.
[3] 阎宏,Java与模式,北京:电子工业出版社. 2002.10
[4] 王俊峰 戚晓滨. 设计模式和UML. 计算机应用研究,1999.16(5), 27-29,39.
[5] 陈琴 朱正强. UML在设计模式描述中的应用. 计算机工程与设计,2003.24(4), 81-84.
[6] 周传宏 吴思达. 可扩展的基于设计模式的PLM定制架构. 制造业自动化,2007.29(4), 27-29,76.
[7] 王松涛 汪莉 林勇. Mediator设计模式的研究与改进. 科学技术与工程,2005.5(7), 427-430.
[8] 罗达 张远舟 周晓聪. 中介者模式的面向方面实现. 计算机应用与软件,2008.25(11), 46-47,111.
[9] 何成万[1,2,3] 何克清[1] 涂文婕[3]. 一种基于Mediator模式的角色实现方法. 计算机工程,2006.32(18), 48-49,94.
[10] 计春雷. 软件设计模式及其应用研究. 上海电机学院学报,2006.9(5), 46-49,70.
[11] 韩鹏 李成忠. 设计模式及其在J2ME中的应用. 成都信息工程学院学报,2004.19(3), 332-335.
[12] 曾蔚 陈维斌. 设计模式在新生报到系统中的应用与实现. 计算机技术与发展,2007.17(7), 178-182.
[13] Quarkus官网. https://quarkus.io/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值