﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Mark's Java Blog-随笔分类-设计模式</title><link>http://www.blogjava.net/mark1207/category/30107.html</link><description>MyEclipse, Java EE, Spring, Struts, Hibernate, JPA, SWT, Swing, AJAX, JavaScript,SOA</description><language>zh-cn</language><lastBuildDate>Sat, 12 Apr 2008 14:20:05 GMT</lastBuildDate><pubDate>Sat, 12 Apr 2008 14:20:05 GMT</pubDate><ttl>60</ttl><item><title>（转）《分析模式：可重用对象模型》-- 责任模式(party)</title><link>http://www.blogjava.net/mark1207/archive/2008/04/01/190072.html</link><dc:creator>Mark</dc:creator><author>Mark</author><pubDate>Tue, 01 Apr 2008 06:35:00 GMT</pubDate><guid>http://www.blogjava.net/mark1207/archive/2008/04/01/190072.html</guid><wfw:comment>http://www.blogjava.net/mark1207/comments/190072.html</wfw:comment><comments>http://www.blogjava.net/mark1207/archive/2008/04/01/190072.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mark1207/comments/commentRss/190072.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mark1207/services/trackbacks/190072.html</trackback:ping><description><![CDATA[<h1 style="line-height: 130%"><span style="font-size: 14pt">1<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 14pt; font-family: 宋体">责任模式</span></h1>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm"><span style="font-family: 宋体">这一章关注的重点是<strong>关系</strong>，以及怎样为错综复杂的关系建立模型，另外，所有的插图都来自原书（《</span>Analysis Patterns<span style="font-family: 宋体">：</span>Reusable Object Models<span style="font-family: 宋体">》），并遵循</span>UML<span style="font-family: 宋体">标准。</span></p>
<h2 style="line-height: 130%">1.1<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span>Party模式 </h2>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm"><span style="font-family: 宋体">在这一章中，首先我们接触到是是</span><strong>Party</strong><span style="font-family: 宋体">模式，在进行系统分析和概念模型设计的时候，经常发现<strong><em>人和各种各样的组织有着同样的行为</em></strong>，例如，固定电话的计费可能是针对个人，也可能是一个单位；需要各种服务的时候，你可能求助于一个服务公司，或者服务公司一个特定的业务员。总之，因为人（<strong>Person</strong><span style="font-family: 宋体">）和组织（</span><strong>Organization</strong><span style="font-family: 宋体">）表现上的一致性，如下图所见，我们从中抽象出</span><strong>Party</strong><span style="font-family: 宋体">，作为</span><strong>Person</strong></span><span style="font-family: 宋体">和</span><strong>Organization</strong><span style="font-family: 宋体">的抽象父类。</span></p>
<p style="line-height: 130%"><img height="284" alt="" src="http://www.uml.org.cn/sjms/images/party.2.jpg" width="546" v:shapes="_x0000_i1025" /></p>
<h2 style="line-height: 130%"><span style="font-size: 12pt; font-family: 宋体">1.2<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; font-family: 宋体">组织（</span><span style="font-size: 12pt; font-family: 宋体">Organization</span><span style="font-size: 12pt; font-family: 宋体">）的内部结构</span></h2>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm"><span style="font-family: 宋体">第二步，如果我们把注意力转移到组织（</span><strong>Organization</strong><span style="font-family: 宋体">）的内部结构，就会发现一些有趣的问题，通常最常见的一种结构是金字塔结构，因此建模时可能按照这样的结构建立线性的模型，例如：</span></p>
<p style="line-height: 130%"><img height="118" alt="" src="http://www.uml.org.cn/sjms/images/party.3.jpg" width="546" v:shapes="_x0000_i1026" /></p>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm">这样的模型并没有错误，但是有缺陷，首先不能满足比较复杂的组织关系，更严重的是，一旦<strong><em>需要更多的层次关系</em></strong>，例如存在部门直接上下级关系以及区域附属管理方式，必将引起整个模型的更改，对系统的影响可想而知，在这种情况下，最通常的改进措施是引入层次关系，如下图所示：</p>
<p style="line-height: 130%"><img height="279" alt="" src="http://www.uml.org.cn/sjms/images/party.4.gif" width="428" v:shapes="_x0000_i1027" /></p>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm"><span style="font-family: 宋体">通过增加新的关联关系，可以灵活实现组织（</span><strong>Organization</strong><span style="font-family: 宋体">）之间的各种关系以及可能的变化。在上图中，<strong>{hierarchy}</strong><span style="font-family: 宋体">是一个约束（</span><strong>constraint</strong><span style="font-family: 宋体">）来限定关系。</span></span></p>
<h2 style="line-height: 130%"><span style="font-size: 12pt">1.3<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; font-family: 宋体">组织关系抽象</span></h2>
<p style="margin-left: 0cm; line-height: 130%; margin-right: 0cm">第三步，在一般的情况下，以上的模式已经足够解决问题，但当这样的层次和组织关系很多而且复杂时（超过两种），例如现在流行的矩阵管理，就可以将关系本身抽取出来独立处理，如下图所示，作者此时考虑到组织结构的有效时段，所以加入了一个时间段属性来记录组织结构的存在时间。</p>
<p style="line-height: 130%"><img height="333" alt="" src="http://www.uml.org.cn/sjms/images/party.5.jpg" width="576" v:shapes="_x0000_i1028" /></p>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm"><span style="font-family: 宋体">请注意，在这个模式中，</span><strong>Organization Structure</strong><span style="font-family: 宋体">才是模式的核心，在系统中，由两个<strong>Organization</strong><span style="font-family: 宋体">的实例（分别充当</span></span>parent<span style="font-family: 宋体">和</span>subsidiary<span style="font-family: 宋体">），以及一个</span><strong>Type</strong><span style="font-family: 宋体">实例来说明该结构的类型。在这样的结构中，可能存在许多的规则（<strong>Rule</strong><span style="font-family: 宋体">），这些规则可以根据情况分别处理：如果</span><strong>Type</strong><span style="font-family: 宋体">很多，而且规则主要跟</span><strong>Type</strong><span style="font-family: 宋体">有关，就分配给与</span><strong>Type</strong><span style="font-family: 宋体">相关联；如果</span><strong>Type</strong><span style="font-family: 宋体">并不多，但主要根据</span><strong>Organization</strong><span style="font-family: 宋体">的子类型变化，就可以分布到</span><strong>Organization</strong><span style="font-family: 宋体">的子类型中。</span></span></p>
<h2 style="line-height: 130%"><span style="font-size: 12pt; font-family: 宋体">1.4<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; font-family: 宋体">责任（Accountability）模式</span></h2>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm"><span style="font-family: 宋体">第四步，从第一步看到，</span><strong>Party</strong><span style="font-family: 宋体">是<strong>Person</strong><span style="font-family: 宋体">和</span><strong>Organization</strong><span style="font-family: 宋体">的抽象父类，因此把</span></span>Party<span style="font-family: 宋体">代入上面的模式（有点象我们小时侯代数里常用的代入），正式形成责任（</span><strong>Accountability</strong><span style="font-family: 宋体">）模式。</span></p>
<p style="margin: 2.5pt 0cm; text-indent: 10pt; line-height: 130%"><img height="318" alt="" src="http://www.uml.org.cn/sjms/images/party.6.jpg" width="521" v:shapes="_x0000_i1029" /></p>
<h2 style="line-height: 130%"><span style="font-size: 12pt; font-family: 宋体">1.5<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; font-family: 宋体">知识层（Knowledge level）和操作层（Operational level）分离 </span></h2>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm"><span style="font-family: 宋体">出现这样一种想法是考虑到以下情况：当</span><strong>Accountablity Type</strong><span style="font-family: 宋体">的数量比<strong>Accountability</strong><span style="font-family: 宋体">的数量多很多的时候，处理</span><strong>Accountablity Type</strong><span style="font-family: 宋体">的规则也变得更为复杂，要解决这样的问题，就可以引入知识层和操作层的分离。</span></span></p>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm"><span style="font-family: 宋体">由下图可见，用虚线隔离开的，就是知识层（</span><strong>Knowledge level</strong><span style="font-family: 宋体">）和操作层（<strong>Operational level</strong><span style="font-family: 宋体">），在这个模型中，知识层（</span><strong>Knowledge level</strong><span style="font-family: 宋体">）由三个类协作完成，它们分别是</span><strong>Accountablity Type</strong><span style="font-family: 宋体">、</span><strong>Connection Rule</strong><span style="font-family: 宋体">、</span><strong>Party Type</strong><span style="font-family: 宋体">，在</span><strong>Connection Rule</strong><span style="font-family: 宋体">中定义合法的</span><strong>Party</strong><span style="font-family: 宋体">关系规则，并通过</span><strong>Accountablity Type</strong><span style="font-family: 宋体">对</span><strong>Accountablity</strong><span style="font-family: 宋体">进行创建时的合法性检验。它的另一个好处就是，可以将知识层的实例化独立出来，作为操作层（</span><strong>Operational level</strong><span style="font-family: 宋体">）运行时的配置；换句话说，当知识层的规则改变时，系统的行为将被改变，而不需要任何其他代码的改动，这当然是一种比较理想化的情况。</span></span></p>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm"><img height="476" alt="" src="http://www.uml.org.cn/sjms/images/party.7.jpg" width="524" v:shapes="_x0000_i1030" />&nbsp;</p>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm">由此想到，构建专家系统的设计思路也可以从这个模式得到一些启发，这是笔者一时的感触。</p>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm">在原书中，如何实现这样的模型提得比较模糊，但是笔者认为，可以将它们作为正常的模型来实现，两个层次的区分只是表明它们各自担负的任务和地位不同。知识层倾向于描述系统可能存在的各种形式，并设定判断系统是否有效的各种规则；操作层则描述在这样的配置下系统实际的行为。通过改变内在的配置来改变外在的行为，就是这个模式的目的。</p>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm">由于这个模式的特点，改变系统行为时不必更改操作层的代码，但是，并不意味着改变系统行为连测试也不必要做。同样，也需要调试、配置管理。</p>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm">作者也提到，这样的模式用起来并不轻松，甚至在一般的系统中也不必要，但当你发现有必要用它的时候，别犹豫（感觉象用降落伞一样）！</p>
<h2 style="line-height: 130%"><span style="font-size: 12pt">1.6<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; font-family: 宋体">小结</span></h2>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm"><span style="font-family: 宋体">从简单到复杂，前面分五步介绍了适用于解决</span><strong>Party</strong><span style="font-family: 宋体">及其关系的各种模式，每种推荐的模式都有其表现的机会，希望我这篇文章可以起到一些抛砖引玉的作用，并欢迎大家对其中的错误进行指正，欢迎发表意见，进行交流。</span></p>
<p style="margin-left: 0cm; text-indent: 21pt; line-height: 130%; margin-right: 0cm"><span style="font-family: 宋体">原文参照《</span>Analysis Patterns<span style="font-family: 宋体">：</span>Reusable Object Models<span style="font-family: 宋体">》，</span>Chapter 2<span style="font-family: 宋体">，</span>Martin Fowler</p>
<br />
原文：<a href="http://blog.csdn.net/nzh_csdn/archive/2004/12/19/221484.aspx">http://blog.csdn.net/nzh_csdn/archive/2004/12/19/221484.aspx</a>
<img src ="http://www.blogjava.net/mark1207/aggbug/190072.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mark1207/" target="_blank">Mark</a> 2008-04-01 14:35 <a href="http://www.blogjava.net/mark1207/archive/2008/04/01/190072.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>观察者模式（二）</title><link>http://www.blogjava.net/mark1207/archive/2008/03/18/187004.html</link><dc:creator>Mark</dc:creator><author>Mark</author><pubDate>Tue, 18 Mar 2008 07:04:00 GMT</pubDate><guid>http://www.blogjava.net/mark1207/archive/2008/03/18/187004.html</guid><wfw:comment>http://www.blogjava.net/mark1207/comments/187004.html</wfw:comment><comments>http://www.blogjava.net/mark1207/archive/2008/03/18/187004.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mark1207/comments/commentRss/187004.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mark1207/services/trackbacks/187004.html</trackback:ping><description><![CDATA[使用java.util.Observable类和java.util.Observer接口实现观察者模式气象站（拉、推均实现，自己也可以按照它的实现方法扩展）<br />
<br />
拉：也就是观察者来决定接到&#8220;可观察者&#8221;类通知时获取&#8220;可观察者&#8221;的哪些变化。调用方法notifyObservers（）；<br />
<br />
推：&#8220;可观察者&#8221;类通知观察者时传递给观察者自身所有的变化。调用方法notifyObservers（Object arg）；<br />
<br />
<br />
import java.util.Observable;<br />
import java.util.Observer;<br />
&nbsp;//此类实现的是&#8220;拉&#8221;的发式，继承java.util.Observable类<br />
public class WeatherData extends Observable {<br />
&nbsp;private float temperature;<br />
&nbsp;private float humidity;<br />
&nbsp;private float pressure;<br />
&nbsp;//构造器不需要为了记住观察者们而建立数据结构了<br />
&nbsp;public WeatherData() { }<br />
&nbsp;<br />
&nbsp;public void measurementsChanged() {<br />
&nbsp;&nbsp;setChanged();//指示可观察者状态已改变（可以由状态是否改变决定是否通知观察者，很容易，自己实现就行）<br />
&nbsp;&nbsp;notifyObservers();//没有调用传送数据对象，表示采用&#8220;拉&#8221;的做法<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void setMeasurements(float temperature, float humidity, float pressure) {<br />
&nbsp;&nbsp;this.temperature = temperature;<br />
&nbsp;&nbsp;this.humidity = humidity;<br />
&nbsp;&nbsp;this.pressure = pressure;<br />
&nbsp;&nbsp;measurementsChanged();<br />
&nbsp;}<br />
&nbsp;//以下不是新方法，而是为了使用&#8220;拉&#8221;的做法<br />
&nbsp;public float getTemperature() {<br />
&nbsp;&nbsp;return temperature;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public float getHumidity() {<br />
&nbsp;&nbsp;return humidity;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public float getPressure() {<br />
&nbsp;&nbsp;return pressure;<br />
&nbsp;}<br />
}<br />
<br />
<br />
import java.util.Observable;<br />
import java.util.Observer;<br />
&nbsp;//实现java.util.Observer接口，成为观察者<br />
public class CurrentConditionsDisplay implements Observer, DisplayElement {<br />
&nbsp;Observable observable;<br />
&nbsp;private float temperature;<br />
&nbsp;private float humidity;<br />
&nbsp;//构造器需要Observable&nbsp;作为参数，并将本对象登记为观察者<br />
&nbsp;public CurrentConditionsDisplay(Observable observable) {<br />
&nbsp;&nbsp;this.observable = observable;<br />
&nbsp;&nbsp;observable.addObserver(this);<br />
&nbsp;}<br />
&nbsp;//改变update()方法，增加Observable&nbsp;和数据对象为参数<br />
&nbsp;public void update(Observable obs, Object arg) {<br />
&nbsp;&nbsp;if (obs instanceof WeatherData) {<br />
&nbsp;&nbsp;&nbsp;WeatherData weatherData = (WeatherData)obs;<br />
&nbsp;&nbsp;&nbsp;this.temperature = weatherData.getTemperature();<br />
&nbsp;&nbsp;&nbsp;this.humidity = weatherData.getHumidity();<br />
&nbsp;&nbsp;&nbsp;display();<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void display() {<br />
&nbsp;&nbsp;System.out.println("Current conditions: " + temperature <br />
&nbsp;&nbsp;&nbsp;+ "F degrees and " + humidity + "% humidity");<br />
&nbsp;}<br />
}<br />
<br />
<span style="color: red">注意：java.util.Observable是一个类而不是接口，而且还没有实现任何接口。它本身的实现有很多问题，限制了它的使用和复用。由于它是个类，所以我们只能继承，java不允许多继承，所以限制了其复用潜力。而且setChanged()方法被保护起来（被定义成protected），这就意味着除非继承，否则无法创建实例并组合到自己的对象中，这就违背了设计原则&#8220;多用组合，少用继承&#8221;。</span>
<img src ="http://www.blogjava.net/mark1207/aggbug/187004.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mark1207/" target="_blank">Mark</a> 2008-03-18 15:04 <a href="http://www.blogjava.net/mark1207/archive/2008/03/18/187004.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>观察者模式（一）</title><link>http://www.blogjava.net/mark1207/archive/2008/03/18/186986.html</link><dc:creator>Mark</dc:creator><author>Mark</author><pubDate>Tue, 18 Mar 2008 05:52:00 GMT</pubDate><guid>http://www.blogjava.net/mark1207/archive/2008/03/18/186986.html</guid><wfw:comment>http://www.blogjava.net/mark1207/comments/186986.html</wfw:comment><comments>http://www.blogjava.net/mark1207/archive/2008/03/18/186986.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mark1207/comments/commentRss/186986.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mark1207/services/trackbacks/186986.html</trackback:ping><description><![CDATA[<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;观察者模式：在对象之间定义一对多的依赖，当一个对象改变状态，依赖他的对象都会收到通知，并自动更新。（以松耦合方式在一系列对象之间沟通状态，代表人物--MVC）<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注意事项：主题（可观察者）用一个共同的接口来更新观察者，主题不知道观察者的细节，只知道观察者实现了观察者接口。使用此模式时，你可从被观察者处推（push）或拉（pull）数据（推的方式被认为更正确）。有多个观察者时，不可以依赖特定的通知顺序。java有多种观察者模式的实现，包括java.util.Observable(有一些违背设计原则的问题，有必要的话可以实现自己的Observable)，JavaBeans,RMI等，Swing大量使用此模式，许多GUI框架也是如此。<br />
<br />
</p>
用观察者模式实现一个气象站的实例：<br />
要求当WeatherData对象（接受物理气象站数据的对象）更新数据时，随即会更新三个布告板的显示：目前状况（温度、湿度、气压）、气象统计和天气预报。并且公布API可以让其他人写出自己的布告板。<br />
<br />
代码：<br />
//主题接口，提供注册、删除、更新布告板的方法<br />
public interface Subject {<br />
&nbsp;public void registerObserver(Observer o);<br />
&nbsp;public void removeObserver(Observer o);<br />
&nbsp;public void notifyObservers();<br />
}<br />
<br />
//观察者接口，提供更新本布告板的方法<br />
public interface Observer {<br />
&nbsp;public void update(float temp, float humidity, float pressure);<br />
}<br />
<br />
//布告板显示接口，提供布告板显示的方法<br />
public interface DisplayElement {<br />
&nbsp;public void display();<br />
}<br />
<br />
//主题实现类<br />
public class WeatherData implements Subject {<br />
&nbsp;private ArrayList observers;<br />
&nbsp;private float temperature;<br />
&nbsp;private float humidity;<br />
&nbsp;private float pressure;<br />
&nbsp;//构造方法中初始化观察者记录<br />
&nbsp;public WeatherData() {<br />
&nbsp;&nbsp;observers = new ArrayList();<br />
&nbsp;}<br />
&nbsp;//注册观察者<br />
&nbsp;public void registerObserver(Observer o) {<br />
&nbsp;&nbsp;observers.add(o);<br />
&nbsp;}<br />
&nbsp;//删除观察者<br />
&nbsp;public void removeObserver(Observer o) {<br />
&nbsp;&nbsp;int i = observers.indexOf(o);<br />
&nbsp;&nbsp;if (i &gt;= 0) {<br />
&nbsp;&nbsp;&nbsp;observers.remove(i);<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
&nbsp;//当主题状态改变时调用，以通知所有观察者<br />
&nbsp;public void notifyObservers() {<br />
&nbsp;&nbsp;for (int i = 0; i &lt; observers.size(); i++) {<br />
&nbsp;&nbsp;&nbsp;Observer observer = (Observer)observers.get(i);<br />
&nbsp;&nbsp;&nbsp;observer.update(temperature, humidity, pressure);<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
&nbsp;//通知观察者方法<br />
&nbsp;public void measurementsChanged() {<br />
&nbsp;&nbsp;notifyObservers();<br />
&nbsp;}<br />
&nbsp;//更新数据方法<br />
&nbsp;public void setMeasurements(float temperature, float humidity, float pressure) {<br />
&nbsp;&nbsp;this.temperature = temperature;<br />
&nbsp;&nbsp;this.humidity = humidity;<br />
&nbsp;&nbsp;this.pressure = pressure;<br />
&nbsp;&nbsp;measurementsChanged();<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;// other WeatherData methods here<br />
&nbsp;<br />
&nbsp;public float getTemperature() {<br />
&nbsp;&nbsp;return temperature;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public float getHumidity() {<br />
&nbsp;&nbsp;return humidity;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public float getPressure() {<br />
&nbsp;&nbsp;return pressure;<br />
&nbsp;}<br />
}<br />
<br />
//观察者实现类<br />
public class CurrentConditionsDisplay implements Observer, DisplayElement {<br />
&nbsp;private float temperature;<br />
&nbsp;private float humidity;<br />
&nbsp;private Subject weatherData;<br />
&nbsp;//构造方法中把此观察者注册到主题<br />
&nbsp;public CurrentConditionsDisplay(Subject weatherData) {<br />
&nbsp;&nbsp;this.weatherData = weatherData;<br />
&nbsp;&nbsp;weatherData.registerObserver(this);<br />
&nbsp;}<br />
&nbsp;//修改观察者状态<br />
&nbsp;public void update(float temperature, float humidity, float pressure) {<br />
&nbsp;&nbsp;this.temperature = temperature;<br />
&nbsp;&nbsp;this.humidity = humidity;<br />
&nbsp;&nbsp;display();<br />
&nbsp;}<br />
&nbsp;//显示布告板更新内容<br />
&nbsp;public void display() {<br />
&nbsp;&nbsp;System.out.println("Current conditions: " + temperature <br />
&nbsp;&nbsp;&nbsp;+ "F degrees and " + humidity + "% humidity");<br />
&nbsp;}<br />
}<br />
<br />
<p>public class ForecastDisplay implements Observer, DisplayElement {<br />
&nbsp;private float currentPressure = 29.92f;&nbsp; <br />
&nbsp;private float lastPressure;<br />
&nbsp;private WeatherData weatherData;</p>
<p>&nbsp;public ForecastDisplay(WeatherData weatherData) {<br />
&nbsp;&nbsp;this.weatherData = weatherData;<br />
&nbsp;&nbsp;weatherData.registerObserver(this);<br />
&nbsp;}</p>
<p>&nbsp;public void update(float temp, float humidity, float pressure) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastPressure = currentPressure;<br />
&nbsp;&nbsp;currentPressure = pressure;</p>
<p>&nbsp;&nbsp;display();<br />
&nbsp;}</p>
<p>&nbsp;public void display() {<br />
&nbsp;&nbsp;System.out.print("Forecast: ");<br />
&nbsp;&nbsp;if (currentPressure &gt; lastPressure) {<br />
&nbsp;&nbsp;&nbsp;System.out.println("Improving weather on the way!");<br />
&nbsp;&nbsp;} else if (currentPressure == lastPressure) {<br />
&nbsp;&nbsp;&nbsp;System.out.println("More of the same");<br />
&nbsp;&nbsp;} else if (currentPressure &lt; lastPressure) {<br />
&nbsp;&nbsp;&nbsp;System.out.println("Watch out for cooler, rainy weather");<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}<br />
</p>
<br />
<p>public class StatisticsDisplay implements Observer, DisplayElement {<br />
&nbsp;private float maxTemp = 0.0f;<br />
&nbsp;private float minTemp = 200;<br />
&nbsp;private float tempSum= 0.0f;<br />
&nbsp;private int numReadings;<br />
&nbsp;private WeatherData weatherData;</p>
<p>&nbsp;public StatisticsDisplay(WeatherData weatherData) {<br />
&nbsp;&nbsp;this.weatherData = weatherData;<br />
&nbsp;&nbsp;weatherData.registerObserver(this);<br />
&nbsp;}</p>
<p>&nbsp;public void update(float temp, float humidity, float pressure) {<br />
&nbsp;&nbsp;tempSum += temp;<br />
&nbsp;&nbsp;numReadings++;</p>
<p>&nbsp;&nbsp;if (temp &gt; maxTemp) {<br />
&nbsp;&nbsp;&nbsp;maxTemp = temp;<br />
&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;if (temp &lt; minTemp) {<br />
&nbsp;&nbsp;&nbsp;minTemp = temp;<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;display();<br />
&nbsp;}</p>
<p>&nbsp;public void display() {<br />
&nbsp;&nbsp;System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)<br />
&nbsp;&nbsp;&nbsp;+ "/" + maxTemp + "/" + minTemp);<br />
&nbsp;}<br />
}<br />
</p>
<br />
//测试类<br />
<p>public class WeatherStation {</p>
<p>&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;WeatherData weatherData = new WeatherData();<br />
&nbsp;<br />
&nbsp;&nbsp;CurrentConditionsDisplay currentDisplay = <br />
&nbsp;&nbsp;&nbsp;new CurrentConditionsDisplay(weatherData);<br />
&nbsp;&nbsp;StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);<br />
&nbsp;&nbsp;ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);</p>
<p>&nbsp;&nbsp;weatherData.setMeasurements(80, 65, 30.4f);<br />
&nbsp;&nbsp;weatherData.setMeasurements(82, 70, 29.2f);<br />
&nbsp;&nbsp;weatherData.setMeasurements(78, 90, 29.2f);<br />
&nbsp;}<br />
}<br />
<br />
当我们想添加一个布告板的时候只要实现观察者借口就可以加入主题通知的记录中，实际代码如下：<br />
//我们要添加一个酷热指数的布告板，利用一套公式来计算酷热指数。<br />
</p>
<p>public class HeatIndexDisplay implements Observer, DisplayElement {<br />
&nbsp;float heatIndex = 0.0f;<br />
&nbsp;private WeatherData weatherData;</p>
<p>&nbsp;public HeatIndexDisplay(WeatherData weatherData) {<br />
&nbsp;&nbsp;this.weatherData = weatherData;<br />
&nbsp;&nbsp;weatherData.registerObserver(this);<br />
&nbsp;}</p>
<p>&nbsp;public void update(float t, float rh, float pressure) {<br />
&nbsp;&nbsp;heatIndex = computeHeatIndex(t, rh);<br />
&nbsp;&nbsp;display();<br />
&nbsp;}<br />
&nbsp;//酷热指数计算<br />
&nbsp;private float computeHeatIndex(float t, float rh) {<br />
&nbsp;&nbsp;float index = (float)((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh) <br />
&nbsp;&nbsp;&nbsp;+ (0.00941695 * (t * t)) + (0.00728898 * (rh * rh)) <br />
&nbsp;&nbsp;&nbsp;+ (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) +<br />
&nbsp;&nbsp;&nbsp;(0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 * <br />
&nbsp;&nbsp;&nbsp;(rh * rh * rh)) + (0.00000142721 * (t * t * t * rh)) + <br />
&nbsp;&nbsp;&nbsp;(0.000000197483 * (t * rh * rh * rh)) - (0.0000000218429 * (t * t * t * rh * rh)) +<br />
&nbsp;&nbsp;&nbsp;0.000000000843296 * (t * t * rh * rh * rh)) -<br />
&nbsp;&nbsp;&nbsp;(0.0000000000481975 * (t * t * t * rh * rh * rh)));<br />
&nbsp;&nbsp;return index;<br />
&nbsp;}</p>
<p>&nbsp;public void display() {<br />
&nbsp;&nbsp;System.out.println("Heat index is " + heatIndex);<br />
&nbsp;}<br />
}<br />
<br />
//加入酷热指数布告板后的测试类<br />
</p>
<p>public class WeatherStationHeatIndex {</p>
<p>&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;WeatherData weatherData = new WeatherData();<br />
&nbsp;&nbsp;CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);<br />
&nbsp;&nbsp;StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);<br />
&nbsp;&nbsp;ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);<br />
&nbsp;&nbsp;HeatIndexDisplay heatIndexDisplay = new HeatIndexDisplay(weatherData);</p>
<p>&nbsp;&nbsp;weatherData.setMeasurements(80, 65, 30.4f);<br />
&nbsp;&nbsp;weatherData.setMeasurements(82, 70, 29.2f);<br />
&nbsp;&nbsp;weatherData.setMeasurements(78, 90, 29.2f);<br />
&nbsp;}<br />
}</p>
<img src ="http://www.blogjava.net/mark1207/aggbug/186986.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mark1207/" target="_blank">Mark</a> 2008-03-18 13:52 <a href="http://www.blogjava.net/mark1207/archive/2008/03/18/186986.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OO设计原则</title><link>http://www.blogjava.net/mark1207/archive/2008/03/18/186984.html</link><dc:creator>Mark</dc:creator><author>Mark</author><pubDate>Tue, 18 Mar 2008 05:48:00 GMT</pubDate><guid>http://www.blogjava.net/mark1207/archive/2008/03/18/186984.html</guid><wfw:comment>http://www.blogjava.net/mark1207/comments/186984.html</wfw:comment><comments>http://www.blogjava.net/mark1207/archive/2008/03/18/186984.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mark1207/comments/commentRss/186984.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mark1207/services/trackbacks/186984.html</trackback:ping><description><![CDATA[1、找出应用中可能需要变化之处，把它们独立出来，不要和那些不需要变化的代码混在一起（封装变化）。<br />
2、针对借口编程，而不是针对实现编程&nbsp;。<br />
3、多用组合，少用继承。<br />
4、为交互对象之间的松耦合设计而努力（松耦合设计更有弹性，更能应对变化） <br />
5、类应该对扩展开放，对修改关闭。 <br />
6、依赖抽象，不要依赖具体类。
<img src ="http://www.blogjava.net/mark1207/aggbug/186984.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mark1207/" target="_blank">Mark</a> 2008-03-18 13:48 <a href="http://www.blogjava.net/mark1207/archive/2008/03/18/186984.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>策略模式</title><link>http://www.blogjava.net/mark1207/archive/2008/03/17/186698.html</link><dc:creator>Mark</dc:creator><author>Mark</author><pubDate>Mon, 17 Mar 2008 01:55:00 GMT</pubDate><guid>http://www.blogjava.net/mark1207/archive/2008/03/17/186698.html</guid><wfw:comment>http://www.blogjava.net/mark1207/comments/186698.html</wfw:comment><comments>http://www.blogjava.net/mark1207/archive/2008/03/17/186698.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mark1207/comments/commentRss/186698.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mark1207/services/trackbacks/186698.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;策略模式定义了算法族，分别封装起来，让它们之间可以互相替换，此模式让算法的变化独立于使用算法的客户。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;个人理解：策略模式就是把父类中需要根据不同情况而变化的行为想成&#8220;一族算法&#8221;，并把它抽象出来变成两个接口，在父类中包含这个接口类型的属性，这样就可以利用不同的接口实现类来改变这个行为。并且添加了getter,setter方法后可以在运行时随意改变行为的实现，这样就可以使我们的设计更加富有弹性，可以使我们的设计更加易于维护和扩展。 <br />
<br />
实例代码：<br />
<br />
要求：所有的各类鸭子继承一个超类，并且可以拥有自己的特性，可以因为需求变化而改变某个鸭子或某一类鸭子的某种特性（如可以改变叫声和飞行状态）。<br />
<br />
//鸭子超类<br />
public abstract class Duck {<br />
//飞行状态算法族<br />
&nbsp;FlyBehavior flyBehavior;<br />
//鸣叫状态算法族<br />
&nbsp;QuackBehavior quackBehavior;<br />
&nbsp;<br />
&nbsp;public Duck() {<br />
&nbsp;}<br />
&nbsp;//改变算法组状态的方法，可是在运行时改变特性的方法<br />
&nbsp;public void setFlyBehavior (FlyBehavior fb) {<br />
&nbsp;&nbsp;flyBehavior = fb;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void setQuackBehavior(QuackBehavior qb) {<br />
&nbsp;&nbsp;quackBehavior = qb;<br />
&nbsp;}<br />
&nbsp;//由子类继承并实现的鸭子特性（不会改变）<br />
&nbsp;abstract void display();<br />
&nbsp;//由子类继承的飞行和鸣叫方法<br />
&nbsp;public void performFly() {<br />
&nbsp;&nbsp;flyBehavior.fly();<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void performQuack() {<br />
&nbsp;&nbsp;quackBehavior.quack();<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void swim() {<br />
&nbsp;&nbsp;System.out.println("All ducks float, even decoys!");<br />
&nbsp;}<br />
}<br />
<br />
//飞行接口<br />
public interface FlyBehavior {<br />
&nbsp;public void fly();<br />
}<br />
<br />
//飞行状态实现类（不能飞）<br />
public class FlyNoWay implements FlyBehavior {<br />
&nbsp;public void fly() {<br />
&nbsp;&nbsp;System.out.println("I can't fly");<br />
&nbsp;}<br />
}<br />
<br />
//火箭助推器<br />
public class FlyRocketPowered implements FlyBehavior {<br />
&nbsp;public void fly() {<br />
&nbsp;&nbsp;System.out.println("I'm flying with a rocket");<br />
&nbsp;}<br />
}<br />
//鸣叫接口<br />
public interface QuackBehavior {<br />
&nbsp;public void quack();<br />
}<br />
<br />
//鸣叫状态实现类（不能叫）<br />
public class MuteQuack implements QuackBehavior {<br />
&nbsp;public void quack() {<br />
&nbsp;&nbsp;System.out.println("&lt;&lt; Silence &gt;&gt;");<br />
&nbsp;}<br />
}<br />
<br />
//一个模型鸭的子类，在创建时指定特性<br />
public class DecoyDuck extends Duck {<br />
//在构造器中指定飞行特性和鸣叫特性（不能飞，不能叫）<br />
&nbsp;public DecoyDuck() {<br />
&nbsp;&nbsp;setFlyBehavior(new FlyNoWay());<br />
&nbsp;&nbsp;setQuackBehavior(new MuteQuack());<br />
&nbsp;}<br />
<br />
&nbsp;public void display() {<br />
&nbsp;&nbsp;System.out.println("I'm a duck Decoy");<br />
&nbsp;}<br />
}<br />
<br />
//测试程序<br />
<p>public class MiniDuckSimulator {<br />
&nbsp;<br />
&nbsp;public static void main(String[] args) {<br />
&nbsp;<br />
&nbsp;&nbsp;DecoyDuck&nbsp;decoy = new DecoyDuck();<br />
</p>
<p>&nbsp;&nbsp;decoy.performQuack();<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;decoy .performFly();&nbsp;<br />
//运行时把飞行状态改为火箭助推器飞行<br />
&nbsp;&nbsp;decoy .setFlyBehavior(new FlyRocketPowered());<br />
&nbsp;&nbsp;decoy .performFly();<br />
&nbsp;}<br />
}<br />
</p>
<img src ="http://www.blogjava.net/mark1207/aggbug/186698.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mark1207/" target="_blank">Mark</a> 2008-03-17 09:55 <a href="http://www.blogjava.net/mark1207/archive/2008/03/17/186698.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>