|
Java深入C定程?׃可避免的到设计模式(design pattern)q一概念,了解设计模式,自己对java中的接口或抽象类应用有更q理解.设计模式在java的中型系l中应用q泛,遵@一定的~程模式,才能使自q代码便于理解,易于交流,Observer(观察?模式是比较常用的一个模?其在界面设计中应用q泛,而本站所x的是Java在电(sh)子商务系l中应用,因此想从?sh)子商务实例中分析Observer的应?
虽然|上商店形式多样,每个站点有自q特色,但也有其一般的共?单就"商品的变?以便及时通知订户"q一?是很多网上商店共有的模式,q一模式cMObserver patern.
具体的说,如果|上商店中商品在名称 h{方面有变化,如果pȝ能自动通知会员,是|上商店区别传统商店的一大特?q就需要在商品product中加入Observerq样角色,以便productl节发生变化?Observer能自动观察到q种变化,q能q行及时的update或notify动作.
Java的APIqؓ为我们提供现成的Observer接口Java.util.Observer.我们只要直接使用它就可以.
我们必须extends Java.util.Observer才能真正使用?
1.提供Add/Delete observer的方?
2.提供通知(notisfy) 所有observer的方?
import java.util.Observable; public class product extends Observable { private String name; private float price; public String getName() { public void setName(String name) { } public float getPrice() { public void setPrice(float price) { } //以下可以是数据库更新 插入命o. } public static void main(String[] args) { |
我们注意?在productcM 的setXXXҎ(gu)?我们讄?notify(通知)Ҏ(gu), 当调用setXXX,实际上就触发了notisfyObserversҎ(gu),q将通知相应观察者应该采取行动了.
下面看看q些观察者的代码,他们I竟采取了什么行?
//观察者NameObserver主要用来对品名U?name)q行观察?br>public class NameObserver implements Observer{ private String name=null; public void update(Observable obj,Object arg){ name=(String)arg; } } } //观察者PriceObserver主要用来对品h(hun)?price)q行观察?br>public class PriceObserver implements Observer{ private float price=0; public void update(Observable obj,Object arg){ price=((Float)arg).floatValue(); } } } |
正如上面信息工程的创始hJames MartinZ息工E的概念所做定?a target=_new>c?/font>|模式(patterns)的创始h建筑师ChriSTopher Alexander?lt;模式语言Q?977?979>一书中Ҏ(gu)式的概念q行了如下描q?附注Q书名后面的q䆾代表在各个不同时期的作品Q下面Ş式同?Q?br>每一个模式描qC一个在我们周围不断重复发生的问题,以及该问题的解决Ҏ(gu)的核心。这P你就能一ơ又一ơ的使用该解x案而不必做重复力_。每个模式是׃部分l成的一个规则,q个规则描述特定环境、问题和解决Ҏ(gu)之间的关pR简单的_没有一个模式是独立的实体,每个模式都存在着怺支持Q但支持的程度不同:大的模式可以内嵌的模式Q同{层ơ的模式q列存在Q而小的模式被嵌入到大的模式之中?
--- Christopher Alexander
模式的概念在软g行业被采用以后,得到的广泛的发展Q现在已l存在许多种cd的模式应用,其中比较有名的箸作有Q?a target=_new>GoF(Erich GAmma、Richard Helm、Ralph Johnson和John VlissIDEs四hQ简UͼGang of Four[GoF])?lt;设计模式Q?995>QMartin Fowler?lt;分析模式Q?997>QFrank Buschmann{h?lt;体系l构模式Q?996?000>、Jim O.Coplien、Niel Harrison{h?lt;~程模式Q?995?996?998?999>和Deepak Alur{h?lt;J2EE核心模式Q?001>{,其中最具媄响的是GoF?lt;设计模式>一书,书中详细讨论了三U类型,?3U模式。好的设计源于工作中l验的积累,当设计用标准的模板以模式的方式q行交流Ӟ模式成了交和重用的强大机Ӟq且可以改善设计和开发Y件的方式。模式可以帮助我们在一个特定的环境里整理ƈ记录已知的可重现的问题及解决Ҏ(gu)Qƈ且通过模式来与他h交流q些知识Q这些模式可以解军_不同环境中重复出现的问题。模式可以设计重复使用Q重复用已知的解决Ҏ(gu)可以~短设计和开发应用的周期Q有效的使用模式Q可以我们q离重复投资的怪圈。模式的关键在于单性和可重现性?br> 举一个模式应用的单示例。例如,在你的便携式?sh)?/font>上运行一个进E中?a target=_new>对象Qƈ且这些对象需要和q行在另一q程中的别的对象通信Q也许这一q程q不在你的便携式?sh)脑上,而在别的地方。你又不惌pȝ中的对象担心如何扑֯|上的其他对象或者执?a target=_new>q程q程调用。这Ӟ可以使用代理(Proxy模式Q详见GoF?lt;设计模式>一?模式来解册个问题,你能做的事就是ؓq个q程对象在你的本地过E中建立一个代理对象,该代理对象和q程对象h相同的接口。你的本地对象利用通常处理q程中的消息发送来和代理交谈。这时代理对象负责把消息传送给实在对象Q而不实在对象位于何处?br> ׃下面要讲的Java 2q_的企业版(J2EE)应用模式中很多用C设计模式?a target=_new>重构(Refactoring)的概念,所以在此有必要再概要介l一下重构的概念。重构已l被证明可以L软g的腐朽和衰|Q关于重构方面的有名怽当然首推是Martin Fowler所写的<重构Q?999>一书了Q书中详l介l了重构的七大类型,?0余种具体的重构手法,同时也指出测试机制在重构中的重要性。书中Martin Fowler寚w构的概念q行了详l说明:
重构是对软g内部l构的一U调_目地是在不改变[软g之可察行为]的前提下Q提高其可理解性,降低其修Ҏ(gu)本。重构是一U有U律的、经q训l的、有条不紊的E序整理Ҏ(gu)Q可以将整理q程中不心引入的错误的机率降到最低,本质上说Q重构就是在代码写好之后改进它的设计。重构之前,首先查自己是否有一套可靠的试机制Q这些测试必L我检验能力?/p>
--- Martin Fowler
建立于Java~程语言和Java技术基之上的J2EEq_是最适用于企业分布式环境的应用l构Q它被设计ؓ面向多层体系的结构。J2EE包含下面关键技术:Java服务器页?Java Service PageQJSP)?a target=_new>Servlet?a target=_new>Enterprise JavaBeans(EJB)lg?a target=_new>Java消息服务(Java Message ServiceQ?a target=_new>JMS)?a target=_new>JDBC和Java命名与目录接?Java Naming and DIrECtory InterfaceQJNDI)。由于J2EEq_?a target=_new>分层pȝQ所以我们将J2EE的层ơ模型化Q这个模型得我们将职责逻辑地分C同的层中Q共分了五个层次Q客户层、表C层、业务层、集成层和资源层。因为客户层和资源层q不是J2EEq_直接x的问题,所以后面介l的15个J2EE应用模式全部属于上面五层中的中间三层Q其中表C层模式包含与Servlet和JSP技术相关的模式、业务层模式包含与EJB技术有关的模式、集成层模式包含与JMS和JDBC有关的模式。具体模式可参看下面表格Q?/p>
表一Q表C层模式
模式?/strong> | 单描q?/strong> |
截取qo?Intercepting Filter) | 促进h的预先处理和后处?/td> |
前端控制?Front Controller) | 提供h处理的集中控制器 |
视图助手(View Helper) | 把与表示层格式化无关的逻辑装到助手组?/td> |
复合视图(CompOSite View) | 从原子的子组件创Z个聚集视?/td> |
工作者服?Service To Worker) | 合ƈ分发者组件、前端控制器和视囑֊手模?/td> |
分发者视?Dispatcher View) | 合ƈ分发者组件、前端控制器和视囑֊手模式,把许多动作推q到视图处理 |
模式?/strong> | 单描q?/strong> |
业务委托(Business Delegate) | 把表C层和服务层分隔开Qƈ且提供服务的外观和代理接?/td> |
值对?Value object) | 通过减少|络对话Q以加速层之间的数据交?/td> |
会话外观(Session Facade) | 隐藏业务对象复性,集中?a target=_new>工作?/font>处理 |
复合实体(Composite Entity) | 通过把参数相关的对象分组q单个实体beanQ表C计粗_度实体bean的最好经?/td> |
值对象组装器(Value Object ASsembler) | 把来自多个数据源的值对象组装成一个复合值对?/td> |
值列表处理器(Value List Handler) | 理查询执行、结果缓册Ӏ以及结果处?/td> |
服务定位?Service Locator) | 装业务服务查找和创建的复杂性,定位业务服务工厂 |
模式?/strong> | 单描q?/strong> |
数据讉K对象(Data Access Object) | 抽象数据源,提供Ҏ(gu)据的透明讉K |
服务Ȁ发器(Service Activator) | 加速EJBlg的异步处?/td> |
׃J2EE模式众多Q篇q有限,q里只概要介l其中的一U应用模?- 集成层的数据讉K对象(DAO)模式Q有兴趣的读者可以参看下面参考文献中的资料?br>数据讉K对象模式
数据讉K对象模式
1、问?br> Ҏ(gu)数据源不同,数据讉K也不同。根据存储的cd(关系数据?/font>?a target=_new>面向对象数据库等)和供应商不同Q持久性存?比如数据?的访问差别也很大。当业务lg(如会话bean)或表C组?如助手组?需要访问某数据源时Q它们可以用合适的API来获得连接性,以及操作该数据源。但是在q些lg中包含连接性和数据讉K代码会引入这些组件及数据源实C间的紧密耦合。组件中q类代码依赖性应用E序从某U数据源q移到其它种cȝ数据源将变得非常ȝ和困难,当数据源变化Ӟlg也需要改变,以便于能够处理新cd的数据源?/p>
2、解x?br> 使用数据讉K对象(DAO)来抽象和装所有对数据源的讉K。DAO理着与数据源的连接以便于索和存储数据QDAO实现了用来操作数据源的访问机制。依赖于DAO的业务组件ؓ?a target=_new>客户?/font>使用DAO提供了更单的接口QDAO完全向客L隐藏了数据源实现l节。由于当低层数据源实现变化时QDAO向客L提供的接口不会变化,所以该模式允许DAO调整C同的存储模式Q而不会媄响其客户端或业务lg。重要的是,DAO充当lg和数据源之间的适配器?/p>
3、实现策?br> 通过调整抽象工厂(Abstract Factory)模式和工厂方?Factory MethodQ这二个创徏型模式的实现详情可参看GoF?lt;设计模式>一?模式QDAO模式可以辑ֈ很高的灵zd?
当低层存储不会随着实现变化而变化时Q可以用工厂方法模式来实现该策略,以生应用程序需要的大量DAOQ如下面cd1所C?
当低层存储随着实现的变化而变化时Q策略可以通过使用抽象工厂模式而实现。抽象工厂可以基于工厂方法实现而创建,q可使用工厂Ҏ(gu)实现Q该{略提供一个DAO的抽象工厂对象,其中该对象可以构造多U类型的具体的DAO工厂Q每个工厂支持一U不同类型的持久性存储实现。一旦你获取某特定实现的具体DAO工厂Q你可以使用它来生成该实C所支持和实现的DAOQ如下面cd2所C?
4、应?br> 当数据访问代码被直接嵌入到有其他不相兌责的某类中时Q就会修改变的十分困难。这时可以采用分L据访问代码的解决Ҏ(gu)Q将数据讉K代码抽取C个新cMQƈ且把该新c逻辑或者物理地Ud到离数据源比较近的位|,q样可以增强模块性和可重用性,如下面图3所C。具体作法可以用提炼类(Extract ClassQ一U重构手法,l节可参看Martin?lt;重构>一?Ҏ(gu)创徏一个新c,q将原来cM把数据访问代码移动到q个新的数据讉K对象(DAO)c,使用q个新的DAO对象从控制器cM讉K数据?br> CZQ持久性逻辑被嵌入到一个用新DAO对象理的持久性的某企业新DAO对象中,把持久性代码和该企业新DAO对象代码l合h会创q、紧密耦合的代码。当持久性代码是该企业新DAO对象的一部分Ӟ对该持久性存储的M改动都要求更改该新DAO对象的持久性代码。这U耦合对企业新DAO对象代码l护会带来负面的影响。下面图4用分L据访问对象方法对其进行重构改q后的结果?/p>
?5个J2EE模式中,每个模式都作用于设计模式和构架模式之间的某些斚w。每个模式不是孤立存在的Q需要其它模式的支持才能更加体现其含义和用处Qؓ了最大限度的用好模式Q还需要充分理解模式之间的关系?
参考文?
pȝ分析员教E?--- |晓沛等?
设计模式Q可复用面向对象软g的元?--- 李英军等?
重构-改善既有代码的设?--- 侯捷{译
J2EE核心模式 --- 牛志奇等?
UML_a(W二? --- 徐家译
|