当前位置:  编程技术>软件工程/软件设计
本页文章导读:
    ▪设计模式11---设计模式之中介者模式(Mediator)      1.场景问题 电脑中如果没有主板,那么就会出现如下图所示的乱成一团的结构。   如果上面的情况发生在软件开发呢? 如果软件开发需要很多模块,难道要每个模块同其他模块各个交互.........
    ▪带你走进EJB--JMS编程模型               在上篇文章中我们已经对JMS的基本模型有了基本的了解.下面内容主要是通过一张图来了解JMS的编程模型,并用一个实例来进行辅助说明. 下面这张图是JMS的编程模型,.........
    ▪从抽象谈起(二):观察者模式与回调       观察者模式又叫发布订阅模式,有订阅者和发布者;发布者可以包含了多个订阅者订阅的事件,一旦发布者执行,会执行所有的订阅者订阅的事件。我觉得这么讲还是很迷糊。其实就是说“.........

[1]设计模式11---设计模式之中介者模式(Mediator)
    来源: 互联网  发布时间: 2013-11-19
1.场景问题

电脑中如果没有主板,那么就会出现如下图所示的乱成一团的结构。


 
如果上面的情况发生在软件开发呢?
如果软件开发需要很多模块,难道要每个模块同其他模块各个交互么?那岂不是太不好用么?那么如何简化这种交互呢?跟电脑一样,弄一个中介者就行了。所有的模块跟中介者交互,那么就降低了模块间的耦合性。
2.举一个稍微具体的例子 使用电脑看电影:
首先是光驱读取光盘数据,告诉主板,状态改变
主办得到数据,交给CPU处理
CPU处理完,把数据分为视频和音频,通知主板,它处理完了。
主板去得到CPU处理过后的数据,把数据交给显卡和声卡,然后显示出视频和发出声音。
3.解决方案:中介者模式 3.1中介者定义: 用一个中介对象来封装一系列的对象交互,中介者使得各对象不需要显示的相互引用,从而使其耦合松散,而且可以独立的改变他们之间的交互。这样会有利于对象的修改和维护。
3.2中介者结构图:  
4.示例代码如下 4.1同事类的抽象父类(注意是个抽象类)
package demo09.mediator.example1;


/**
 * 同事类的抽象父类
 */
public abstract class Colleague {
	/**
	 * 持有中介者对象,每一个同事类都知道它的中介者对象
	 */
	private Mediator mediator;


	/**
	 * 构造方法,传入中介者对象
	 * 
	 * @param mediator
	 *        中介者对象
	 */
	public Colleague(Mediator mediator) {
		this.mediator = mediator;
	}


	/**
	 * 获取当前同事类对应的中介者对象
	 * 
	 * @return 对应的中介者对象
	 */
	public Mediator getMediator() {
		return mediator;
	}
}
4.2同事A注意:是继承奥
package demo09.mediator.example1;
/**
 * 具体的同事类A
 */
public class ConcreteColleagueA extends Colleague {
	public ConcreteColleagueA(Mediator mediator) {
		super(mediator);
	}
	/**
	 * 示意方法,执行某些业务功能
	 */
	public void someOperation() {
		//在需要跟其他同事通信的时候,通知中介者对象
		getMediator().changed(this);
	}
}
4.3同事B注意:是继承
package demo09.mediator.example1;
/**
 * 具体的同事类B
 */
public class ConcreteColleagueB extends Colleague {
	public ConcreteColleagueB(Mediator mediator) {
		super(mediator);
	}
	/**
	 * 示意方法,执行某些业务功能
	 */
	public void someOperation() {
		//在需要跟其他同事通信的时候,通知中介者对象
		getMediator().changed(this);
	}
}
4.4中介者,定义各个同事对象通信的接口
package demo09.mediator.example1;
/**
 * 中介者,定义各个同事对象通信的接口
 */
public interface Mediator {
	/**
	 * 同事对象在自身改变的时候来通知中介者的方法,
	 * 让中介者去负责相应的与其他同事对象的交互
	 * @param colleague 同事对象自身,好让中介者对象通过对象实例
	 *                  去获取同事对象的状态
	 */
	public void changed(Colleague colleague);
}
4.5具体的中介者实现 所有的同事交互都是在中介者中实现
package demo09.mediator.example1;
/**
 * 具体的中介者实现
 */
public class ConcreteMediator implements Mediator {
	
	/**
	 * 持有并维护同事A
	 */
	private ConcreteColleagueA colleagueA;
	/**
	 * 持有并维护同事B
	 */
	private ConcreteColleagueB colleagueB;
	
	/**
	 * 设置中介者需要了解并维护的同事A对象
	 * @param colleague 同事A对象
	 */
	public void setConcreteColleagueA(ConcreteColleagueA colleague) {
		colleagueA = colleague;
	}
	/**
	 * 设置中介者需要了解并维护的同事B对象
	 * @param colleague 同事B对象
	 */
	public void setConcreteColleagueB(ConcreteColleagueB colleague) {
		colleagueB = colleague;
	}
	
	public void changed(Colleague colleague) {
		//某个同事类发生了变化,通常需要与其他同事交户
		//具体协调相应的同事对象来实现协作行为
	}
}
5.使用中介者实现范例: 5.1结构示意图  
5.2同事类的抽象父类(注意:是个抽象类)
package demo09.mediator.example2;


/**
 * 同事类的抽象父类
 */
public abstract class Colleague {
	/**
	 * 持有中介者对象,每一个同事类都知道它的中介者对象
	 */
	private Mediator mediator;
	/**
	 * 构造方法,传入中介者对象
	 * @param mediator 中介者对象
	 */
	public Colleague(Mediator mediator) {
		this.mediator = mediator;
	}
	/**
	 * 获取当前同事类对应的中介者对象
	 * @return 对应的中介者对象
	 */
	public Mediator getMediator() {
		return mediator;
	}
}
5.3光驱类,一个同事类
package demo09.mediator.example2;
/**
 * 光驱类,一个同事类
 */
public class CDDriver extends Colleague{
	public CDDriver(Mediator mediator) {
		super(mediator);
	}
	/**
	 * 光驱读取出来的数据
	 */
	private String data = "";
	/**
	 * 获取光驱读取出来的数据
	 * @return 光驱读取出来的数据
	 */
	public String getData(){
		return this.data;
	}
	/**
	 * 读取光盘
	 */
	public void readCD(){
		//逗号前是视频显示的数据,逗号后是声音
		this.data = "设计模式,值得好好研究";
		//通知主板,自己的状态发生了改变
		this.getMediator().changed(this);
	}
}
5.4CPU类,一个同事类
package demo09.mediator.example2;
/**
 * CPU类,一个同事类
 */
public class CPU extends Colleague{
	public CPU(Mediator mediator) {
		super(mediator);
	}
	/**
	 * 分解出来的视频数据
	 */
	private String videoData = "";
	/**
	 * 分解出来的声音数据
	 */
	private String soundData = "";
	/**
	 * 获取分解出来的视频数据
	 * @return 分解出来的视频数据
	 */
	public String getVideoData() {
		return videoData;
	}
	/**
	 * 获取分解出来的声音数据
	 * @return 分解出来的声音数据
	 */
	public String getSoundData() {
		return soundData;
	}
	/**
	 * 处理数据,把数据分成音频和视频的数据
	 * @param data 被处理的数据
	 */
	public void executeData(String data){
		//把数据分解开,前面的是视频数据,后面的是音频数据
		String [] ss = data.split(",");
		this.videoData = ss[0];
		this.soundData = ss[1];
		//通知主板,CPU的工作完成
		this.getMediator().changed(this);
	}
}
5.5显卡类,一个同事类
package demo09.mediator.example2;


/**
 * 显卡类,一个同事类
 */
public class VideoCard extends Colleague {
	public VideoCard(Mediator mediator) {
		super(mediator);
	}


	/**
	 * 显示视频数据
	 * 
	 * @param data
	 *        被显示的数据
	 */
	public void showData(String data) {
		System.out.println("您正观看的是:" + data);
	}
}
5.6声卡类,一个同事类
package demo09.mediator.example2;
/**
 * 声卡类,一个同事类
 */
public class SoundCard extends Colleague{
	public SoundCard(Mediator mediator) {
		super(mediator);
	}
	
	/**
	 * 按照声频数据发出声音
	 * @param data 发出声音的数据
	 */
	public void soundData(String data){
		System.out.println("画外音:"+data);
	}
}
5.7中介者接口
package demo09.mediator.example2;
/**
 * 中介者对象的接口
 */
public interface Mediator {
	/**
	 * 同事对象在自身改变的时候来通知中介者的方法,
	 * 让中介者去负责相应的与其他同事对象的交互
	 * @param colleague 同事对象自身,好让中介者对象通过对象实例
	 *                  去获取同事对象的状态
	 */
	public void changed(Colleague colleague);
}
5.8主板类,实现中介者接口
package demo09.mediator.example2;
/**
 * 主板类,实现中介者接口
 */
public class MotherBoard implements Mediator{
	/**
	 * 需要知道要交互的同事类——光驱类
	 */
	private CDDriver cdDriver = null;
	/**
	 * 需要知道要交互的同事类——CPU类
	 */
	private CPU cpu = null;
	/**
	 * 需要知道要交互的同事类——显卡类
	 */
	private VideoCard videoCard = null;
	/**
	 * 需要知道要交互的同事类——声卡类
	 */
	private SoundCard soundCard = null;


	public void setCdDriver(CDDriver cdDriver) {
		this.cdDriver = cdDriver;
	}
	public void setCpu(CPU cpu) {
		this.cpu = cpu;
	}
	public void setVideoCard(VideoCard videoCard) {
		this.videoCard = videoCard;
	}
	public void setSoundCard(SoundCard soundCard) {
		this.soundCard = soundCard;
	}
	
	public void changed(Colleague colleague) {
		if(colleague == cdDriver){
			//表示光驱读取数据了
			this.opeCDDriverReadData((CDDriver)colleague);
		}else if(colleague == cpu){
			//表示CPU处理完了
			this.opeCPU((CPU)colleague);
		}
	}
	/**
	 * 处理光驱读取数据过后与其他对象的交互
	 * @param cd 光驱同事对象
	 */
	private void opeCDDriverReadData(CDDriver cd){
		//1:先获取光驱读取的数据
		String data = cd.getData();
		//2:把这些      
    
[2]带你走进EJB--JMS编程模型
    来源: 互联网  发布时间: 2013-11-19

        在上篇文章中我们已经对JMS的基本模型有了基本的了解.下面内容主要是通过一张图来了解JMS的编程模型,并用一个实例来进行辅助说明.

下面这张图是JMS的编程模型,

    

 

Connection Factory

     创建Connection对象的工厂,针对两种不同的JMS消息模型,分别有QueueConnectionFactory和TopicConnectionFactory两种。可以通过JNDI来查找ConnectionFactory对象。

 

//获取上下文信息

InitialContextcontext = new InitialContext();

//创建QueueConnectionFactory

QueueConnectionFactoryfactory=(QueueConnectionFactory)context.lookup("ConnectionFactory");

Connection

     Connection表示在客户端和JMS系统之间建立的链接(对TCP/IP socket的包装)。Connection可以产生一个或多个Session。跟ConnectionFactory一样,Connection也有两种类型:QueueConnection和TopicConnection。

 

    //创建QueueConnection

    QueueConnectionqueueConnection= factory.createQueueConnection();

 

 

Session

     Session是我们操作消息的接口。可以通过session创建生产者、消费者、消息等。Session提供了事务的功能。当我们需要使用session发送/接收多个消息时,可以将这些发送/接收动作放到一个事务中。同样,也分QueueSession和TopicSession。

     //创建QueueSession

QueueSessionqueueSession =queueConnection.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE);

 

Destination

      Destination的意思是消息生产者的消息发送目标或者说消息消费者的消息来源。对于消息生产者来说,它的Destination是某个队列(Queue)或某个主题(Topic);对于消息消费者来说,它的Destination也是某个队列或主题(即消息来源)。所以,Destination实际上就是两种类型的对象:Queue、Topic。

 可以通过JNDI来查找Destination。

     

       //获取Destination对象

Queuequeue = (Queue)context.lookup("queue/myqueue");

 

 

消息生产者

     消息生产者由Session创建,并用于将消息发送到Destination。同样,消息生产者分两种类型:QueueSender和TopicPublisher。可以调用消息生产者的方法(send或publish方法)发送消息!

 

       //创建文本对象

TextMessagetextMessage = queueSession.createTextMessage("hello world!");

 

//创建发送者

QueueSendersender = queueSession.createSender(queue);

 

//发送消息

sender.send(textMessage);

 


    
[3]从抽象谈起(二):观察者模式与回调
    来源: 互联网  发布时间: 2013-11-19

观察者模式又叫发布订阅模式,有订阅者和发布者;发布者可以包含了多个订阅者订阅的事件,一旦发布者执行,会执行所有的订阅者订阅的事件。我觉得这么讲还是很迷糊。其实就是说“发布者”是一段上层代码,他知道他所需要执行的过程中会发生一些事情,而这些事情具体逻辑自己又不知道,就算知道所有的逻辑,要用条件分支判断执行,这总归的是不好的,所以才有了这个模式。这是一个非常棒的模式。他使得发布者的代码保持不变。而订阅者的事件可以散步在他们自己的代码中。

我们实际应用中最常见的就是页面中的按钮点击事件。当我们双击webform中的按钮后会自动生成一个btn_OnClick的方法,然后在里面编写一些逻辑,同时也生成了btn.Click+= new EventHandler(btn_OnClick)代码(只是2.0之后这个代码就被隐藏起来了),这就是给按钮btn(订阅者)订阅了一个事件。这些逻辑理当属于按钮所在的页面,而不是需要执行这个方法的代码中。

当按钮点击之后,会触发页面的提交,webform框架可以获取是哪个按钮被点击过,然后执行btn.Click(),就可以执行我们具体的逻辑了。 设想如果不用这个模式,按钮的Click方法是不是要写很多switch来判断是哪个按钮,然后调用该有的逻辑。

那么假如说我们不用.NET的这套事件机制,该如何漂亮的抽象出Click的代码呢?

其实只要相当上一节的策略模式,我们只要给Click接受一个IClickEvent接口,然后button类再包含一组IClickEvent的成员,就可以遍历这些成员执行了。订阅的代码就变成了button.AddEvent(new xxClickEvent());即可。

在.net中,我们没必要用IClickEvent接口的形式,因为我们有委托这个方法代理(或者叫方法指针),他可以说是一个只具有一个方法的接口,而.net中的事件本身也是委托。只是事件形式的委托是封闭的,不可在外部直接赋值操作,只能订阅和删除订阅。

综上来看,观察者模式不过是一个处理未知方法的模式,他漂亮的把具体逻辑分散到他该属于地方。

在web前端的Javascript中,这种情况就更为普遍。比如我们用jQuery时,给一个按钮增加一个onClick方法,只需要$(“#btn”).click(function(){})即可。浏览器会知道具体的哪个按钮被点击,甚至我们随便点击页面的一个地方,都会被浏览器截获,假如我们有相应的OnClick方法,他会执行调用,并传值给我们当前鼠标的位置等。 在我们发起一个ajax请求时,会有一个参数是callback方法,在判断完XmlHttpRequest的readyState == 4后调用,每个ajax的请求完后的callback都不一致。所以说他也是观察者模式。我们说这种叫做回调模式是不是更好?所谓的“回”就是使用之前的代码,而不是当前的代码。

说了这么多,不知道表达清楚没有,我们来讲一个实际应用不依赖于框架的。

比如我们发布一篇文章,常用逻辑就是保存文章。如果哪天来了新的需求,比如说跟某某公司合作,发表完文章之后需要给用户增加一些奖励。又过了几天又来一个新的需求,所最近抓的紧,需要对文章审

    
最新技术文章:
 




特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3