﻿<?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-ALL  ABOUT JAVA-随笔分类-JAVA 设计模式</title><link>http://www.blogjava.net/wdlfellow/category/21234.html</link><description>JAVA 技术</description><language>zh-cn</language><lastBuildDate>Tue, 17 Apr 2007 07:19:10 GMT</lastBuildDate><pubDate>Tue, 17 Apr 2007 07:19:10 GMT</pubDate><ttl>60</ttl><item><title>23种设计模式及其对应实例-转</title><link>http://www.blogjava.net/wdlfellow/archive/2007/04/17/111320.html</link><dc:creator>泡面</dc:creator><author>泡面</author><pubDate>Tue, 17 Apr 2007 07:15:00 GMT</pubDate><guid>http://www.blogjava.net/wdlfellow/archive/2007/04/17/111320.html</guid><wfw:comment>http://www.blogjava.net/wdlfellow/comments/111320.html</wfw:comment><comments>http://www.blogjava.net/wdlfellow/archive/2007/04/17/111320.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wdlfellow/comments/commentRss/111320.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wdlfellow/services/trackbacks/111320.html</trackback:ping><description><![CDATA[<p>－转载</p>
<p>下面是作者对设计模式的理解并自以为所对应的实例<br>一 ： 单例模式(Singleton)<br>&nbsp;<br>账本类：1 单一实例 2 给多个对象共享 3 自己创建。网页计数器 <br>&nbsp;&nbsp; <br>二：策略模式(Strategy)&nbsp; <br>&nbsp;<br>使用QQ泡MM时使用外挂&nbsp; 客户端 ：ME 抽象类： 外挂 具体：策略（图片，笑话，名人名言）<br>图书销售算法（不同书本折扣的算法）<br>&nbsp;<br>三：原型模式(Prototype)<br>&nbsp;<br>复印技术： 1 不是同一个对象 2 属同类 <br>短消息（转发） 1-n个MM<br>&nbsp;<br>四：门面模式(Fa&#231;ade)<br>&nbsp;<br>Facade典型应用就是数据库JDBC的应用和Session的应用<br>ME---&#224;MM---&#224;(father,mum,sister,brother)<br>&nbsp;<br>五：备忘录模式(Memento)<br>&nbsp;<br>备份系统时使用 <br>GHOST</p>
<p>六 ： 命令模式（Command）<br>&nbsp;<br>MM（客户端）--&#224;ME（请求者）--&#224;命令角色--&#224;（具体命令）-&#224;代理处（接收者）--&#224;MM<br>上网 IE 输入 http地址 发送命令<br>&nbsp;<br>七： 解释器(Interpreter)<br>&nbsp;<br>编译原理之编译器<br>文言文注释：一段文言文，将它翻译成白话文<br>八：调停者模式(Mediator)<br>&nbsp;<br>法院和原告，被告的关系<br>九：责任链模式(CHAIN OF RESPONSIBLEITY)<br>&nbsp;<br>喝酒时通过成语接龙决定谁喝酒(马到成功－功不可没－没完没了)<br>十：工厂模式（Factory）<br>&nbsp;<br>水果园—〉（葡萄园，苹果园）--〉（葡萄，苹果）（各自生产）<br>十一：抽象工厂模式（Abstract Factory）<br>&nbsp;<br>女娲造人---〉（阴，阳）--〉（人，兽）----〉（男人，女人，公兽，母兽）(人和兽属于不同的产品类)<br>&nbsp;<br>十二：建造模式（Builder）<br>&nbsp;<br>汽车制造<br>&nbsp;<br>十三：合成模式（Composite）<br>&nbsp;<br>windows的目录树（文件系统）<br>&nbsp;<br>十四：装饰模式（DECORATOR）<br>&nbsp;<br>在visio中文件可以使用背景进行装饰<br>变废为宝<br>十五：设计模式之Adapter(适配器)<br>&nbsp;<br>充电器（手机和220V电压）<br>jdbc-odbc桥<br>十六：桥梁模式（Bridge）<br>&nbsp;<br>jdbc驱动程序<br>&nbsp;<br>十七：代理模式（Proxy）<br>&nbsp;<br>用代理服务器连接出网<br>销售代理（厂商）律师代理（客户）<br>foxmail<br>枪手<br>&nbsp;<br>十八：享元模式（Flyweight）<br>&nbsp;<br>字体的26个字母和各自的斜体等<br>&nbsp;<br>十九：状态模式（State）<br>&nbsp;<br>人心情不同时表现不同有不同的行为<br>编钟<br>登录login logout<br>&nbsp;<br>二十：观察者模式（Observer）<br>&nbsp;<br>公司邮件系统<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#101;&#118;&#101;&#114;&#121;&#111;&#110;&#101;&#64;&#115;&#105;&#110;&#97;&#46;&#99;&#111;&#109;">everyone@sina.com</a>的应用。当公司员工向这个邮箱发邮件时会发给公司的每一个员工。如果设置了Outlook则会及时收到通知。<br>接收到短消息<br>&nbsp;<br>二十一：模板方法模式（Template）<br>&nbsp;<br>使用网页设计时使用的模板架构网页（骨架） 算法的各个逻辑系统<br>&nbsp;<br>二十二：访问者模式（Visitor）<br>&nbsp;<br>电脑销售系统： 访问者（自己）---〉电脑配置系统（主板，CPU，内存。。。。。。）<br>&nbsp;<br>二十三：迭代子模式（Iterator）<br>&nbsp;<br>查询数据库，返回结果集（map， list， set）<br>&nbsp;<br>下面的参考文献是读书笔记的全部参考文献。这里不一定用到的。<br>参考文献：<br><a href="http://blog.csdn.net/airhand/">http://blog.csdn.net/airhand/</a><br><a href="http://blog.csdn.net/bloom121/">http://blog.csdn.net/bloom121/</a><br><a href="http://blog.csdn.net/laurecn/">http://blog.csdn.net/laurecn/</a><br><a href="http://blog.csdn.net/legendinfo/">http://blog.csdn.net/legendinfo/</a><br><a href="http://www-128.ibm.com/developerworks/cn/java/l-struts1-1/">http://www-128.ibm.com/developerworks/cn/java/l-struts1-1/</a><br>《Design Patterns》<br>《Java与模式》<br>《设计模式：可复用面向对象软件的基础》</p>
<p>&nbsp;</p>
<p>Trackback: <a href="http://tb.blog.csdn.net/TrackBack.aspx?PostId=1227902">http://tb.blog.csdn.net/TrackBack.aspx?PostId=1227902</a></p>
<img src ="http://www.blogjava.net/wdlfellow/aggbug/111320.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wdlfellow/" target="_blank">泡面</a> 2007-04-17 15:15 <a href="http://www.blogjava.net/wdlfellow/archive/2007/04/17/111320.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jive 源码研究与设计模式－转</title><link>http://www.blogjava.net/wdlfellow/archive/2007/04/14/110625.html</link><dc:creator>泡面</dc:creator><author>泡面</author><pubDate>Sat, 14 Apr 2007 04:46:00 GMT</pubDate><guid>http://www.blogjava.net/wdlfellow/archive/2007/04/14/110625.html</guid><wfw:comment>http://www.blogjava.net/wdlfellow/comments/110625.html</wfw:comment><comments>http://www.blogjava.net/wdlfellow/archive/2007/04/14/110625.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wdlfellow/comments/commentRss/110625.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wdlfellow/services/trackbacks/110625.html</trackback:ping><description><![CDATA[转自 IBM 刘武东，谢谢作者的辛勤劳动！<br><br>
<p><a name=1><span class=atitle>前言</span></a></p>
<p>Jive是一个开放的Java源代码项目。其目标是建设一个开放结构的，强壮的，易于扩展的基于JSP的论坛。在其设计目标的指导下，其结构设计得非常得好，融合了很多新的观念，比如Design Pattern，可更换的Skin，可插入Plug等等。详细解读其源代码对于理解这些新的设计上的概念是很有裨益的。如果你对Design Pattern和Java语言有一定的了解，但是还是会时常迷惑于其中的话，不妨研究研究Jive源代码，一定会对其中的很多概念有更深入的理解。这篇文章源于我的Jive源代码研究笔记，希望能够提纲挈领，带领大家进入到这个美好的世界。当然，如果没有时间仔细地看源代码的话，看看这篇文章，我想也是会有一些帮助的。</p>
<p>再开始之前，需要指出的是，Jive中对Design Pattern的应用，并没有拘礼与GOF书中所给出的实现方法，而是有许多变通的地方。一方面，我想是由于具体的实际需要，另一方面，我想这也是设计观念进化的结果吧。因而，这些变通的地方，将是我讲解的重点。</p>
<br>
<p><a name=2><span class=atitle>整体结构概叙</span></a></p>
<p>基于一个OO的设计原则：面向接口编程，而不是针对实现编程。Jive在设计的时候，把其大部分的基本对象都设计为接口或者抽象类。在Jive中，基本的接口有Forum，ForumMessage，ForumThread，Group，User，Authorization和Query。我们可以很容易的从这些接口的名字来知道他们的功用，下面的类图给出了这些类之间的一些静态关系：</p>
<br><br><a name=N1004F><strong>图1：Jive整体关系</strong></a><br><img height=300 alt=图1：Jive整体关系 src="http://www.ibm.com/developerworks/cn/java/l-jivesrc/fig1.gif" width=415> <br>
<p>你可能会有疑问，为什么会都是接口呢？这是基于扩展性考虑的。在Jive给出的实现中，所有的这些接口，Forum，ForumMessage，User等等，都使用数据库来实现的，一条消息，或者一个用户对应于数据库中的一条消息Jive使用了DbForum，DbForumMessage，DbUser等类来实现这些接口，通过JDBC来操作数据库，使之作为论坛的底层支撑。</p>
<p>然而，有时候，或许我们并不想使用数据库，比如我们想只是使用文件系统来作为论坛的底层支撑，这时候，我们需要做的只是编码实现了Forum等等接口的诸如FileFroum，FileForumMessage等对象，然后嵌入Jive中即可，原有的任何代码都可以不用改变！！！这就是面向接口编程的威力了！</p>
<p>下面来看看具体的设计和编码。<br><br></p>
<p><a name=3><span class=atitle>AbstractFactory模式和可扩展性</span></a></p>
<p>如果要实现较好的可扩展性，AbstractFactory模式确实是一件利器。如上面所说，如果要创建的Forum接口的不同实现，而又不想更改代码的话，就需要用到抽象工厂了。再Jive中，AuthorizationFactory类是一个抽象类，用来创建Authorization对象。这是一个抽象工厂，可以通过不同的子类来创建不同的Authorization对象。这个工厂的实现方法是：</p>
<p>在AuthorizationFactory中使用一个private static变量factory，用来引用具体的抽象工厂的实例： <br><code>private static AuthorizationFactory factory = null;</code> </p>
<p>用一个private static的String，来指明具体的抽象工厂的子类类名： <br><code>private static String className ="com.coolservlets.forum.database.DbAuthorizationFactory";</code> </p>
<p>然后是用一个private static的loadAuthorizationFactory方法来给这个factory变量赋值，生成具体的抽象工厂类：<br></p>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>   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();
            }
            }
            }
            }
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>在static的getAuthorization方法返回一个Authorization的过程中，先初始化工厂类factory变量，然后用factory的createAuthorization方法来创建：</p>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>   public static Authorization getAuthorization(String username,
            String password) throws UnauthorizedException
            {
            loadAuthorizationFactory();
            return factory.createAuthorization(username, password);
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>不同的子类有不同的createAuthorization方法的实现。比如在DbAuthorizationFactory这个AuthorizationFactory的数据库实现子类中，createAuthorization方法是这样实现的：</p>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>   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);
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>在这个类中，可以看到抽象类和具体的子类之间的关系，它们是如何协作的，又是如何划分抽象方法和非抽象方法的，这都是值得注意的地方。一般的，抽象方法需要子类来实现，而抽象类中的非抽象方法应该所有子类所能够共享的，或者可是说，是定义在抽象方法之上的较高层的方法。这确实是一个抽象工厂的好例子！虽然实现的方法已经和GOF中给出的实现相差较远了，但思想没变，这儿的实现，也确实是要巧妙的些。</p>
<p>还有就是静态方法的使用，使得这个类看起来有些Singleton的意味。这使得对于AbstractFactory的创建变得简单。</p>
<p>下面的类图给出了这个AbstractFactory的实现的总体情况：</p>
<br><br><a name=N100A0><strong>图2：AbstractFactory模式的实现类图</strong></a><br><img height=256 alt=图2：AbstractFactory模式的实现类图 src="http://www.ibm.com/developerworks/cn/java/l-jivesrc/fig2.gif" width=570> <br>
<p>在AuthorizationFactory中定义的其它方法，涉及到具体的如何创建Authorization，都是作为abstract方法出现，具体实现留给子类来完成。</p>
<p>这样，在需要生成一个Authorization的时候，只需要调用AuthorizationFactory的静态方法getAuthorization就可以了，由子类实现了具体的细节。</p>
<p>其它的，如同上面讲到的，在创建Forum的时候用的ForumFactory，具有同上面一样的实现，这就是模式之所以称为模式的所在了。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
        </tr>
    </tbody>
</table>
<table class=no-print cellSpacing=0 cellPadding=0 align=right>
    <tbody>
        <tr align=right>
            <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
            <table cellSpacing=0 cellPadding=0 border=0>
                <tbody>
                    <tr>
                        <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                        <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/java/l-jivesrc/index.html#main"><strong><font color=#996699>回页首</font></strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<p><a name=4><span class=atitle>Proxy模式和权限控制</span></a></p>
<p>Proxy模式的功能有很多，比如远程代理，用来给远程对象提供一个本地代表；虚代理，用来为创建开大开销的对象提供缓冲，等等。在Jive中使用的是保护代理，为被保护的对象提供权限控制。</p>
<p>我们都知道在一个论坛中，权限的控制是必须的，否则论坛就很可能会被搞得一团糟。Jive中引入Proxy对象，Authorization接口以及权限描叙属类来提供对论坛的保护。</p>
<p>以ForumFactory为例，一个额外的ForumFactoryProxy来处理权限认证的工作，它为某一个ForumFactory提供了一个代理，保证只有授权的用户才能够存取ForumFactory的某些操作。实际上ForumFactory在这儿不仅仅只是一个生成Forum的类的，它更像是一个Forum的管理类。提供了添加，删除，枚举等等一系列的功能，而有些功能不是什么样的人都可以使用的，因而引入了另外的一个代理类来处理权限的问题。</p>
<p>当然，代理类需要继承ForumFactory，以使方法签名一致： <code>ForumFactoryProxy extends ForumFactory</code> </p>
<p>在它的构造方法中，就提供了一个ForumFactory对象，这是需要被代理的对象；一个Authorization对象，提供用户信息；还有一个ForumPermissions，提供认证信息：</p>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>   public ForumFactoryProxy(ForumFactory factory, Authorization authorization,
            ForumPermissions permissions)
            {
            this.factory = factory;
            this.authorization = authorization;
            this.permissions = permissions;
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>一般的代理过程都是这样的，在访问某个方法之前，必须接受权限的检查，以createForum为例：</p>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>   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();
            }
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>下面给出这个模式的类图：</p>
<br><br><a name=N100DF><strong>图3：Proxy模式的类图</strong></a><br><img height=199 alt=图3：Proxy模式的类图 src="http://www.ibm.com/developerworks/cn/java/l-jivesrc/fig3.gif" width=421> <br>
<p>这个模式的实现基本上和GOF中所给出的实现一致。在Jive中，几乎所有的接口，Forum，ForumMessage，ForumThread等等，都会有一个相应的Proxy对象来进行权限控制。而在创建具体的对象的时候，都是用相应的Proxy对象来代替原有的对象返回的。例如在ForumFactory的getInstance()方法中需要返回一个Forum的时候，Jive是这样做的：</p>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>public static ForumFactory getInstance(Authorization authorization) {
            ......
            ForumFactoryProxy proxy = new ForumFactoryProxy(factory,authorization, factory.getPermissions(authorization));
            return proxy;
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>因而，所有被创建的对象实际上都是Proxy对象，抽象工厂保证了没有权限验证的对象根本不会客户所得到，它们只会在Proxy的内部扮演角色，而永远不会被外部对象所存取，这样，就从根本上保证了论坛的安全。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
        </tr>
    </tbody>
</table>
<table class=no-print cellSpacing=0 cellPadding=0 align=right>
    <tbody>
        <tr align=right>
            <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
            <table cellSpacing=0 cellPadding=0 border=0>
                <tbody>
                    <tr>
                        <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                        <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/java/l-jivesrc/index.html#main"><strong><font color=#996699>回页首</font></strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<p><a name=5><span class=atitle>Decorator模式和过滤器</span></a></p>
<p>一般的在OO设计中，而外功能的添加是通过继承来实现的，但是继承有的时候不够灵活，而且当功能的组合很多的时候，继承的子类就会成几何级数增长，使得类多的难以控制。正是基于这样的考虑，Decorator模式得以诞生。</p>
<p>Decorator模式相当于封装了某个特定的操作，当某个对象需要这个操作的时候，加上这个Decorator即可。并且，多个Decorator还可以组合，以提供更多的功能。</p>
<p>在Jive中，Decorator模式应用在一些过滤器（Filter）中。Filter提供对ForumMessage对象内容的重新构造。比如，当一个ForumMessage对象流过一个名为FilterCodeHighlight的过滤器后，存在于消息中的所有Java源代码文本，会被重新构造为具有语法高亮显示的消息。在比如，当经过了语法高亮修饰的消息再流过一个名为FilterHtml的过滤器后，消息中的HTML片断会被注释可以在HTML内部显示文本，这样就防止了用户输入了HTML控制标签后，使得页面显示不正常的问题。</p>
<p>Jive中，所有的过滤器继承于一个抽象类ForumMessageFilter，而ForumMessageFilter又实现了ForumMessage接口。也就是说，每一个过滤器实际上也是一个ForumMessage对象。</p>
<p>ForumMessageFilter中还封装一个ForumMessage对象。进行过滤的方法很简单，使用的是getBody()，比如在FilterCodeHighlight这个类中：</p>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>   public String getBody() {
            return highlightCode(message.getBody());
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>highlightCode是一个private方法，实施具体的过滤的细节。getBody()方法实际上是定义在ForumMessage接口中的，当调用过滤器的getBody()方法时，就能够得到结构重整后的ForumMessage对象了。这个对象可以被其他客户引用，也可以在传递给另外的过滤器，实施进一步的操作。</p>
<p>在实现一个具体的消息的过滤的时候，在Forum中有addForumMessageFilter()，applyFilters()方法，用来实现对过滤器的应用。</p>
<p>对一个Forum，使用addForumMessageFilter()方法添加一个Filter的时候，并没有指定一个具体的Message，而只是一个规则（Filter中封装了过滤规则），然后applyFilter()方法中，实施这些规则：</p>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>   public ForumMessage applyFilters(ForumMessage message) {
            //Loop through filters and apply them
            for (int i=0; i &lt; filters.length; i++) {
            message = filters[i].clone(message);
            }
            return message;
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>过滤器的clone()方法，为过滤器复制消息体。这个方法的使用，分离了在过滤器中对于消息体和过滤规则的初始化过程，这也是一个值得借鉴的技巧！</p>
<p>下面给出Decorator模式的类图:</p>
<br><br><a name=N10124><strong>图4：Decorator模式的类图</strong></a><br><img height=227 alt=图4：Decorator模式的类图 src="http://www.ibm.com/developerworks/cn/java/l-jivesrc/fig4.gif" width=458> <br>
<p>我们可以看到Decorator模式实际上和Proxy模式是很相近的，但是它们代表两个不同的功能含义。Proxy模式提供一个对象的控制，而Decorator模式则是为对象提供额外的功能。<br><br></p>
<p><a name=6><span class=atitle>Iterator模式和论坛的浏览</span></a>erator模式用来分离数据结构和遍历算法，降低两者之间的耦合度，以使得同一个数据结构用不同的算法遍历时，仍能够具有相同的接口，另一方面，Iterator模式使得当改换遍历算法后，不需要更改程序的代码。</p>
<p>在Java的JDK中本身就定义有一个Iterator接口，在Iterator接口中仅仅定义了三个方法，hasNext()判断是否遍历完最后一个元素，next()方法返回要遍历的数据结构中一个对象，remove()则删除当前对象。Jive中使用IteratorProxy抽象类继承了这一接口。这儿Proxy的含义和上面一样，也就是说，这个IteratorProxy出了会实现Iterator的遍历功能外，还会有代理权限控制的功能。</p>
<p>对于论坛中的基本对象Forum，ForumThread，ForumMessage，Group，User都有相应的遍历器。比如对应于Forum接口有ForumIteratorProxy对象。这个ForumIteratorProxy遍历器就相当于一个封装了一系列Forum对象的集合类，通过定义好的接口hasNext()和next()可以方便的遍历这个集合，而并不需要知道是如何遍历这个集合的。遍历的算法可能很简单，也可能很复杂，但是对于外部的客户而言，这并没有任何的区别。</p>
<p>而对于论坛中具体的遍历方法，这取决于具体的实现，在Jive中给出的是数据库的实现。</p>
<p>我们就以MessageIteratorProxy为例，来讲解Iterator模式的用法。</p>
<p>DbThreadIterator对象实现了Iterator接口，是对于一个Thread中所有Message的遍历器，我们来看看它是如何实现的。</p>
<p>hasNext()判断在这个Thread中是不是还有下一条Message：</p>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>public boolean hasNext() {
            if (currentIndex+1 &gt;= messages.length) {
            return false;
            }
            return true;
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>next()方法从数据库中取出与在这个Thread中的下一条Message：</p>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>   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;
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>这样，通过对数据库的操作，DbThreadIterator实现了对一个Thread中所有Message遍历的方法。</p>
<p>再ForumThread接口中有messages()方法，返回在这个Thread中的所有Message的一个遍历器（Iterator），实际上也就是返回了一个Message的集合： <br><code>public Iterator messages();</code> </p>
<p>在DbForumThread中实现了这个方法： <br><code>public Iterator messages() {return new DbThreadIterator(this);}</code> </p>
<p>从DbForumThread的messages()方法中所返回的就是这个Thread中所有Message的一个遍历器，通过这个遍历器，我们就可以访问Thread中的所有的Message了。当然，事情还没有完，由于权限的问题，我们还需要构造这个遍历器的Proxy对象，然后通过这个Proxy对象来访问遍历器。</p>
<p>下面的类图给出了在Jive中Iterator模式的实现方法：</p>
<br><br><a name=N10177><strong>图5：Jive中Iterator模式的实现</strong></a><br><img height=234 alt=图5：Jive中Iterator模式的实现 src="http://www.ibm.com/developerworks/cn/java/l-jivesrc/fig5.gif" width=447> <br>
<p>在Jive中，因为在一个Thread之下，Message是按树形结构组织的，因而，当需要层级表示一个Thread中的Message之间的关系的时候，仅仅用上面讲到的线性的Iterator是不够的。这时候，对Iterator的概念进行推广，就引入了TreeWalker接口。</p>
<p>顾名思义，TreeWalker提供了遍历一个树和存取树上节点的方法：</p>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>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);</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>TreeWalker只是Iterator的简单推广，并没有Iterator应用的那么广泛，而且，也可以很容易的在TreeWalker上面在套一层Iterator的借口，让它在某些情况下行使Iterator的职责。这儿就不再多讨论了。</p>
<p>再此，Jive设计中所有涉及到的设计模式的地方，基本上都讲完了，看完了之后，是不是对设计模式有了更进一步的了解了呢？</p>
<p>下一部分的内容，将会涉及到具体的编码，深入到JSP的内部，我们将会看到Jive中是如何实现可更换的Skin的，还会涉及Tag Library的一些内容。好了，这次就到这儿了。下次再见。</p>
<img src ="http://www.blogjava.net/wdlfellow/aggbug/110625.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wdlfellow/" target="_blank">泡面</a> 2007-04-14 12:46 <a href="http://www.blogjava.net/wdlfellow/archive/2007/04/14/110625.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>