java手动切换成独立显卡_JAVA设计模式之调停者模式

在阎宏博士的《JAVA与模式》一书中开头是这样描述调停者(Mediator)模式的:

调停者模式是对象的行为模式。调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显引用。从而使它们可以较松散地耦合。当这些对象中的某些对象之间的相互作用发生改变时,不会立即影响到其他的一些对象之间的相互作用。从而保证这些相互作用可以彼此独立地变化。

为什么需要调停者

如下图所示,这个示意图中有大量的对象,这些对象既会影响别的对象,又会被别的对象所影响,因此常常叫做同事(Colleague)对象。这些同事对象通过彼此的相互作用形成系统的行为。从图中可以看出,几乎每一个对象都需要与其他的对象发生相互作用,而这种相互作用表现为一个对象与另一个对象的直接耦合。这就是过度耦合的系统。

bufGW7duiV7ulIF1wY7RVsb+QA1DEEQBMkqqGEIgiBIVkENQxAEQbIKahiCIAiSVf4fuI2WhGEFLvoAAAAASUVORK5CYII=

通过引入调停者对象(Mediator),可以将系统的网状结构变成以中介者为中心的星形结构,如下图所示。在这个星形结构中,同事对象不再通过直接的联系与另一个对象发生相互作用;相反的,它通过调停者对象与另一个对象发生相互作用。调停者对象的存在保证了对象结构上的稳定,也就是说,系统的结构不会因为新对象的引入造成大量的修改工作。

B92VXAeVUNd2AAAAAElFTkSuQmCC  一个好的面向对象的设计可以使对象之间增加协作性(Collaboration),减少耦合度(Couping)。一个深思熟虑的设计会把一个系统分解为一群相互协作的同事对象,然后给每一个同事对象以独特的责任,恰当的配置它们之间的协作关系,使它们可以在一起工作。

如果没有主板

大家都知道,电脑里面各个配件之间的交互,主要是通过主板来完成的。如果电脑里面没有了主板,那么各个配件之间就必须自行相互交互,以互相传送数据。而且由于各个配件的接口不同,相互之间交互时,还必须把数据接口进行转换才能匹配上。

3XEqgAAAAJJREFUWLolLTB0AAAAAElFTkSuQmCC

所幸是有了主板,各个配件的交互完全通过主板来完成,每个配件都只需要和主板交互,而主板知道如何跟所有的配件打交道,这样就简单多了。

wfrZbkpyBoeVgAAAABJRU5ErkJggg==

调停者模式的结构

调停者模式的示意性类图如下所示:

wACiREvU8ZO9wAAAABJRU5ErkJggg==

调停者模式包括以下角色:

●  抽象调停者(Mediator)角色:定义出同事对象到调停者对象的接口,其中主要方法是一个(或多个)事件方法。

●  具体调停者(ConcreteMediator)角色:实现了抽象调停者所声明的事件方法。具体调停者知晓所有的具体同事类,并负责具体的协调各同事对象的交互关系。

●  抽象同事类(Colleague)角色:定义出调停者到同事对象的接口。同事对象只知道调停者而不知道其余的同事对象。

●  具体同事类(ConcreteColleague)角色:所有的具体同事类均从抽象同事类继承而来。实现自己的业务,在需要与其他同事通信的时候,就与持有的调停者通信,调停者会负责与其他的同事交互。

源代码

抽象调停者类

48304ba5e6f9fe08f3fa1abda7d326ab.png

public interfaceMediator {/*** 同事对象在自身改变的时候来通知调停者方法

* 让调停者去负责相应的与其他同事对象的交互*/

public voidchanged(Colleague c);

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

具体调停者类

48304ba5e6f9fe08f3fa1abda7d326ab.png

public class ConcreteMediator implementsMediator {//持有并维护同事A

privateConcreteColleagueA colleagueA;//持有并维护同事B

privateConcreteColleagueB colleagueB;public voidsetColleagueA(ConcreteColleagueA colleagueA) {this.colleagueA =colleagueA;

}public voidsetColleagueB(ConcreteColleagueB colleagueB) {this.colleagueB =colleagueB;

}

@Overridepublic voidchanged(Colleague c) {/*** 某一个同事类发生了变化,通常需要与其他同事交互

* 具体协调相应的同事对象来实现协作行为*/}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

抽象同事类

48304ba5e6f9fe08f3fa1abda7d326ab.png

public abstract classColleague {//持有一个调停者对象

privateMediator mediator;/*** 构造函数*/

publicColleague(Mediator mediator){this.mediator =mediator;

}/*** 获取当前同事类对应的调停者对象*/

publicMediator getMediator() {returnmediator;

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

具体同事类

48304ba5e6f9fe08f3fa1abda7d326ab.png

public class ConcreteColleagueA extendsColleague {publicConcreteColleagueA(Mediator mediator) {super(mediator);

}/*** 示意方法,执行某些操作*/

public voidoperation(){//在需要跟其他同事通信的时候,通知调停者对象

getMediator().changed(this);

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

48304ba5e6f9fe08f3fa1abda7d326ab.png

public class ConcreteColleagueB extendsColleague {publicConcreteColleagueB(Mediator mediator) {super(mediator);

}/*** 示意方法,执行某些操作*/

public voidoperation(){//在需要跟其他同事通信的时候,通知调停者对象

getMediator().changed(this);

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

使用电脑来看电影

在日常生活中,我们经常使用电脑来看电影,把这个过程描述出来,简化后假定会有如下的交互过程:

(1)首先是光驱要读取光盘上的数据,然后告诉主板,它的状态改变了。

(2)主板去得到光驱的数据,把这些数据交给CPU进行分析处理。

(3)CPU处理完后,把数据分成了视频数据和音频数据,通知主板,它处理完了。

(4)主板去得到CPU处理过后的数据,分别把数据交给显卡和声卡,去显示出视频和发出声音。

要使用调停者模式来实现示例,那就要区分出同事对象和调停者对象。很明显,主板是调停者,而光驱、声卡、CPU、显卡等配件,都是作为同事对象。

SqkkIQQQgghfKSQhBBCCCF8pJCEEEIIIXykkIQQQgghfKSQhBBCCCF8pJCEEEIIIXykkIQQQgghfP4fCfyi5lMYBBcAAAAASUVORK5CYII=

源代码

抽象同事类

48304ba5e6f9fe08f3fa1abda7d326ab.png

public abstract classColleague {//持有一个调停者对象

privateMediator mediator;/*** 构造函数*/

publicColleague(Mediator mediator){this.mediator =mediator;

}/*** 获取当前同事类对应的调停者对象*/

publicMediator getMediator() {returnmediator;

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

同事类——光驱

48304ba5e6f9fe08f3fa1abda7d326ab.png

public class CDDriver extendsColleague{//光驱读取出来的数据

private String data = "";/*** 构造函数*/

publicCDDriver(Mediator mediator) {super(mediator);

}/*** 获取光盘读取出来的数据*/

publicString getData() {returndata;

}/*** 读取光盘*/

public voidreadCD(){//逗号前是视频显示的数据,逗号后是声音

this.data = "One Piece,海贼王我当定了";//通知主板,自己的状态发生了改变

getMediator().changed(this);

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

同事类——CPU

48304ba5e6f9fe08f3fa1abda7d326ab.png

public class CPU extendsColleague {//分解出来的视频数据

private String videoData = "";//分解出来的声音数据

private String soundData = "";/*** 构造函数*/

publicCPU(Mediator mediator) {super(mediator);

}/*** 获取分解出来的视频数据*/

publicString getVideoData() {returnvideoData;

}/*** 获取分解出来的声音数据*/

publicString getSoundData() {returnsoundData;

}/*** 处理数据,把数据分成音频和视频的数据*/

public voidexecuteData(String data){//把数据分解开,前面是视频数据,后面是音频数据

String[] array = data.split(",");this.videoData = array[0];this.soundData = array[1];//通知主板,CPU完成工作

getMediator().changed(this);

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

同事类——显卡

48304ba5e6f9fe08f3fa1abda7d326ab.png

public class VideoCard extendsColleague {/*** 构造函数*/

publicVideoCard(Mediator mediator) {super(mediator);

}/*** 显示视频数据*/

public voidshowData(String data){

System.out.println("您正在观看的是:" +data);

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

同事类——声卡

48304ba5e6f9fe08f3fa1abda7d326ab.png

public class SoundCard extendsColleague {/*** 构造函数*/

publicSoundCard(Mediator mediator) {super(mediator);

}/*** 按照声频数据发出声音*/

public voidsoundData(String data){

System.out.println("画外音:" +data);

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

抽象调停者类

48304ba5e6f9fe08f3fa1abda7d326ab.png

public interfaceMediator {/*** 同事对象在自身改变的时候来通知调停者方法

* 让调停者去负责相应的与其他同事对象的交互*/

public voidchanged(Colleague c);

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

具体调停者类

48304ba5e6f9fe08f3fa1abda7d326ab.png

public class MainBoard implementsMediator {//需要知道要交互的同事类——光驱类

private CDDriver cdDriver = null;//需要知道要交互的同事类——CPU类

private CPU cpu = null;//需要知道要交互的同事类——显卡类

private VideoCard videoCard = null;//需要知道要交互的同事类——声卡类

private SoundCard soundCard = null;public voidsetCdDriver(CDDriver cdDriver) {this.cdDriver =cdDriver;

}public voidsetCpu(CPU cpu) {this.cpu =cpu;

}public voidsetVideoCard(VideoCard videoCard) {this.videoCard =videoCard;

}public voidsetSoundCard(SoundCard soundCard) {this.soundCard =soundCard;

}

@Overridepublic voidchanged(Colleague c) {if(c instanceofCDDriver){//表示光驱读取数据了

this.opeCDDriverReadData((CDDriver)c);

}else if(c instanceofCPU){this.opeCPU((CPU)c);

}

}/*** 处理光驱读取数据以后与其他对象的交互*/

private voidopeCDDriverReadData(CDDriver cd){//先获取光驱读取的数据

String data =cd.getData();//把这些数据传递给CPU进行处理

cpu.executeData(data);

}/*** 处理CPU处理完数据后与其他对象的交互*/

private voidopeCPU(CPU cpu){//先获取CPU处理后的数据

String videoData =cpu.getVideoData();

String soundData=cpu.getSoundData();//把这些数据传递给显卡和声卡展示出来

videoCard.showData(videoData);

soundCard.soundData(soundData);

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

客户端类

48304ba5e6f9fe08f3fa1abda7d326ab.png

public classClient {public static voidmain(String[] args) {//创建调停者——主板

MainBoard mediator = newMainBoard();//创建同事类

CDDriver cd = newCDDriver(mediator);

CPU cpu= newCPU(mediator);

VideoCard vc= newVideoCard(mediator);

SoundCard sc= newSoundCard(mediator);//让调停者知道所有同事

mediator.setCdDriver(cd);

mediator.setCpu(cpu);

mediator.setVideoCard(vc);

mediator.setSoundCard(sc);//开始看电影,把光盘放入光驱,光驱开始读盘

cd.readCD();

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

运行结果如下:

weY2q9954zdoAAAAABJRU5ErkJggg==

调停者模式的优点

●  松散耦合

调停者模式通过把多个同事对象之间的交互封装到调停者对象里面,从而使得同事对象之间松散耦合,基本上可以做到互补依赖。这样一来,同事对象就可以独立地变化和复用,而不再像以前那样“牵一处而动全身”了。

● 集中控制交互

多个同事对象的交互,被封装在调停者对象里面集中管理,使得这些交互行为发生变化的时候,只需要修改调停者对象就可以了,当然如果是已经做好的系统,那么就扩展调停者对象,而各个同事类不需要做修改。

●  多对多变成一对多

没有使用调停者模式的时候,同事对象之间的关系通常是多对多的,引入调停者对象以后,调停者对象和同事对象的关系通常变成双向的一对多,这会让对象的关系更容易理解和实现。

调停者模式的缺点

调停者模式的一个潜在缺点是,过度集中化。如果同事对象的交互非常多,而且比较复杂,当这些复杂性全部集中到调停者的时候,会导致调停者对象变得十分复杂,而且难于管理和维护。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/453500.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2018.2.8 php实现qq登陆接口

PHP实现QQ登录的原理和实现过程 2018-02-08 学习与分享 PHP自学中心 第三方登录,就是使用大家比较熟悉的比如QQ、微信、微博等第三方软件登录自己的网站,这可以免去注册账号、快速留住用户的目的,免去了相对复杂的注册流程。下边就给大家讲一…

关于积累的一点看法

这是vip那边发表的一篇帖子,今天整理,发现可能有一点代表性,就再发在这里,供各位同学参考。 坛子里有人讨论小公司要不要积累框架的问题,有感而发,写了点自己的看法,一家之言,欢迎拍…

去除vue项目中的#及其ie9兼容性

一、如何去除vue项目中访问地址的# vue2中在路由配置中添加mode(vue-cli创建的项目在src/router/index.js) 1 export default new Router({2 mode: history,3 routes: [4 {5 path: /,6 name: menu,7 component: menu,8 …

sendBroadcast与sendStickyBroadcast的区别

前提条件:此处我主要讨论两种广播在代码中动态注册时的一些细节问题。 正常情况下,广播通常都是执行一次注册代码,就会触发各接收器接收一次,无论是在onCreate里注册还是onResume里注册:若在onCreate里注册&#xff0…

java 线程池 初始大小_为什么tomcat的默认线程池大小如此之大? - java

我注意到默认的tomcat 7线程池大小似乎是200。但是普通的CPU似乎有16个内核。因此只能并行执行16个线程为什么tomcat使用那么多线程。参考方案多年以来,许多单核计算机问世,并且能够以“伪并行”模式运行功能,也就是说,您可能有16…

Hadoop2.6.0完全分布式安装

1、修改主机名称 对master/slave1/slave2同时配置为Master/Slave1/Slave2 masterMaster:~$ sudo gedit /etc/hostname 上述3个虚机结点均需要进行以上步骤 2、填写主机IP 对master/slave1/slave2同时配置 masterMaster:~$ sudo gedit /etc/hosts 192.168.48.128 master192.168.…

DEX加密效果分析

dex加密目的:保护安卓应用的Java源代码,避免被恶意分析,技术被窃取准备工具:1、apktool :反编译apk,提取smali代码2、dex2jar :将dex转化为jar文件3、jd-gui :查看jar文件&#xff0…

一些比特率值

比特率 比特率是指将数字声音由模拟格式转化成数字格式的采样率,采样率越高,还原后的音质就越好。 比特率值与现实音频对照: 16KBPS电话音质 24KBPS增加电话音质、短波广播、长波广播、欧洲制式中波广播40KBPS美国制式中波广播56KBPS话…

java asynccontext,超时后的JavaEE 6 AsyncContext行为

What is the exact behavior of AsyncContext after it times out? Does it still run and does it return response using getResponse()?解决方案Java Servlet 3.0 Maintenance Release on page 34 reads:A call to this method - ServletRequest.startAsync(ServletReques…

BZOJ1857:[SCOI2010]传送带——题解

http://www.lydsy.com/JudgeOnline/problem.php?id1857 Description 在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段AB和线段CD。lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R。…

mnt/sdcard和storage/sdcard的区别

/mnt 目录,熟悉linux的人都清楚,linux默认挂载外部设备都会挂到这个目录下面去,如将sd卡挂载上去后,会生成一个/mnt/sdcard 目录。 storage/sdcard 目录,这是一个软链接(相当于windows的文件夹的快捷方式&a…

kd树的原理

kd树就是一种对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构,可以运用在k近邻法中,实现快速k近邻搜索。构造kd树相当于不断地用垂直于坐标轴的超平面将k维空间切分。    假设数据集\(T\)的大小是\(m*n\),即\(T{x_1,x_2,...x_m}\),其中…

应聘华为的朋友小心了,应聘华为的悲惨遭遇!

以下内容全部真实,为本人亲身经历。可随时进行当面对质。 本人女朋友,原本是西安一家企业里面的行政助理,工作比较稳定,收入不高,但也基本够她用了。 一天,我的一个同学(华为员工)说…

力软 java主从表保存_JAVA常用知识总结(十二)——数据库(二)

MySQL主从热备份工作原理简单的说:就是主服务器上执行过的sql语句会保存在binLog里面,别的从服务器把他同步过来,然后重复执行一遍,那么它们就能一直同步啦。整体上来说,复制有3个步骤:作为主服务器的Maste…

HttpClient和DefaultHttpClient

HttpClient 是接口,DefaultHttpClient是实现这个接口的子类 public interface HttpClient {/*** Obtains the parameters for this client.* These parameters will become defaults for all requests being* executed with this client, and for the parameters of…

Go语言版黑白棋

1、游戏说明2、无边框窗口实现3、背景图、最小化、关闭窗口4、界面其它设计5、黑白子提示闪烁效果6、落子7、初始化棋子、改变角色8、倒计时9、吃子10、棋子个数统计、胜负判断11、机器落子 转载于:https://www.cnblogs.com/tennysonsky/p/8442827.html

vue使用render渲染jsx

vue&jsx文档 vue实例属性 // App.ts import hBtn from ./components/hBtn import hUl from ./components/hUlexport default {data(){return {theme: "mdui-theme-pink",accent: "mdui-theme-accent-pink",users:[aoo, boo, coo]}},methods:{},render(…

java中的多线程有什么意义_Java多线程与并发面试题(小结)

1,什么是线程?线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一…

IT必须掌握的常用命令

一,ping      它是用来检查网络是否通畅或者网络连接速度的命令。作为一个生活在网络上的管理员或者黑客来说,ping命令是第一个必须掌握的DOS命令,它所利用的原理是这样的:网络上的机器都有唯一确定的IP地址,我们…

Callable类

(一) Callable和Runnable比较相似,都可以用来实现线程任务。但callable使用了泛型设计,使用一个V类型值,能够 在执行结束后返回一个V类型的值。而Runable只会返回一个void,不能够获得执行的结果。 &#x…