下面是作者对设计模式的理解ƈ自以为所对应的实?br>一 Q?单例模式(Singleton)
账本c:1 单一实例 2 l多个对象共?3 自己创徏。网计数器
二:{略模式(Strategy)
使用QQ泡MM时用外?nbsp; 客户?QME 抽象c: 外挂 具体Q策略(囄Q笑话,名h名言Q?br>图书销售算法(不同书本折扣的算法)
三:原型模式(Prototype)
复印技术: 1 不是同一个对?2 属同c?
短消息(转发Q?1-n个MM
四:门面模式(Façade)
Facade典型应用是数据库JDBC的应用和Session的应?br>ME---àMM---à(father,mum,sister,brother)
五:备忘录模?Memento)
备䆾pȝ时?
GHOST
?Q?命o模式QCommandQ?br>
MMQ客LQ?-àMEQ请求者)--à命o角色--àQ具体命令)-à代理处(接收者)--àMM
上网 IE 输入 http地址 发送命?br>
七: 解释?Interpreter)
~译原理之编译器
文言文注释:一D|a文,它译成白话文
八:调停者模?Mediator)
法院和原告,被告的关p?br>九:责Q链模?CHAIN OF RESPONSIBLEITY)
喝酒旉过成语接龙军_谁喝?马到成功Q功不可没-没完没了)
十:工厂模式QFactoryQ?br>
水果园—〉(葡萄园,Ҏ园)--〉(葡萄Q苹果)Q各自生产)
十一Q抽象工厂模式(Abstract FactoryQ?br>
奛_造h---〉(_阻I--〉(人,兽)----〉(男hQ女人,公兽Q母兽)(人和兽属于不同的产品c?
十二Q徏造模式(BuilderQ?br>
汽R刉?br>
十三Q合成模式(CompositeQ?br>
windows的目录树Q文件系l)
十四Q装饰模式(DECORATORQ?br>
在visio中文件可以用背景进行装?br>变废为宝
十五Q设计模式之Adapter(适配?
充电器(手机?20V电压Q?br>jdbc-odbc?br>十六Q桥梁模式(BridgeQ?br>
jdbc驱动E序
十七Q代理模式(ProxyQ?br>
用代理服务器q接出网
销售代理(厂商Q律师代理(客户Q?br>foxmail
枪手
十八Qn元模式(FlyweightQ?br>
字体?6个字母和各自的斜体等
十九Q状态模式(StateQ?br>
人心情不同时表现不同有不同的行ؓ
~钟
dlogin logout
二十Q观察者模式(ObserverQ?br>
公司邮gpȝeveryone@sina.com的应用。当公司员工向这个邮发邮g时会发给公司的每一个员工。如果设|了Outlook则会及时收到通知?br>接收到短消息
二十一Q模板方法模式(TemplateQ?br>
使用|页设计时用的模板架构|页Q骨Ӟ 法的各个逻辑pȝ
二十二:讉K者模式(VisitorQ?br>
电脑销售系l: 讉K者(自己Q?--〉电脑配|系l(LQCPUQ内存。。。。。。)
二十三:q代子模式(IteratorQ?br>
查询数据库,q回l果集(mapQ?listQ?setQ?br>
下面的参考文献是MW记的全部参考文献。这里不一定用到的?br>参考文献:
http://blog.csdn.net/airhand/
http://blog.csdn.net/bloom121/
http://blog.csdn.net/laurecn/
http://blog.csdn.net/legendinfo/
http://www-128.ibm.com/developerworks/cn/java/l-struts1-1/
《Design Patterns?br>《Java与模式?br>《设计模式:可复用面向对象Y件的基础?/p>
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1227902
Jive是一个开攄Java源代码项目。其目标是徏设一个开攄构的Q强壮的Q易于扩展的ZJSP的论坛。在其设计目标的指导下,其结构设计得非常得好Q融合了很多新的观念Q比如Design PatternQ可更换的SkinQ可插入Plug{等。详l解d源代码对于理解这些新的设计上的概忉|很有裨益的。如果你对Design Pattern和Java语言有一定的了解Q但是还是会时常qh于其中的话,不妨研究研究Jive源代码,一定会对其中的很多概念有更深入的理解。这文章源于我的Jive源代码研I笔讎ͼ希望能够提纲挈领Q带领大家进入到q个好的世界。当Ӟ如果没有旉仔细地看源代码的话,看看q篇文章Q我想也是会有一些帮助的?/p>
再开始之前,需要指出的是,Jive中对Design Pattern的应用,q没有拘CgGOF书中所l出的实现方法,而是有许多变通的地方。一斚wQ我x׃具体的实际需要,另一斚wQ我惌也是设计观念q化的结果吧。因而,q些变通的地方Q将是我讲解的重炏V?/p>
Z一个OO的设计原则:面向接口~程Q而不是针对实现编E。Jive在设计的时候,把其大部分的基本对象都设计ؓ接口或者抽象类。在Jive中,基本的接口有ForumQForumMessageQForumThreadQGroupQUserQAuthorization和Query。我们可以很Ҏ的从q些接口的名字来知道他们的功用,下面的类囄Zq些cM间的一些静态关p:
你可能会有疑问,Z么会都是接口呢?q是Z扩展性考虑的。在Jivel出的实CQ所有的q些接口QForumQForumMessageQUser{等Q都使用数据库来实现的,一条消息,或者一个用户对应于数据库中的一条消息Jive使用了DbForumQDbForumMessageQDbUser{类来实现这些接口,通过JDBC来操作数据库Q之作坛的底层支撑?/p>
然而,有时候,或许我们q不想用数据库Q比如我们想只是使用文gpȝ来作坛的底层支撑Q这时候,我们需要做的只是编码实CForum{等接口的诸如FileFroumQFileForumMessage{对象,然后嵌入Jive中即可,原有的Q何代码都可以不用改变Q!Q这是面向接口~程的威力了Q?/p>
下面来看看具体的设计和编码?br>
如果要实现较好的可扩展性,AbstractFactory模式实是一件利器。如上面所_如果要创建的Forum接口的不同实玎ͼ而又不想更改代码的话Q就需要用到抽象工厂了。再Jive中,AuthorizationFactorycL一个抽象类Q用来创建Authorization对象。这是一个抽象工厂,可以通过不同的子cL创徏不同的Authorization对象。这个工厂的实现Ҏ是:
在AuthorizationFactory中用一个private static变量factoryQ用来引用具体的抽象工厂的实例: private static AuthorizationFactory factory = null;
用一个private static的StringQ来指明具体的抽象工厂的子类cdQ?private static String className ="com.coolservlets.forum.database.DbAuthorizationFactory";
然后是用一个private static的loadAuthorizationFactoryҎ来给q个factory变量赋|生成具体的抽象工厂类Q?br>
private static void loadAuthorizationFactory() { if (factory == null) { synchronized(className) { if (factory == null) { String classNameProp = PropertyManager.getProperty( "AuthorizationFactory.className" ); if (classNameProp != null) { className = classNameProp; } try { Class c = Class.forName(className); factory = (AuthorizationFactory)c.newInstance(); } catch (Exception e) { System.err.println("Exception loading class: " + e); e.printStackTrace(); } } } } } |
在static的getAuthorizationҎq回一个Authorization的过E中Q先初始化工厂类factory变量Q然后用factory的createAuthorizationҎ来创建:
public static Authorization getAuthorization(String username, String password) throws UnauthorizedException { loadAuthorizationFactory(); return factory.createAuthorization(username, password); } |
不同的子cL不同的createAuthorizationҎ的实现。比如在DbAuthorizationFactoryq个AuthorizationFactory的数据库实现子类中,createAuthorizationҎ是这样实现的Q?/p>
public Authorization createAuthorization(String username, String password) throws UnauthorizedException { if (username == null || password == null) { throw new UnauthorizedException(); } password = StringUtils.hash(password); int userID = 0; Connection con = null; PreparedStatement pstmt = null; try { con = DbConnectionManager.getConnection(); pstmt = con.prepareStatement(AUTHORIZE); pstmt.setString(1, username); pstmt.setString(2, password); ResultSet rs = pstmt.executeQuery(); if (!rs.next()) { throw new UnauthorizedException(); } userID = rs.getInt(1); } catch( SQLException sqle ) { System.err.println("Exception in DbAuthorizationFactory:" + sqle); sqle.printStackTrace(); throw new UnauthorizedException(); } finally { try { pstmt.close(); } catch (Exception e) { e.printStackTrace(); } try { con.close(); } catch (Exception e) { e.printStackTrace(); } } return new DbAuthorization(userID); } |
在这个类中,可以看到抽象cd具体的子cM间的关系Q它们是如何协作的,又是如何划分抽象Ҏ和非抽象Ҏ的,q都是值得注意的地斏V一般的Q抽象方法需要子cL实现Q而抽象类中的非抽象方法应该所有子cL能够׃n的,或者可是说Q是定义在抽象方法之上的较高层的Ҏ。这实是一个抽象工厂的好例子!虽然实现的方法已l和GOF中给出的实现相差较远了,但思想没变Q这儿的实现Q也实是要巧妙的些?/p>
q有是静态方法的使用Q得这个类看v来有些Singleton的意呟뀂这使得对于AbstractFactory的创建变得简单?/p>
下面的类囄Zq个AbstractFactory的实现的M情况Q?/p>
?QAbstractFactory模式的实现类?/strong>
在AuthorizationFactory中定义的其它ҎQ涉及到具体的如何创建AuthorizationQ都是作为abstractҎ出现Q具体实现留l子cL完成?/p>
q样Q在需要生成一个Authorization的时候,只需要调用AuthorizationFactory的静态方法getAuthorization可以了Q由子类实现了具体的l节?/p>
其它的,如同上面讲到的,在创建Forum的时候用的ForumFactoryQ具有同上面一L实现Q这是模式之所以称为模式的所在了?/p>
![]() ![]() |
![]()
|
Proxy模式的功能有很多Q比如远E代理,用来l远E对象提供一个本C表;虚代理,用来为创建开大开销的对象提供缓Ԍ{等。在Jive中用的是保护代理,保护的对象提供权限控制?/p>
我们都知道在一个论坛中Q权限的控制是必ȝQ否则论坛就很可能会被搞得一团糟。Jive中引入Proxy对象QAuthorization接口以及权限描叙属类来提供对论坛的保护?/p>
以ForumFactoryZQ一个额外的ForumFactoryProxy来处理权限认证的工作Q它为某一个ForumFactory提供了一个代理,保证只有授权的用h能够存取ForumFactory的某些操作。实际上ForumFactory在这儿不仅仅只是一个生成Forum的类的,它更像是一个Forum的管理类。提供了dQ删除,枚D{等一pd的功能,而有些功能不是什么样的h都可以用的Q因而引入了另外的一个代理类来处理权限的问题?/p>
当然Q代理类需要承ForumFactoryQ以使方法签名一_ ForumFactoryProxy extends ForumFactory
在它的构造方法中Q就提供了一个ForumFactory对象Q这是需要被代理的对象;一个Authorization对象Q提供用户信息;q有一个ForumPermissionsQ提供认证信息:
public ForumFactoryProxy(ForumFactory factory, Authorization authorization, ForumPermissions permissions) { this.factory = factory; this.authorization = authorization; this.permissions = permissions; } |
一般的代理q程都是q样的,在访问某个方法之前,必须接受权限的检查,以createForumZQ?/p>
public Forum createForum(String name, String description) throws UnauthorizedException, ForumAlreadyExistsException { if (permissions.get(ForumPermissions.SYSTEM_ADMIN)) { Forum newForum = factory.createForum(name, description); return new ForumProxy(newForum, authorization, permissions); } else { throw new UnauthorizedException(); } } |
下面l出q个模式的类图:
q个模式的实现基本上和GOF中所l出的实C致。在Jive中,几乎所有的接口QForumQForumMessageQForumThread{等Q都会有一个相应的Proxy对象来进行权限控制。而在创徏具体的对象的时候,都是用相应的Proxy对象来代替原有的对象q回的。例如在ForumFactory的getInstance()Ҏ中需要返回一个Forum的时候,Jive是这样做的:
public static ForumFactory getInstance(Authorization authorization) { ...... ForumFactoryProxy proxy = new ForumFactoryProxy(factory,authorization, factory.getPermissions(authorization)); return proxy; } |
因而,所有被创徏的对象实际上都是Proxy对象Q抽象工厂保证了没有权限验证的对象根本不会客h得到Q它们只会在Proxy的内部扮演角Ԍ而永q不会被外部对象所存取Q这P׃Ҏ上保证了论坛的安全?/p>
![]() ![]() |
![]()
|
一般的在OO设计中,而外功能的添加是通过l承来实现的Q但是承有的时候不够灵z,而且当功能的l合很多的时候,l承的子cd会成几何U数增长Q得类多的难以控制。正是基于这L考虑QDecorator模式得以诞生?/p>
Decorator模式相当于封装了某个特定的操作,当某个对象需要这个操作的时候,加上q个Decorator卛_。ƈ且,多个Decoratorq可以组合,以提供更多的功能?/p>
在Jive中,Decorator模式应用在一些过滤器QFilterQ中。Filter提供对ForumMessage对象内容的重新构造。比如,当一个ForumMessage对象过一个名为FilterCodeHighlight的过滤器后,存在于消息中的所有Java源代码文本,会被重新构造ؓh语法高亮昄的消息。在比如Q当l过了语法高亮修饰的消息再流q一个名为FilterHtml的过滤器后,消息中的HTML片断会被注释可以在HTML内部昄文本Q这样就防止了用戯入了HTML控制标签后,使得面昄不正常的问题?/p>
Jive中,所有的qo器承于一个抽象类ForumMessageFilterQ而ForumMessageFilter又实CForumMessage接口。也是_每一个过滤器实际上也是一个ForumMessage对象?/p>
ForumMessageFilter中还装一个ForumMessage对象。进行过滤的Ҏ很简单,使用的是getBody()Q比如在FilterCodeHighlightq个cMQ?/p>
public String getBody() { return highlightCode(message.getBody()); } |
highlightCode是一个privateҎQ实施具体的qo的细节。getBody()Ҏ实际上是定义在ForumMessage接口中的Q当调用qo器的getBody()ҎӞp够得到结构重整后的ForumMessage对象了。这个对象可以被其他客户引用Q也可以在传递给另外的过滤器Q实施进一步的操作?/p>
在实C个具体的消息的过滤的时候,在Forum中有addForumMessageFilter()QapplyFilters()ҎQ用来实现对qo器的应用?/p>
对一个ForumQ用addForumMessageFilter()Ҏd一个Filter的时候,q没有指定一个具体的MessageQ而只是一个规则(Filter中封装了qo规则Q,然后applyFilter()Ҏ中,实施q些规则Q?/p>
public ForumMessage applyFilters(ForumMessage message) { //Loop through filters and apply them for (int i=0; i < filters.length; i++) { message = filters[i].clone(message); } return message; } |
qo器的clone()ҎQؓqo器复制消息体。这个方法的使用Q分M在过滤器中对于消息体和过滤规则的初始化过E,q也是一个值得借鉴的技巧!
下面l出Decorator模式的类?
我们可以看到Decorator模式实际上和Proxy模式是很相近的,但是它们代表两个不同的功能含义。Proxy模式提供一个对象的控制Q而Decorator模式则是为对象提供额外的功能?br>
Iterator模式和论坛的览erator模式用来分离数据l构和遍历算法,降低两者之间的耦合度,以得同一个数据结构用不同的算法遍历时Q仍能够h相同的接口,另一斚wQIterator模式使得当改换遍历算法后Q不需要更改程序的代码?/p>
在Java的JDK中本w就定义有一个Iterator接口Q在Iterator接口中仅仅定义了三个ҎQhasNext()判断是否遍历完最后一个元素,next()Ҏq回要遍历的数据l构中一个对象,remove()则删除当前对象。Jive中用IteratorProxy抽象cȝ承了q一接口。这儿Proxy的含义和上面一P也就是说Q这个IteratorProxyZ会实现Iterator的遍历功能外Q还会有代理权限控制的功能?/p>
对于论坛中的基本对象ForumQForumThreadQForumMessageQGroupQUser都有相应的遍历器。比如对应于Forum接口有ForumIteratorProxy对象。这个ForumIteratorProxy遍历器就相当于一个封装了一pdForum对象的集合类Q通过定义好的接口hasNext()和next()可以方便的遍历这个集合,而ƈ不需要知道是如何遍历q个集合的。遍历的法可能很简单,也可能很复杂Q但是对于外部的客户而言Q这q没有Q何的区别?/p>
而对于论坛中具体的遍历方法,q取决于具体的实玎ͼ在Jive中给出的是数据库的实现?/p>
我们׃MessageIteratorProxyZQ来讲解Iterator模式的用法?/p>
DbThreadIterator对象实现了Iterator接口Q是对于一个Thread中所有Message的遍历器Q我们来看看它是如何实现的?/p>
hasNext()判断在这个Thread中是不是q有下一条MessageQ?/p>
public boolean hasNext() { if (currentIndex+1 >= messages.length) { return false; } return true; } |
next()Ҏ从数据库中取Z在这个Thread中的下一条MessageQ?/p>
public Object next() throws java.util.NoSuchElementException { ForumMessage message = null; if (nextMessage != null) { message = nextMessage; nextMessage = null; } else { message = getNextMessage(); if (message == null) { throw new java.util.NoSuchElementException(); } } return message; } |
q样Q通过Ҏ据库的操作,DbThreadIterator实现了对一个Thread中所有Message遍历的方法?/p>
再ForumThread接口中有messages()ҎQ返回在q个Thread中的所有Message的一个遍历器QIteratorQ,实际上也是q回了一个Message的集合: public Iterator messages();
在DbForumThread中实Cq个ҎQ?public Iterator messages() {return new DbThreadIterator(this);}
从DbForumThread的messages()Ҏ中所q回的就是这个Thread中所有Message的一个遍历器Q通过q个遍历器,我们可以访问Thread中的所有的Message了。当Ӟ事情q没有完Q由于权限的问题Q我们还需要构造这个遍历器的Proxy对象Q然后通过q个Proxy对象来访问遍历器?/p>
下面的类囄Z在Jive中Iterator模式的实现方法:
在Jive中,因ؓ在一个Thread之下QMessage是按树Şl构l织的,因而,当需要层U表CZ个Thread中的Message之间的关pȝ时候,仅仅用上面讲到的U性的Iterator是不够的。这时候,对Iterator的概念进行推q,引入了TreeWalker接口?/p>
思义QTreeWalker提供了遍历一个树和存取树上节点的ҎQ?/p>
public interface TreeWalker { public ForumMessage getRoot(); public ForumMessage getChild(ForumMessage parent, int index); public int getChildCount(ForumMessage parent); public int getRecursiveChildCount(ForumMessage parent); public int getIndexOfChild(ForumMessage parent, ForumMessage child); public boolean isLeaf(ForumMessage node); |
TreeWalker只是Iterator的简单推q,q没有Iterator应用的那么广泛,而且Q也可以很容易的在TreeWalker上面在套一层Iterator的借口Q让它在某些情况下行使Iterator的职责。这儿就不再多讨Z?/p>
再此QJive设计中所有涉及到的设计模式的地方Q基本上都讲完了Q看完了之后Q是不是对设计模式有了更q一步的了解了呢Q?/p>
下一部分的内容,会涉及到具体的~码Q深入到JSP的内部,我们会看到Jive中是如何实现可更换的Skin的,q会涉及Tag Library的一些内宏V好了,q次到q儿了。下ơ再见?/p>