﻿<?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-混沌中立-随笔分类-about java &amp; j2ee</title><link>http://www.blogjava.net/GandofYan/category/9719.html</link><description>－－－－－－－－－仰望星空，心中只剩下一片深蓝</description><language>zh-cn</language><lastBuildDate>Sun, 22 Jun 2014 15:19:54 GMT</lastBuildDate><pubDate>Sun, 22 Jun 2014 15:19:54 GMT</pubDate><ttl>60</ttl><item><title>一个简单的Java集合范围过滤的多个方式对比</title><link>http://www.blogjava.net/GandofYan/archive/2014/06/21/415009.html</link><dc:creator>混沌中立</dc:creator><author>混沌中立</author><pubDate>Sat, 21 Jun 2014 15:33:00 GMT</pubDate><guid>http://www.blogjava.net/GandofYan/archive/2014/06/21/415009.html</guid><wfw:comment>http://www.blogjava.net/GandofYan/comments/415009.html</wfw:comment><comments>http://www.blogjava.net/GandofYan/archive/2014/06/21/415009.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/GandofYan/comments/commentRss/415009.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/GandofYan/services/trackbacks/415009.html</trackback:ping><description><![CDATA[在一个项目里面有这么一个技术需求:<br />1.集合中元素个数,10M<br />2.根据上限和下限从一个Set中过滤出满足要求的元素集合.<br /><br />实际这个是个很典型的技术要求, 之前的项目也遇见过,但是因为当时的类库不多, 都是直接手写实现的. 方式基本等同于第一个方式.<br /><br />在这个过程中, 我写了四个方式, 基本记录到下面.<br />第一个方式:对Set进行迭代器遍历, 判断每个元素是否都在上限和下限范围中.如果满足则添加到结果集合中, 最后返回结果集合.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;测试效果:集合大小100K, 运算时间 3000ms+<br />过滤部分的逻辑如下:<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;filerSet(Set&lt;BigDecimal&gt;&nbsp;targetSet,&nbsp;String&nbsp;lower,&nbsp;String&nbsp;higher)&nbsp;{<br /><span style="color: #008080; ">&nbsp;2</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;bdLower&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;BigDecimal(Double.parseDouble(lower));<br /><span style="color: #008080; ">&nbsp;3</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;bdHigher&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;BigDecimal(Double.parseDouble(higher));<br /><span style="color: #008080; ">&nbsp;4</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;5</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set&lt;BigDecimal&gt;&nbsp;returnSet&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;HashSet&lt;BigDecimal&gt;();<br /><span style="color: #008080; ">&nbsp;6</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(BigDecimal&nbsp;object&nbsp;:&nbsp;targetSet)&nbsp;{<br /><span style="color: #008080; ">&nbsp;7</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(isInRange(object,&nbsp;bdLower,&nbsp;bdHigher))&nbsp;{<br /><span style="color: #008080; ">&nbsp;8</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;returnSet.add(object);<br /><span style="color: #008080; ">&nbsp;9</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">10</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">11</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">12</span>&nbsp;<br /><span style="color: #008080; ">13</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;isInRange(BigDecimal&nbsp;object,&nbsp;BigDecimal&nbsp;bdLower,<br /><span style="color: #008080; ">14</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;bdHigher)&nbsp;{<br /><span style="color: #008080; ">15</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;object.compareTo(bdLower)&nbsp;&gt;=&nbsp;0<br /><span style="color: #008080; ">16</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;object.compareTo(bdHigher)&nbsp;&lt;=&nbsp;0;<br /><span style="color: #008080; ">17</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div>第二个方式: 借助TreeSet, 原始集合进行排序, 然后直接subset.<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 测试效果: 集合大小10M, 运算时间: 12000ms+(获得TreeSet) , 200ms(获得结果)<br />过滤部分的逻辑如下(非常繁琐):<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp; 1</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set&lt;BigDecimal&gt;&nbsp;getSubSet(TreeSet&lt;BigDecimal&gt;&nbsp;targetSet,&nbsp;String&nbsp;lower,<br /><span style="color: #008080; ">&nbsp;&nbsp;2</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;higher)&nbsp;{<br /><span style="color: #008080; ">&nbsp;&nbsp;3</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;&nbsp;4</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;bdLower&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;BigDecimal(Double.parseDouble(lower));<br /><span style="color: #008080; ">&nbsp;&nbsp;5</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;bdHigher&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;BigDecimal(Double.parseDouble(higher));<br /><span style="color: #008080; ">&nbsp;&nbsp;6</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;&nbsp;7</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;((bdHigher.compareTo(targetSet.first())&nbsp;==&nbsp;-1)<br /><span style="color: #008080; ">&nbsp;&nbsp;8</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;||&nbsp;(bdLower.compareTo(targetSet.last())&nbsp;==&nbsp;1))&nbsp;{<br /><span style="color: #008080; ">&nbsp;&nbsp;9</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; ">&nbsp;10</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;11</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;12</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;hasLower&nbsp;=&nbsp;targetSet.contains(bdLower);<br /><span style="color: #008080; ">&nbsp;13</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;hasHigher&nbsp;=&nbsp;targetSet.contains(bdHigher);<br /><span style="color: #008080; ">&nbsp;14</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(hasLower)&nbsp;{<br /><span style="color: #008080; ">&nbsp;15</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(hasHigher)&nbsp;{<br /><span style="color: #008080; ">&nbsp;16</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("get&nbsp;start:"&nbsp;+&nbsp;bdLower);<br /><span style="color: #008080; ">&nbsp;17</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("get&nbsp;end:"&nbsp;+&nbsp;bdHigher);<br /><span style="color: #008080; ">&nbsp;18</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;targetSet.subSet(bdLower,&nbsp;<span style="color: #0000FF; ">true</span>,&nbsp;bdHigher,&nbsp;<span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; ">&nbsp;19</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;20</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;newEnd&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; ">&nbsp;21</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("get&nbsp;start:"&nbsp;+&nbsp;bdLower);<br /><span style="color: #008080; ">&nbsp;22</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortedSet&lt;BigDecimal&gt;&nbsp;returnSet&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; ">&nbsp;23</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(bdHigher.compareTo(targetSet.last())&nbsp;!=&nbsp;-1)&nbsp;{<br /><span style="color: #008080; ">&nbsp;24</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newEnd&nbsp;=&nbsp;targetSet.last();<br /><span style="color: #008080; ">&nbsp;25</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;26</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortedSet&lt;BigDecimal&gt;&nbsp;newTargetSet&nbsp;=&nbsp;targetSet<br /><span style="color: #008080; ">&nbsp;27</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.tailSet(bdLower);<br /><span style="color: #008080; ">&nbsp;28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(BigDecimal&nbsp;object&nbsp;:&nbsp;newTargetSet)&nbsp;{<br /><span style="color: #008080; ">&nbsp;29</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(object.compareTo(bdHigher)&nbsp;==&nbsp;1)&nbsp;{<br /><span style="color: #008080; ">&nbsp;30</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newEnd&nbsp;=&nbsp;object;<br /><span style="color: #008080; ">&nbsp;31</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span>;<br /><span style="color: #008080; ">&nbsp;32</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(object.compareTo(bdHigher)&nbsp;==&nbsp;0)&nbsp;{<br /><span style="color: #008080; ">&nbsp;33</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newEnd&nbsp;=&nbsp;object;<br /><span style="color: #008080; ">&nbsp;34</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span>;<br /><span style="color: #008080; ">&nbsp;35</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;36</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;37</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;38</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;returnSet&nbsp;=&nbsp;targetSet.subSet(bdLower,&nbsp;<span style="color: #0000FF; ">true</span>,&nbsp;newEnd,&nbsp;<span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; ">&nbsp;39</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(newEnd.compareTo(bdHigher)&nbsp;==&nbsp;1)&nbsp;{<br /><span style="color: #008080; ">&nbsp;40</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;returnSet.remove(newEnd);<br /><span style="color: #008080; ">&nbsp;41</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;42</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;returnSet;<br /><span style="color: #008080; ">&nbsp;43</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;44</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;45</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;46</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(hasHigher)&nbsp;{<br /><span style="color: #008080; ">&nbsp;47</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("get&nbsp;end:"&nbsp;+&nbsp;bdHigher);<br /><span style="color: #008080; ">&nbsp;48</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeSet&lt;BigDecimal&gt;&nbsp;newTargetSet&nbsp;=&nbsp;(TreeSet&lt;BigDecimal&gt;)&nbsp;targetSet<br /><span style="color: #008080; ">&nbsp;49</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.headSet(bdHigher,&nbsp;<span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; ">&nbsp;50</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;newStart&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; ">&nbsp;51</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortedSet&lt;BigDecimal&gt;&nbsp;returnSet&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; ">&nbsp;52</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;53</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(bdLower.compareTo(targetSet.first())&nbsp;==&nbsp;-1)&nbsp;{<br /><span style="color: #008080; ">&nbsp;54</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newStart&nbsp;=&nbsp;targetSet.first();<br /><span style="color: #008080; ">&nbsp;55</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;56</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(BigDecimal&nbsp;object&nbsp;:&nbsp;newTargetSet)&nbsp;{<br /><span style="color: #008080; ">&nbsp;57</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(object.compareTo(bdLower)&nbsp;!=&nbsp;-1)&nbsp;{<br /><span style="color: #008080; ">&nbsp;58</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newStart&nbsp;=&nbsp;object;<br /><span style="color: #008080; ">&nbsp;59</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span>;<br /><span style="color: #008080; ">&nbsp;60</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;61</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;62</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;63</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;returnSet&nbsp;=&nbsp;targetSet.subSet(newStart,&nbsp;<span style="color: #0000FF; ">true</span>,&nbsp;bdHigher,&nbsp;<span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; ">&nbsp;64</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;65</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;returnSet;<br /><span style="color: #008080; ">&nbsp;66</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;67</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Not&nbsp;get&nbsp;start:"&nbsp;+&nbsp;bdLower);<br /><span style="color: #008080; ">&nbsp;68</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Not&nbsp;get&nbsp;end:"&nbsp;+&nbsp;bdHigher);<br /><span style="color: #008080; ">&nbsp;69</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;newStart&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; ">&nbsp;70</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;newEnd&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; ">&nbsp;71</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(bdHigher.compareTo(targetSet.last())&nbsp;!=&nbsp;-1)&nbsp;{<br /><span style="color: #008080; ">&nbsp;72</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newEnd&nbsp;=&nbsp;targetSet.last();<br /><span style="color: #008080; ">&nbsp;73</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;74</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(bdLower.compareTo(targetSet.first())&nbsp;==&nbsp;-1)&nbsp;{<br /><span style="color: #008080; ">&nbsp;75</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newStart&nbsp;=&nbsp;targetSet.first();<br /><span style="color: #008080; ">&nbsp;76</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;77</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(BigDecimal&nbsp;object&nbsp;:&nbsp;targetSet)&nbsp;{<br /><span style="color: #008080; ">&nbsp;78</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(newStart&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br /><span style="color: #008080; ">&nbsp;79</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(object.compareTo(bdLower)&nbsp;!=&nbsp;-1)&nbsp;{<br /><span style="color: #008080; ">&nbsp;80</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newStart&nbsp;=&nbsp;object;<br /><span style="color: #008080; ">&nbsp;81</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(newEnd&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br /><span style="color: #008080; ">&nbsp;82</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span>;<br /><span style="color: #008080; ">&nbsp;83</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;84</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;85</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;86</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;87</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(newEnd&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br /><span style="color: #008080; ">&nbsp;88</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(object.compareTo(bdHigher)&nbsp;!=&nbsp;-1)&nbsp;{<br /><span style="color: #008080; ">&nbsp;89</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newEnd&nbsp;=&nbsp;object;<br /><span style="color: #008080; ">&nbsp;90</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(newStart&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br /><span style="color: #008080; ">&nbsp;91</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span>;<br /><span style="color: #008080; ">&nbsp;92</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;93</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;94</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;95</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;96</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;97</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(newStart&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br /><span style="color: #008080; ">&nbsp;98</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(newEnd&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br /><span style="color: #008080; ">&nbsp;99</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;((bdHigher.compareTo(targetSet.first())&nbsp;==&nbsp;-1)<br /><span style="color: #008080; ">100</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;||&nbsp;(bdLower.compareTo(targetSet.last())&nbsp;==&nbsp;1))&nbsp;{<br /><span style="color: #008080; ">101</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; ">102</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">103</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;targetSet;<br /><span style="color: #008080; ">104</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">105</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortedSet&lt;BigDecimal&gt;&nbsp;newTargetSet&nbsp;=&nbsp;targetSet.headSet(<br /><span style="color: #008080; ">106</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newEnd,&nbsp;<span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; ">107</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(newEnd.compareTo(bdHigher)&nbsp;==&nbsp;1)&nbsp;{<br /><span style="color: #008080; ">108</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newTargetSet.remove(newEnd);<br /><span style="color: #008080; ">109</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">110</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;newTargetSet;<br /><span style="color: #008080; ">111</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">112</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">113</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(newEnd&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br /><span style="color: #008080; ">114</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortedSet&lt;BigDecimal&gt;&nbsp;newTargetSet&nbsp;=&nbsp;targetSet.tailSet(<br /><span style="color: #008080; ">115</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newStart,&nbsp;<span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; ">116</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;newTargetSet;<br /><span style="color: #008080; ">117</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">118</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortedSet&lt;BigDecimal&gt;&nbsp;newTargetSet&nbsp;=&nbsp;targetSet.subSet(<br /><span style="color: #008080; ">119</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newStart,&nbsp;<span style="color: #0000FF; ">true</span>,&nbsp;newEnd,&nbsp;<span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; ">120</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(newEnd.compareTo(bdHigher)&nbsp;==&nbsp;1)&nbsp;{<br /><span style="color: #008080; ">121</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newTargetSet.remove(newEnd);<br /><span style="color: #008080; ">122</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">123</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;newTargetSet;<br /><span style="color: #008080; ">124</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">125</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">126</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">127</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">128</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div>第三种方式: 使用Apache Commons Collections, 直接对于原始Set进行filter.<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 测试效果:集合大小10M,过滤结果1M, 运算时间: 1000ms+<br />过滤部分的代码如下:<br /><div style="font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">过滤的主体逻辑</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;filterSet(Set&lt;BigDecimal&gt;&nbsp;targetSet,&nbsp;String&nbsp;lower,&nbsp;String&nbsp;higher)&nbsp;{<br /><span style="color: #008080; ">&nbsp;3</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;BigDecimal&nbsp;bdLower&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;BigDecimal(Double.parseDouble(lower));<br /><span style="color: #008080; ">&nbsp;4</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;BigDecimal&nbsp;bdHigher&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;BigDecimal(Double.parseDouble(higher));<br /><span style="color: #008080; ">&nbsp;5</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;6</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Predicate&nbsp;predicate&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Predicate()&nbsp;{<br /><span style="color: #008080; ">&nbsp;7</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;evaluate(Object&nbsp;object)&nbsp;{<br /><span style="color: #008080; ">&nbsp;8</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;bDObject&nbsp;=&nbsp;(BigDecimal)&nbsp;object;<br /><span style="color: #008080; ">&nbsp;9</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;bDObject.compareTo(bdLower)&nbsp;&gt;=&nbsp;0<br /><span style="color: #008080; ">10</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;bDObject.compareTo(bdHigher)&nbsp;&lt;=&nbsp;0;<br /><span style="color: #008080; ">11</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">12</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br /><span style="color: #008080; ">13</span>&nbsp;<br /><span style="color: #008080; ">14</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CollectionUtils.filter(targetSet,&nbsp;predicate);<br /><span style="color: #008080; ">15</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div><br />第四种方式:使用Guava(google Collections), 直接对于原始Set进行Filter<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;测试效果:集合大小10M,过滤结果1M, 运算时间: 100ms-<br />过滤部分的代码如下:<br /><div style="font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">guava&nbsp;filter</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #008000; "></span><br /><span style="color: #008080; ">&nbsp;3</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set&lt;BigDecimal&gt;&nbsp;filterSet(Set&lt;BigDecimal&gt;&nbsp;targetSet,&nbsp;String&nbsp;lower,<br /><span style="color: #008080; ">&nbsp;4</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;higher)&nbsp;{<br /><span style="color: #008080; ">&nbsp;5</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;BigDecimal&nbsp;bdLower&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;BigDecimal(Double.parseDouble(lower));<br /><span style="color: #008080; ">&nbsp;6</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;BigDecimal&nbsp;bdHigher&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;BigDecimal(Double.parseDouble(higher));<br /><span style="color: #008080; ">&nbsp;7</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;8</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set&lt;BigDecimal&gt;&nbsp;filterCollection&nbsp;=&nbsp;Sets.filter(targetSet,<br /><span style="color: #008080; ">&nbsp;9</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Predicate&lt;BigDecimal&gt;()&nbsp;{<br /><span style="color: #008080; ">10</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br /><span style="color: #008080; ">11</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;apply(BigDecimal&nbsp;input)&nbsp;{<br /><span style="color: #008080; ">12</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;bDObject&nbsp;=&nbsp;(BigDecimal)&nbsp;input;<br /><span style="color: #008080; ">13</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;bDObject.compareTo(bdLower)&nbsp;&gt;=&nbsp;0<br /><span style="color: #008080; ">14</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;bDObject.compareTo(bdHigher)&nbsp;&lt;=&nbsp;0;<br /><span style="color: #008080; ">15</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">16</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br /><span style="color: #008080; ">17</span>&nbsp;<br /><span style="color: #008080; ">18</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;filterCollection;<br /><span style="color: #008080; ">19</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div><br /><br />四种方式对比如下:<br />第一种方式: &nbsp;仅依赖于JAVA原生类库 遍历时间最慢, 代码量很小<br />第二种方式: &nbsp;仅依赖于JAVA原生类库 遍历时间比较慢(主要慢在生成有序Set), 代码量最多<br />第三种方式: &nbsp;依赖于Apache Commons Collections, 遍历时间比较快, 代码量很少<br />第四种方式: &nbsp;依赖于Guava, 遍历时间最快, 代码量很少<br /><br />基于目前个人的技术水平和视野, 第四种方式可能是最佳选择.<br /><br />记录一下, 以后可能还会有更好的方案.<br /><br /><br /><br /><br /><div class="vimiumReset vimiumHUD" style="right: 150px; opacity: 0; display: none;"></div><img src ="http://www.blogjava.net/GandofYan/aggbug/415009.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/GandofYan/" target="_blank">混沌中立</a> 2014-06-21 23:33 <a href="http://www.blogjava.net/GandofYan/archive/2014/06/21/415009.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个Sudoku的java求解算法</title><link>http://www.blogjava.net/GandofYan/archive/2006/07/13/58004.html</link><dc:creator>混沌中立</dc:creator><author>混沌中立</author><pubDate>Thu, 13 Jul 2006 08:19:00 GMT</pubDate><guid>http://www.blogjava.net/GandofYan/archive/2006/07/13/58004.html</guid><wfw:comment>http://www.blogjava.net/GandofYan/comments/58004.html</wfw:comment><comments>http://www.blogjava.net/GandofYan/archive/2006/07/13/58004.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/GandofYan/comments/commentRss/58004.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/GandofYan/services/trackbacks/58004.html</trackback:ping><description><![CDATA[这个小的project是前一个阶段，待业在家的时候，迷恋sudoku的时候，自己写来玩的。<br />正好当时在看Uncle Bob的《Agile Software Development: Principles, Patterns, and Practices》 （敏捷软件开发：原则、模式与实践）,所以就按照自己对书中的一些概念和方法的理解，结合自己之前的开发经验写出来一段小的代码。<br /><br />代码行数： &lt; 900<br />类的个数： 18<br />抽象类的个数：2<br />工厂类的个数：1<br />包的个数：5<br /><br />一些关于类和包作用的说明：<br />1.Cell:表示一个Cell，是一个游戏中的一个单元格。<br />  Cell主要由3个部分组成，Point,Value,Status.<br />2.Point:表示一个坐标，主要格式为:(2,3).<br />  ！！！注意：由于个人比较懒,所以开始的错误被贯彻了下来。<br />  这个错误就是（2，3）表示的是由最左上的位置为坐标原点，第二行和第三列所确定的那个单元格。也就是纵坐标在前，横坐标在后了。<br />3.Value:表示一个值<br />4.Status:表示Cell的状态，只有两个状态，一个是NotSure,另一个是Sure.<br /><br />5.AbstractCells：表示一些cell的集合，主要有三个子类<br />     BlockCells：表示一个由多个Cell组成的块，例如一个2*2由4个Cell组成的块，或者一个2*3由6个Cell组成的块<br />     HorizonCells:表示一个横行，即：从（0，0）到(0,n)坐标确定的所有Cell的集合。<br />     VerticalCells:表示一个纵行，即：从（0，0）到(n,0)坐标确定的所有Cell的集合。<br />6.AbstractPolicy:就是游戏的策略。<br />   这个主要表示的是：4*4的游戏，还是9*9的游戏。<br />   可以在以后对此类进行继承和扩展，例如16*16的游戏我就没有实现。<br />   主要扩展3个方法：<br />                  1）getValueRange，返回当前policy的value的个数。4*4的游戏的getValueRange返回的就应该是4。<br />          2）getStep：表示当前policy中相邻的两个BlockCells的坐标差。<br />          3）getIncrease：说不明白了：）（只可意会不可言传。）<br />7.Game：进行Policy的场所（我一直想抛弃这个类）<br />8.TestGame:游戏运行的地方，包括从PolicyFactory取得指定的Policy,设置输入输出文件的路径。<br />9.PolicyFactory：取得Policy的工厂。<br />    getPolicy(int x) :这个方法获得的是正方形的sudoku的策略。例如:4*4的，9*9,16*16。<br />    getPolicy(int x, int y)：这个方法获得的是长方形的Sudoku的策略。例如：9*12的。<br /><br /><br />虽然是尽量避免bad code smell，但是由于能力有限，还是出现了一些不好的地方。<br />例如：之间的关联关系还是很多，而且很强；抽象的方法和抽象类的个数偏少等等。<br /><br />里面实现了三个解决sudoku的方法：<br />1.在一个Cell中出现的Value,不会在和这个Cell处在同一个AbstractCells中的所有Cell中出现；<br />2.如果一个Cell中，所有可能出现的Value的个数为1，那么Cell的Value必然是这个最后的Value；<br />2.如果一个Value,如果在当前AbstractCells的所有其他的Cell中都不可能出现，那么它必然是最后一个Cell的Value。<br /><br />附件1：src code<br />http://www.blogjava.net/Files/GandofYan/sudoku.rar<br />附件2：输入输出文件的example<br />http://www.blogjava.net/Files/GandofYan/temp.rar<br /><br /><img src ="http://www.blogjava.net/GandofYan/aggbug/58004.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/GandofYan/" target="_blank">混沌中立</a> 2006-07-13 16:19 <a href="http://www.blogjava.net/GandofYan/archive/2006/07/13/58004.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>javaEye上面对于domain object的讨论</title><link>http://www.blogjava.net/GandofYan/archive/2006/05/30/48954.html</link><dc:creator>混沌中立</dc:creator><author>混沌中立</author><pubDate>Tue, 30 May 2006 05:31:00 GMT</pubDate><guid>http://www.blogjava.net/GandofYan/archive/2006/05/30/48954.html</guid><wfw:comment>http://www.blogjava.net/GandofYan/comments/48954.html</wfw:comment><comments>http://www.blogjava.net/GandofYan/archive/2006/05/30/48954.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/GandofYan/comments/commentRss/48954.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/GandofYan/services/trackbacks/48954.html</trackback:ping><description><![CDATA[
		<div>
				<a href="http://forum.javaeye.com/viewtopic.php?t=11712&amp;start=0&amp;postdays=0&amp;postorder=asc&amp;highlight=">
						<u>
								<font color="#0000ff">总结一下最近关于domain object以及相关的讨论</font>
						</u>
				</a>
		</div>
		<div> </div>
		<div>
				<span>在最近的围绕domain 
object的讨论中浮现出来了三种模型，(还有一些其他的旁枝，不一一分析了)，经过一番讨论，各种问题逐渐清晰起来，在这里我试图做一个总结，便于大家了解和掌握。 
<br /><br />第一种模型：只有getter/setter方法的纯数据类，所有的业务逻辑完全由business 
object来完成(又称TransactionScript)，这种模型下的domain object被Martin Fowler称之为“贫血的domain 
object”。下面用举一个具体的代码来说明，代码来自Hibernate的caveatemptor，但经过我的改写： 
<br /><br />一个实体类叫做Item，指的是一个拍卖项目 <br />一个DAO接口类叫做ItemDao 
<br />一个DAO接口实现类叫做ItemDaoHibernateImpl <br />一个业务逻辑类叫做ItemManager(或者叫做ItemService) 
<br /><br /></span>
				<table align="center" border="0" cellpadding="3" cellspacing="1" width="90%">
						<tbody>
								<tr>
										<td>
												<span>
														<b>java代码: </b>
												</span>
										</td>
								</tr>
								<tr>
										<td>
												<div style="font-family: 'Courier New',Courier,monospace;">
														<br />
														<font face="Courier New">
																<span style="font-weight: bold; color: rgb(153, 0, 102);">public</span>
																<span style="font-weight: bold; color: rgb(153, 0, 102);">class</span> Item <span style="font-weight: bold; color: rgb(153, 0, 102);">implements</span><span style="color: rgb(170, 170, 221);">Serializable</span><span style="color: rgb(0, 0, 0);">{</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span><span style="color: rgb(170, 170, 221);">Long</span> id = <span style="font-weight: bold; color: rgb(153, 0, 102);">null</span>; <br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span><span style="font-weight: bold; color: rgb(153, 0, 102);">int</span> version; <br />    
<span style="font-weight: bold; color: rgb(153, 0, 102);">private</span><span style="color: rgb(170, 170, 221);">String</span> name; <br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span> User seller; 
<br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span><span style="color: rgb(170, 170, 221);">String</span> description; <br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span> MonetaryAmount 
initialPrice; <br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span> MonetaryAmount 
reservePrice; <br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span><span style="color: rgb(170, 170, 221);">Date</span> startDate; <br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span><span style="color: rgb(170, 170, 221);">Date</span> endDate; <br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span><span style="color: rgb(170, 170, 221);">Set</span> categorizedItems = <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span><span style="color: rgb(170, 170, 221);">HashSet</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>; 
<br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span><span style="color: rgb(170, 170, 221);">Collection</span> bids = <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span><span style="color: rgb(170, 170, 221);">ArrayList</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>; 
<br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span> 
Bid successfulBid; <br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span> ItemState state; 
<br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span> 
User approvedBy; <br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span><span style="color: rgb(170, 170, 221);">Date</span> approvalDatetime; <br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span><span style="color: rgb(170, 170, 221);">Date</span> created = <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span><span style="color: rgb(170, 170, 221);">Date</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>; 
<br />    <span style="color: rgb(102, 102, 255);">//  
getter/setter方法省略不写，避免篇幅太长</span><br /><span style="color: rgb(0, 0, 0);">}</span></font>
												</div>
												<br />
										</td>
								</tr>
						</tbody>
				</table>
				<span>
						<br />
						<br />
				</span>
				<table align="center" border="0" cellpadding="3" cellspacing="1" width="90%">
						<tbody>
								<tr>
										<td>
												<span>
														<b>java代码: </b>
												</span>
										</td>
								</tr>
								<tr>
										<td>
												<div style="font-family: 'Courier New',Courier,monospace;">
														<br />
														<font face="Courier New">
																<span style="font-weight: bold; color: rgb(153, 0, 102);">public</span>
																<span style="font-weight: bold; color: rgb(153, 0, 102);">interface</span> ItemDao <span style="color: rgb(0, 0, 0);">{</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span> Item 
getItemById<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(170, 170, 221);">Long</span> id<span style="color: rgb(0, 0, 0);">)</span>; <br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span><span style="color: rgb(170, 170, 221);">Collection</span> findAll<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>; 
<br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span><span style="font-weight: bold; color: rgb(153, 0, 102);">void</span> 
updateItem<span style="color: rgb(0, 0, 0);">(</span>Item item<span style="color: rgb(0, 0, 0);">)</span>; <br /><span style="color: rgb(0, 0, 0);">}</span></font>
												</div>
												<br />
										</td>
								</tr>
						</tbody>
				</table>
				<span>
						<br />
						<br />ItemDao定义持久化操作的接口，用于隔离持久化代码。 
<br /><br /></span>
				<table align="center" border="0" cellpadding="3" cellspacing="1" width="90%">
						<tbody>
								<tr>
										<td>
												<span>
														<b>java代码: </b>
												</span>
										</td>
								</tr>
								<tr>
										<td>
												<div style="font-family: 'Courier New',Courier,monospace;">
														<br />
														<font face="Courier New">
																<span style="font-weight: bold; color: rgb(153, 0, 102);">public</span>
																<span style="font-weight: bold; color: rgb(153, 0, 102);">class</span> 
ItemDaoHibernateImpl <span style="font-weight: bold; color: rgb(153, 0, 102);">implements</span> ItemDao <span style="font-weight: bold; color: rgb(153, 0, 102);">extends</span> 
HibernateDaoSupport <span style="color: rgb(0, 0, 0);">{</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span> Item 
getItemById<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(170, 170, 221);">Long</span> id<span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />        <span style="font-weight: bold; color: rgb(153, 0, 102);">return</span><span style="color: rgb(0, 0, 0);">(</span>Item<span style="color: rgb(0, 0, 0);">)</span> getHibernateTemplate<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>.<span style="color: rgb(0, 0, 0);">load</span><span style="color: rgb(0, 0, 0);">(</span>Item.<span style="color: rgb(0, 0, 0);">class</span>, id<span style="color: rgb(0, 0, 0);">)</span>; <br />    <span style="color: rgb(0, 0, 0);">}</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span><span style="color: rgb(170, 170, 221);">Collection</span> findAll<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />        <span style="font-weight: bold; color: rgb(153, 0, 102);">return</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(170, 170, 221);">List</span><span style="color: rgb(0, 0, 0);">)</span> getHibernateTemplate<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>.<span style="color: rgb(0, 0, 0);">find</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">"from 
Item"</span><span style="color: rgb(0, 0, 0);">)</span>; <br />    <span style="color: rgb(0, 0, 0);">}</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span><span style="font-weight: bold; color: rgb(153, 0, 102);">void</span> updateItem<span style="color: rgb(0, 0, 0);">(</span>Item item<span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />        getHibernateTemplate<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>.<span style="color: rgb(0, 0, 0);">update</span><span style="color: rgb(0, 0, 0);">(</span>item<span style="color: rgb(0, 0, 0);">)</span>; 
<br />    <span style="color: rgb(0, 0, 0);">}</span><br /><span style="color: rgb(0, 0, 0);">}</span></font>
												</div>
												<br />
										</td>
								</tr>
						</tbody>
				</table>
				<span>
						<br />ItemDaoHibernateImpl完成具体的持久化工作，请注意，数据库资源的获取和释放是在ItemDaoHibernateImpl 
里面处理的，每个DAO方法调用之前打开Session，DAO方法调用之后，关闭Session。(Session放在ThreadLocal中，保证一次调用只打开关闭一次) 
<br /><br /></span>
				<table align="center" border="0" cellpadding="3" cellspacing="1" width="90%">
						<tbody>
								<tr>
										<td>
												<span>
														<b>java代码: </b>
												</span>
										</td>
								</tr>
								<tr>
										<td>
												<div style="font-family: 'Courier New',Courier,monospace;">
														<br />
														<font face="Courier New">
																<span style="font-weight: bold; color: rgb(153, 0, 102);">public</span>
																<span style="font-weight: bold; color: rgb(153, 0, 102);">class</span> ItemManager <span style="color: rgb(0, 0, 0);">{</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span> ItemDao itemDao; 
<br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span><span style="font-weight: bold; color: rgb(153, 0, 102);">void</span> 
setItemDao<span style="color: rgb(0, 0, 0);">(</span>ItemDao itemDao<span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span> 
this.<span style="color: rgb(0, 0, 0);">itemDao</span> = itemDao;<span style="color: rgb(0, 0, 0);">}</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span> Bid 
loadItemById<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(170, 170, 221);">Long</span> id<span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />        itemDao.<span style="color: rgb(0, 0, 0);">loadItemById</span><span style="color: rgb(0, 0, 0);">(</span>id<span style="color: rgb(0, 0, 0);">)</span>; 
<br />    <span style="color: rgb(0, 0, 0);">}</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span><span style="color: rgb(170, 170, 221);">Collection</span> listAllItems<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />        <span style="font-weight: bold; color: rgb(153, 0, 102);">return</span>  itemDao.<span style="color: rgb(0, 0, 0);">findAll</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>; 
<br />    <span style="color: rgb(0, 0, 0);">}</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span> Bid placeBid<span style="color: rgb(0, 0, 0);">(</span>Item item, User bidder, MonetaryAmount 
bidAmount, <br />                            Bid currentMaxBid, Bid 
currentMinBid<span style="color: rgb(0, 0, 0);">)</span><span style="font-weight: bold; color: rgb(153, 0, 102);">throws</span> BusinessException 
<span style="color: rgb(0, 0, 0);">{</span><br />            <span style="font-weight: bold; color: rgb(153, 0, 102);">if</span><span style="color: rgb(0, 0, 0);">(</span>currentMaxBid != <span style="font-weight: bold; color: rgb(153, 0, 102);">null</span> &amp;&amp; 
currentMaxBid.<span style="color: rgb(0, 0, 0);">getAmount</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>.<span style="color: rgb(0, 0, 0);">compareTo</span><span style="color: rgb(0, 0, 0);">(</span>bidAmount<span style="color: rgb(0, 0, 0);">)</span> &gt; <span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />            throw <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span> 
BusinessException<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">"Bid too low."</span><span style="color: rgb(0, 0, 0);">)</span>; <br />    <span style="color: rgb(0, 0, 0);">}</span><br />    <br />    <span style="color: rgb(102, 102, 255);">// Auction is active</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">if</span><span style="color: rgb(0, 0, 0);">(</span> !state.<span style="color: rgb(0, 0, 0);">equals</span><span style="color: rgb(0, 0, 0);">(</span>ItemState.<span style="color: rgb(0, 0, 0);">ACTIVE</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">)</span><br />            throw <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span> 
BusinessException<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">"Auction is not active yet."</span><span style="color: rgb(0, 0, 0);">)</span>; <br />    <br />    <span style="color: rgb(102, 102, 255);">// Auction still valid</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">if</span><span style="color: rgb(0, 0, 0);">(</span> item.<span style="color: rgb(0, 0, 0);">getEndDate</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>.<span style="color: rgb(0, 0, 0);">before</span><span style="color: rgb(0, 0, 0);">(</span><span style="font-weight: bold; color: rgb(153, 0, 102);">new</span><span style="color: rgb(170, 170, 221);">Date</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">)</span><br />            throw <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span> 
BusinessException<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">"Can't place new bid, auction already 
ended."</span><span style="color: rgb(0, 0, 0);">)</span>; <br />    <br />    <span style="color: rgb(102, 102, 255);">// Create new Bid</span><br />    Bid newBid = 
<span style="font-weight: bold; color: rgb(153, 0, 102);">new</span> Bid<span style="color: rgb(0, 0, 0);">(</span>bidAmount, item, bidder<span style="color: rgb(0, 0, 0);">)</span>; <br />    <br />    <span style="color: rgb(102, 102, 255);">// Place bid for this Item</span><br />    
item.<span style="color: rgb(0, 0, 0);">getBids</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>.<span style="color: rgb(0, 0, 0);">add</span><span style="color: rgb(0, 0, 0);">(</span>newBid<span style="color: rgb(0, 0, 0);">)</span>; <br />    itemDao.<span style="color: rgb(0, 0, 0);">update</span><span style="color: rgb(0, 0, 0);">(</span>item<span style="color: rgb(0, 0, 0);">)</span>;  
   <span style="color: rgb(102, 102, 255);">//  调用DAO完成持久化操作</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">return</span> newBid; <br />    
<span style="color: rgb(0, 0, 0);">}</span><br /><span style="color: rgb(0, 0, 0);">}</span></font>
												</div>
												<br />
										</td>
								</tr>
						</tbody>
				</table>
				<span>
						<br />
						<br />事务的管理是在ItemManger这一层完成的，ItemManager实现具体的业务逻辑。除了常见的和CRUD有关的简单逻辑之外，这里还有一个placeBid的逻辑，即项目的竞标。 
<br /><br />以上是一个完整的第一种模型的示例代码。在这个示例中，placeBid，loadItemById，findAll等等业务逻辑统统放在ItemManager中实现，而Item只有getter/setter方法。</span>
		</div>
		<p> </p>
		<p> </p>
		<p>
				<span>第二种模型，也就是Martin Fowler指的rich domain object是下面这样子的： 
<br /><br />一个带有业务逻辑的实体类，即domain object是Item <br />一个DAO接口ItemDao 
<br />一个DAO实现ItemDaoHibernateImpl <br />一个业务逻辑对象ItemManager <br /><br /></span>
		</p>
		<table align="center" border="0" cellpadding="3" cellspacing="1" width="90%">
				<tbody>
						<tr>
								<td>
										<span>
												<b>java代码: </b>
										</span>
								</td>
						</tr>
						<tr>
								<td>
										<div style="font-family: 'Courier New',Courier,monospace;">
												<br />
												<font face="Courier New">
														<span style="font-weight: bold; color: rgb(153, 0, 102);">public</span>
														<span style="font-weight: bold; color: rgb(153, 0, 102);">class</span> Item <span style="font-weight: bold; color: rgb(153, 0, 102);">implements</span><span style="color: rgb(170, 170, 221);">Serializable</span><span style="color: rgb(0, 0, 0);">{</span><br />    <span style="color: rgb(102, 102, 255);">//  所有的属性和getter/setter方法同上，省略</span><br />    
<span style="font-weight: bold; color: rgb(153, 0, 102);">public</span> Bid 
placeBid<span style="color: rgb(0, 0, 0);">(</span>User bidder, MonetaryAmount 
bidAmount, <br />                        Bid currentMaxBid, Bid currentMinBid<span style="color: rgb(0, 0, 0);">)</span><br />            <span style="font-weight: bold; color: rgb(153, 0, 102);">throws</span> BusinessException 
<span style="color: rgb(0, 0, 0);">{</span><br />    <br />            <span style="color: rgb(102, 102, 255);">// Check highest bid (can also be a different 
Strategy (pattern))</span><br />            <span style="font-weight: bold; color: rgb(153, 0, 102);">if</span><span style="color: rgb(0, 0, 0);">(</span>currentMaxBid != <span style="font-weight: bold; color: rgb(153, 0, 102);">null</span> &amp;&amp; 
currentMaxBid.<span style="color: rgb(0, 0, 0);">getAmount</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>.<span style="color: rgb(0, 0, 0);">compareTo</span><span style="color: rgb(0, 0, 0);">(</span>bidAmount<span style="color: rgb(0, 0, 0);">)</span> &gt; <span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />                    throw <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span> 
BusinessException<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">"Bid too low."</span><span style="color: rgb(0, 0, 0);">)</span>; <br />            <span style="color: rgb(0, 0, 0);">}</span><br />    <br />            <span style="color: rgb(102, 102, 255);">// Auction is active</span><br />            
<span style="font-weight: bold; color: rgb(153, 0, 102);">if</span><span style="color: rgb(0, 0, 0);">(</span> !state.<span style="color: rgb(0, 0, 0);">equals</span><span style="color: rgb(0, 0, 0);">(</span>ItemState.<span style="color: rgb(0, 0, 0);">ACTIVE</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">)</span><br />                    throw <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span> 
BusinessException<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">"Auction is not active yet."</span><span style="color: rgb(0, 0, 0);">)</span>; <br />    <br />            <span style="color: rgb(102, 102, 255);">// Auction still valid</span><br />            
<span style="font-weight: bold; color: rgb(153, 0, 102);">if</span><span style="color: rgb(0, 0, 0);">(</span> this.<span style="color: rgb(0, 0, 0);">getEndDate</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>.<span style="color: rgb(0, 0, 0);">before</span><span style="color: rgb(0, 0, 0);">(</span><span style="font-weight: bold; color: rgb(153, 0, 102);">new</span><span style="color: rgb(170, 170, 221);">Date</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">)</span><br />                    throw <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span> 
BusinessException<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">"Can't place new bid, auction already 
ended."</span><span style="color: rgb(0, 0, 0);">)</span>; <br />    <br />            
<span style="color: rgb(102, 102, 255);">// Create new Bid</span><br />            
Bid newBid = <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span> 
Bid<span style="color: rgb(0, 0, 0);">(</span>bidAmount, this, bidder<span style="color: rgb(0, 0, 0);">)</span>; <br />    <br />            <span style="color: rgb(102, 102, 255);">// Place bid for this Item</span><br />          
  this.<span style="color: rgb(0, 0, 0);">getBids</span>.<span style="color: rgb(0, 0, 0);">add</span><span style="color: rgb(0, 0, 0);">(</span>newBid<span style="color: rgb(0, 0, 0);">)</span>;  <span style="color: rgb(102, 102, 255);">// 
请注意这一句，透明的进行了持久化，但是不能在这里调用ItemDao，Item不能对ItemDao产生依赖！</span><br />    <br />        
    <span style="font-weight: bold; color: rgb(153, 0, 102);">return</span> newBid; 
<br />    <span style="color: rgb(0, 0, 0);">}</span><br /><span style="color: rgb(0, 0, 0);">}</span></font>
										</div>
										<br />
								</td>
						</tr>
				</tbody>
		</table>
		<span>
				<br />
				<br />竞标这个业务逻辑被放入到Item中来。请注意this.getBids.add(newBid); 
如果没有Hibernate或者JDO这种O/R 
Mapping的支持，我们是无法实现这种透明的持久化行为的。但是请注意，Item里面不能去调用ItemDAO，对ItemDAO产生依赖！ 
<br /><br />ItemDao和ItemDaoHibernateImpl的代码同上，省略。 <br /><br /></span>
		<table align="center" border="0" cellpadding="3" cellspacing="1" width="90%">
				<tbody>
						<tr>
								<td>
										<span>
												<b>java代码: </b>
										</span>
								</td>
						</tr>
						<tr>
								<td>
										<div style="font-family: 'Courier New',Courier,monospace;">
												<br />
												<font face="Courier New">
														<span style="font-weight: bold; color: rgb(153, 0, 102);">public</span>
														<span style="font-weight: bold; color: rgb(153, 0, 102);">class</span> ItemManager <span style="color: rgb(0, 0, 0);">{</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span> ItemDao itemDao; 
<br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span><span style="font-weight: bold; color: rgb(153, 0, 102);">void</span> 
setItemDao<span style="color: rgb(0, 0, 0);">(</span>ItemDao itemDao<span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span> 
this.<span style="color: rgb(0, 0, 0);">itemDao</span> = itemDao;<span style="color: rgb(0, 0, 0);">}</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span> Bid 
loadItemById<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(170, 170, 221);">Long</span> id<span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />        itemDao.<span style="color: rgb(0, 0, 0);">loadItemById</span><span style="color: rgb(0, 0, 0);">(</span>id<span style="color: rgb(0, 0, 0);">)</span>; 
<br />    <span style="color: rgb(0, 0, 0);">}</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span><span style="color: rgb(170, 170, 221);">Collection</span> listAllItems<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />        <span style="font-weight: bold; color: rgb(153, 0, 102);">return</span>  itemDao.<span style="color: rgb(0, 0, 0);">findAll</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>; 
<br />    <span style="color: rgb(0, 0, 0);">}</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span> Bid placeBid<span style="color: rgb(0, 0, 0);">(</span>Item item, User bidder, MonetaryAmount 
bidAmount, <br />                            Bid currentMaxBid, Bid 
currentMinBid<span style="color: rgb(0, 0, 0);">)</span><span style="font-weight: bold; color: rgb(153, 0, 102);">throws</span> BusinessException 
<span style="color: rgb(0, 0, 0);">{</span><br />        item.<span style="color: rgb(0, 0, 0);">placeBid</span><span style="color: rgb(0, 0, 0);">(</span>bidder, bidAmount, currentMaxBid, 
currentMinBid<span style="color: rgb(0, 0, 0);">)</span>; <br />        itemDao.<span style="color: rgb(0, 0, 0);">update</span><span style="color: rgb(0, 0, 0);">(</span>item<span style="color: rgb(0, 0, 0);">)</span>;  
  <span style="color: rgb(102, 102, 255);">// 必须显式的调用DAO，保持持久化</span><br />    <span style="color: rgb(0, 0, 0);">}</span><br /><span style="color: rgb(0, 0, 0);">}</span></font>
										</div>
										<br />
								</td>
						</tr>
				</tbody>
		</table>
		<span>
				<br />
				<br />在第二种模型中，placeBid业务逻辑是放在Item中实现的，而loadItemById和findAll业务逻辑是放在 
ItemManager中实现的。不过值得注意的是，即使placeBid业务逻辑放在Item中，你仍然需要在ItemManager中简单的封装一层，以保证对placeBid业务逻辑进行事务的管理和持久化的触发。 
<br /><br />这种模型是Martin Fowler所指的真正的domain 
model。在这种模型中，有三个业务逻辑方法：placeBid，loadItemById和findAll，现在的问题是哪个逻辑应该放在Item 
中，哪个逻辑应该放在ItemManager中。在我们这个例子中，placeBid放在Item中(但是ItemManager也需要对它进行简单的封装)，loadItemById和findAll是放在ItemManager中的。 
<br /><br />切分的原则是什么呢？ Rod Johnson提出原则是“case by case”，可重用度高的，和domain 
object状态密切关联的放在Item中，可重用度低的，和domain object状态没有密切关联的放在ItemManager中。 <br /><br /><span style="color: red;">我提出的原则是：看业务方法是否显式的依赖持久化。</span><br /><br />Item的placeBid这个业务逻辑方法没有显式的对持久化ItemDao接口产生依赖，所以要放在Item中。<span style="color: red;">请注意，如果脱离了Hibernate这个持久化框架，Item这个domain 
object是可以进行单元测试的，他不依赖于Hibernate的持久化机制。它是一个独立的，可移植的，完整的，自包含的域对象</span>。 
<br /><br />而loadItemById和findAll这两个业务逻辑方法是必须显式的对持久化ItemDao接口产生依赖，否则这个业务逻辑就无法完成。如果你要把这两个方法放在Item中，那么Item就无法脱离Hibernate框架，无法在Hibernate框架之外独立存在。</span>
		<p> </p>
		<p> </p>
		<p>
				<span>第三种模型印象中好像是firebody或者是Archie提出的(也有可能不是，记不清楚了)，简单的来说，这种模型就是把第二种模型的domain 
object和business object合二为一了。所以ItemManager就不需要了，在这种模型下面，只有三个类，他们分别是： 
<br /><br />Item：包含了实体类信息，也包含了所有的业务逻辑 <br />ItemDao：持久化DAO接口类 
<br />ItemDaoHibernateImpl：DAO接口的实现类 
<br /><br />由于ItemDao和ItemDaoHibernateImpl和上面完全相同，就省略了。 <br /><br /></span>
		</p>
		<table align="center" border="0" cellpadding="3" cellspacing="1" width="90%">
				<tbody>
						<tr>
								<td>
										<span>
												<b>java代码: </b>
										</span>
								</td>
						</tr>
						<tr>
								<td>
										<div style="font-family: 'Courier New',Courier,monospace;">
												<br />
												<font face="Courier New">
														<span style="font-weight: bold; color: rgb(153, 0, 102);">public</span>
														<span style="font-weight: bold; color: rgb(153, 0, 102);">class</span> Item <span style="font-weight: bold; color: rgb(153, 0, 102);">implements</span><span style="color: rgb(170, 170, 221);">Serializable</span><span style="color: rgb(0, 0, 0);">{</span><br />    <span style="color: rgb(102, 102, 255);">//  所有的属性和getter/setter方法都省略</span><br />   <span style="font-weight: bold; color: rgb(153, 0, 102);">private</span><span style="font-weight: bold; color: rgb(153, 0, 102);">static</span> ItemDao itemDao; 
<br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span><span style="font-weight: bold; color: rgb(153, 0, 102);">void</span> 
setItemDao<span style="color: rgb(0, 0, 0);">(</span>ItemDao itemDao<span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span>this.<span style="color: rgb(0, 0, 0);">itemDao</span> = itemDao;<span style="color: rgb(0, 0, 0);">}</span><br />    <br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span><span style="font-weight: bold; color: rgb(153, 0, 102);">static</span> Item 
loadItemById<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(170, 170, 221);">Long</span> id<span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />        <span style="font-weight: bold; color: rgb(153, 0, 102);">return</span><span style="color: rgb(0, 0, 0);">(</span>Item<span style="color: rgb(0, 0, 0);">)</span> itemDao.<span style="color: rgb(0, 0, 0);">loadItemById</span><span style="color: rgb(0, 0, 0);">(</span>id<span style="color: rgb(0, 0, 0);">)</span>; 
<br />    <span style="color: rgb(0, 0, 0);">}</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span><span style="font-weight: bold; color: rgb(153, 0, 102);">static</span><span style="color: rgb(170, 170, 221);">Collection</span> findAll<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />        <span style="font-weight: bold; color: rgb(153, 0, 102);">return</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(170, 170, 221);">List</span><span style="color: rgb(0, 0, 0);">)</span> itemDao.<span style="color: rgb(0, 0, 0);">findAll</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>; 
<br />    <span style="color: rgb(0, 0, 0);">}</span><br /><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">public</span> Bid placeBid<span style="color: rgb(0, 0, 0);">(</span>User bidder, MonetaryAmount bidAmount, <br />    
                Bid currentMaxBid, Bid currentMinBid<span style="color: rgb(0, 0, 0);">)</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">throws</span> BusinessException 
<span style="color: rgb(0, 0, 0);">{</span><br />    <br />        <span style="color: rgb(102, 102, 255);">// Check highest bid (can also be a different 
Strategy (pattern))</span><br />        <span style="font-weight: bold; color: rgb(153, 0, 102);">if</span><span style="color: rgb(0, 0, 0);">(</span>currentMaxBid != <span style="font-weight: bold; color: rgb(153, 0, 102);">null</span> &amp;&amp; 
currentMaxBid.<span style="color: rgb(0, 0, 0);">getAmount</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>.<span style="color: rgb(0, 0, 0);">compareTo</span><span style="color: rgb(0, 0, 0);">(</span>bidAmount<span style="color: rgb(0, 0, 0);">)</span> &gt; <span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />                throw <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span> 
BusinessException<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">"Bid too low."</span><span style="color: rgb(0, 0, 0);">)</span>; <br />        <span style="color: rgb(0, 0, 0);">}</span><br />        <br />        <span style="color: rgb(102, 102, 255);">// Auction is active</span><br />        <span style="font-weight: bold; color: rgb(153, 0, 102);">if</span><span style="color: rgb(0, 0, 0);">(</span> !state.<span style="color: rgb(0, 0, 0);">equals</span><span style="color: rgb(0, 0, 0);">(</span>ItemState.<span style="color: rgb(0, 0, 0);">ACTIVE</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">)</span><br />                throw <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span> 
BusinessException<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">"Auction is not active yet."</span><span style="color: rgb(0, 0, 0);">)</span>; <br />        <br />        <span style="color: rgb(102, 102, 255);">// Auction still valid</span><br />        <span style="font-weight: bold; color: rgb(153, 0, 102);">if</span><span style="color: rgb(0, 0, 0);">(</span> this.<span style="color: rgb(0, 0, 0);">getEndDate</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>.<span style="color: rgb(0, 0, 0);">before</span><span style="color: rgb(0, 0, 0);">(</span><span style="font-weight: bold; color: rgb(153, 0, 102);">new</span><span style="color: rgb(170, 170, 221);">Date</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">)</span><br />                throw <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span> 
BusinessException<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">"Can't place new bid, auction already 
ended."</span><span style="color: rgb(0, 0, 0);">)</span>; <br />        <br />        
<span style="color: rgb(102, 102, 255);">// Create new Bid</span><br />        Bid 
newBid = <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span> 
Bid<span style="color: rgb(0, 0, 0);">(</span>bidAmount, this, bidder<span style="color: rgb(0, 0, 0);">)</span>; <br />        <br />        <span style="color: rgb(102, 102, 255);">// Place bid for this Item</span><br />        
this.<span style="color: rgb(0, 0, 0);">addBid</span><span style="color: rgb(0, 0, 0);">(</span>newBid<span style="color: rgb(0, 0, 0);">)</span>; <br />        itemDao.<span style="color: rgb(0, 0, 0);">update</span><span style="color: rgb(0, 0, 0);">(</span>this<span style="color: rgb(0, 0, 0);">)</span>;  
    <span style="color: rgb(102, 102, 255);">//  调用DAO进行显式持久化</span><br />        
<span style="font-weight: bold; color: rgb(153, 0, 102);">return</span> newBid; 
<br />    <span style="color: rgb(0, 0, 0);">}</span><br /><span style="color: rgb(0, 0, 0);">}</span></font>
										</div>
										<br />
								</td>
						</tr>
				</tbody>
		</table>
		<span>
				<br />
				<br />在这种模型中，所有的业务逻辑全部都在Item中，事务管理也在Item中实现。</span>
		<p> </p>
		<p> </p>
		<p>
				<span>在上面三种模型之外，还有很多这三种模型的变种，例如partech的模型就是把第二种模型中的DAO和 
Manager三个类合并为一个类后形成的模型；例如frain....(id很长记不住)的模型就是把第三种模型的三个类完全合并为一个单类后形成的模型；例如Archie是把第三种模型的Item又分出来一些纯数据类(可能是，不确定)形成的一个模型。 
<br /><br />但是不管怎么变，基本模型归纳起来就是上面的三种模型，下面分别简单评价一下： 
<br /><br />第一种模型绝大多数人都反对，因此反对理由我也不多讲了。但遗憾的是，我观察到的实际情形是，很多使用Hibernate的公司最后都是这种模型，这里面有很大的原因是很多公司的技术水平没有达到这种层次，所以导致了这种贫血模型的出现。从这一点来说，Martin 
Fowler的批评声音不是太响了，而是太弱了，还需要再继续呐喊。 <br /><br />第二种模型就是Martin 
Fowler一直主张的模型，实际上也是我一直在实际项目中采用这种模型。我没有看过Martin的POEAA，之所以能够自己摸索到这种模型，也是因为从02年我已经开始思考这个问题并且寻求解决方案了，但是当时没有看到Hibernate，那时候做的一个小型项目我已经按照这种模型来做了，但是由于没有O/R 
Mapping的支持，写到后来又不得不全部改成贫血的domain 
object，项目做完以后再继续找，随后就发现了Hibernate。当然，现在很多人一开始就是用Hibernate做项目，没有经历过我经历的那个阶段。 
<br /><br />不过我觉得这种模型仍然不够完美，因为你还是需要一个业务逻辑层来封装所有的domain 
logic，这显得非常罗嗦，并且业务逻辑对象的接口也不够稳定。如果不考虑业务逻辑对象的重用性的话(业务逻辑对象的可重用性也不可能好)，很多人干脆就去掉了xxxManager这一层，在Web层的Action代码直接调用xxxDao，同时容器事务管理配置到Action这一层上来。 
Hibernate的caveatemptor就是这样架构的一个典型应用。 <br /><br />第三种模型是我很反对的一种模型，这种模型下面，Domain 
Object和DAO形成了双向依赖关系，无法脱离框架测试，并且业务逻辑层的服务也和持久层对象的状态耦合到了一起，会造成程序的高度的复杂性，很差的灵活性和糟糕的可维护性。也许将来技术进步导致的O/R 
Mapping管理下的domain object发展到足够的动态持久透明化的话，这种模型才会成为一个理想的选择。就像O/R 
Mapping的流行使得第二种模型成为了可能(O/R Mapping流行以前，我们只能用第一种模型，第二种模型那时候是不现实的)。</span>
		</p>
		<p> </p>
		<p> </p>
		<p>
				<span>既然大家都统一了观点，那么就有了一个很好的讨论问题的基础了。Martin Fowler的Domain 
Model，或者说我们的第二种模型难道是完美无缺的吗？当然不是，接下来我就要分析一下它的不足，以及可能的解决办法，而这些都来源于我个人的实践探索。 
<br /><br />在第二种模型中，我们可以清楚的把这4个类分为三层： <br /><br />1、实体类层，即Item，带有domain logic的domain 
object <br />2、DAO层，即ItemDao和ItemDaoHibernateImpl，抽象持久化操作的接口和实现类 
<br />3、业务逻辑层，即ItemManager，接受容器事务控制，向Web层提供统一的服务调用 <br /><br />在这三层中我们大家可以看到，domain 
object和DAO都是非常稳定的层，其实原因也很简单，因为domain object是映射数据库字段的，数据库字段不会频繁变动，所以domain 
object也相对稳定，而面向数据库持久化编程的DAO层也不过就是CRUD而已，不会有更多的花样，所以也很稳定。 
<br /><br />问题就在于这个充当business workflow facade的业务逻辑对象，它的变动是相当频繁的。<span style="color: red;">业务逻辑对象通常都是无状态的、受事务控制的、Singleton类</span>，我们可以考察一下业务逻辑对象都有哪几类业务逻辑方法： 
<br /><br /><span style="color: red;">第一类：DAO接口方法的代理</span>，就是上面例子中的loadItemById方法和findAll方法。 
<br /><br />ItemManager之所以要代理这种类，目的有两个：<span style="color: red;">向Web层提供统一的服务调用入口点和给持久化方法增加事务控制功能</span>。这两点都很容易理解，你不能既给Web层程序员提供xxxManager，也给他提供xxxDao，所以你需要用xxxManager封装xxxDao，在这里，充当了一个简单代理功能；而事务控制也是持久化方法必须的，事务可能需要跨越多个DAO方法调用，所以必须放在业务逻辑层，而不能放在DAO层。 
<br /><br />但是必须看到，对于一个典型的web应用来说，绝大多数的业务逻辑都是简单的CRUD逻辑，所以这种情况下，针对每个DAO方法，xxxManager都需要提供一个对应的封装方法，这不但是非常枯燥的，也是令人感觉非常不好的。 
<br /><br /><br /><span style="color: red;">第二类：domain 
logic的方法代理</span>。就是上面例子中placeBid方法。虽然Item已经有了placeBid方法，但是ItemManager仍然需要封装一下Item的placeBid，然后再提供一个简单封装之后的代理方法。 
<br /><br />这和第一种情况类似，其原因也一样，也是为了给Web层提供一个统一的服务调用入口点和给隐式的持久化动作提供事务控制。 
<br /><br />同样，和第一种情况一样，针对每个domain logic方法，xxxManager都需要提供一个对应的封装方法，同样是枯燥的，令人不爽的。 
<br /><br /><br /><span style="color: red;">第三类：需要多个domain object和DAO参与协作的business 
workflow</span>。这种情况是业务逻辑对象真正应该完成的职责。 
<br /><br />在这个简单的例子中，没有涉及到这种情况，不过大家都可以想像的出来这种应用场景，因此不必举例说明了。 
<br /><br />通过上面的分析可以看出，只有第三类业务逻辑方法才是业务逻辑对象真正应该承担的职责，而前两类业务逻辑方法都是“无奈之举”，不得不为之的事情，不但枯燥，而且令人沮丧。 
<br /><br /><br /><br /><br />分析完了业务逻辑对象，我们再回头看一下domain object，我们要仔细考察一下domain 
logic的话，会发现domain logic也分为两类： <br /><br /><span style="color: red;">第一类：需要持久层框架隐式的实现透明持久化的domain 
logic</span>，例如Item的placeBid方法中的这一句： <br /></span>
		</p>
		<table align="center" border="0" cellpadding="3" cellspacing="1" width="90%">
				<tbody>
						<tr>
								<td>
										<span>
												<b>java代码: </b>
										</span>
								</td>
						</tr>
						<tr>
								<td>
										<div style="font-family: 'Courier New',Courier,monospace;">
												<br />this.<font face="Courier New"><span style="color: rgb(0, 0, 0);">getBids</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>.<span style="color: rgb(0, 0, 0);">add</span><span style="color: rgb(0, 0, 0);">(</span>newBid<span style="color: rgb(0, 0, 0);">)</span></font>;</div>
										<br />
								</td>
						</tr>
				</tbody>
		</table>
		<span>
				<br />上面已经着重提到，虽然这仅仅只是一个Java集合的添加新元素的操作，但是实际上通过事务的控制，会潜在的触发两条SQL：一条是insert一条记录到bid表，一条是更新item表相应的记录。如果我们让Item脱离Hibernate进行单元测试，它就是一个单纯的Java集合操作，如果我们把他加入到Hibernate框架中，他就会潜在的触发两条SQL，<span style="color: red;">这就是隐式的依赖于持久化的domain logic</span>。 
<br />特别请注意的一点是：在没有Hibernate/JDO这类可以实现“透明的持久化”工具出现之前，这类domain logic是无法实现的。 
<br /><br />对于这一类domain logic，业务逻辑对象必须提供相应的封装方法，以实现事务控制。 <br /><br /><br /><span style="color: red;">第二类：完全不依赖持久化的domain logic</span>，例如readonly例子中的Topic，如下： 
<br /><br /></span>
		<table align="center" border="0" cellpadding="3" cellspacing="1" width="90%">
				<tbody>
						<tr>
								<td>
										<span>
												<b>java代码: </b>
										</span>
								</td>
						</tr>
						<tr>
								<td>
										<div style="font-family: 'Courier New',Courier,monospace;">
												<br />
												<font face="Courier New">
														<span style="font-weight: bold; color: rgb(153, 0, 102);">class</span> Topic <span style="color: rgb(0, 0, 0);">{</span><br />    <span style="font-weight: bold; color: rgb(153, 0, 102);">boolean</span> 
isAllowReply<span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">{</span><br />        <span style="color: rgb(170, 170, 221);">Calendar</span> dueDate = 
<span style="color: rgb(170, 170, 221);">Calendar</span>.<span style="color: rgb(0, 0, 0);">getInstance</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>; 
<br />        dueDate.<span style="color: rgb(0, 0, 0);">setTime</span><span style="color: rgb(0, 0, 0);">(</span>lastUpdatedTime<span style="color: rgb(0, 0, 0);">)</span>; <br />        dueDate.<span style="color: rgb(0, 0, 0);">add</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(170, 170, 221);">Calendar</span>.<span style="color: rgb(0, 0, 0);">DATE</span>, forum.<span style="color: rgb(0, 0, 0);">timeToLive</span><span style="color: rgb(0, 0, 0);">)</span>; <br />    <br />        <span style="color: rgb(170, 170, 221);">Date</span> now = <span style="font-weight: bold; color: rgb(153, 0, 102);">new</span><span style="color: rgb(170, 170, 221);">Date</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>; 
<br />        <span style="font-weight: bold; color: rgb(153, 0, 102);">return</span> 
now.<span style="color: rgb(0, 0, 0);">after</span><span style="color: rgb(0, 0, 0);">(</span>dueDate.<span style="color: rgb(0, 0, 0);">getTime</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">)</span>; <br />    <span style="color: rgb(0, 0, 0);">}</span><br /><span style="color: rgb(0, 0, 0);">}</span></font>
										</div>
										<br />
								</td>
						</tr>
				</tbody>
		</table>
		<span>
				<br />
				<br />注意这个isAllowReply方法，他和持久化完全不发生一丁点关系。在实际的开发中，我们同样会遇到很多这种不需要持久化的业务逻辑(主要发生在日期运算、数值运算和枚举运算方面)，这种domain 
logic不管脱离不脱离所在的框架，它的行为都是一致的。对于这种domain 
logic，业务逻辑层并不需要提供封装方法，它可以适用于任何场合。</span>
<img src ="http://www.blogjava.net/GandofYan/aggbug/48954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/GandofYan/" target="_blank">混沌中立</a> 2006-05-30 13:31 <a href="http://www.blogjava.net/GandofYan/archive/2006/05/30/48954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]O/R Mapping 基本概念</title><link>http://www.blogjava.net/GandofYan/archive/2006/05/30/48945.html</link><dc:creator>混沌中立</dc:creator><author>混沌中立</author><pubDate>Tue, 30 May 2006 05:20:00 GMT</pubDate><guid>http://www.blogjava.net/GandofYan/archive/2006/05/30/48945.html</guid><wfw:comment>http://www.blogjava.net/GandofYan/comments/48945.html</wfw:comment><comments>http://www.blogjava.net/GandofYan/archive/2006/05/30/48945.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/GandofYan/comments/commentRss/48945.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/GandofYan/services/trackbacks/48945.html</trackback:ping><description><![CDATA[
		<div>
				<br />原文地址：<a href="http://www.cnblogs.com/idior/archive/2005/07/04/186086.html"><u><font color="#0000ff">http://www.cnblogs.com/idior/archive/2005/07/04/186086.html</font></u></a><br /><br />近日 有关o/r m的讨论突然多了起来. 在这里觉得有必要澄清一些概念, 免的大家讨论来讨论去, 才发现最根本的理解有问题.<br /><br />1. 何谓实体?<br />实体(类似于j2ee中的Entity Bean)通常指一个承载数据的对象, 但是注意它也是可以有行为的! 只不过它的行为一般只操作自身的数据. 比如下面这个例子:<br /><br /><br />class Person<br />{<br />  string firstName;<br />  string lastName;<br /><br />  public void GetName()<br />  {<br />     return  lastName+firstName;<br />  }   <br />}<br /><br /><br />GetName就是它的一个行为.<br /><br />2 何谓对象?<br />对象最重要的特性在于它拥有行为. 仅仅拥有数据,你可以称它为对象, 但是它却失去它最重要的灵魂. <br /><br /><br />class Person<br />{<br />  string firstName;<br />  string lastName;<br />  Role role;<br />  int baseWage;<br />  public void GetSalary()<br />  {<br />     return baseWage*role.GetFactory();<br />  }   <br />}<br /><br />这样需要和别的对象(不是Value Object)打交道的对象,我就不再称其为实体. 领域模型就是指由这些具有业务逻辑的对象构成的模型.<br /><br />3. E/R M or O/R M?!!<br />仔细想想我们为什么需要o/r m,无非是想利用oo的多态来处理复杂的业务逻辑, 而不是靠一堆的if else. <br />而现在在很多人的手上o/r m全变成了e/r m.他们不考虑对象的行为, 而全关注于如何保存数据.这样也难怪他们会产生将CRUD这些操作放入对象中的念头. 如果你不能深刻理解oo, 那么我不推荐你使用o/r m, Table Gateway, Row Gateway才是你想要的东西.<br /><br /><br />作为一个O/R M框架，很重要的一点就是实现映射的透明性（Transparent），比较显著的特点就是在代码中我们是看不到SQL语句的（框架自动生成了）。这里所指的O/R M就是类似于此的框架，<br /><br />4. POEAA中的相关概念<br />  很多次发现有人错用其中的概念, 这里顺便总结一下:<br />  1. Table Gateway<br />    以表为单位的实体,基本没有行为,只有CRUD操作.<br />  2. Row Gateway<br />    以行为单位的实体,基本没有行为,只有CRUD操作.<br />  3. Active Record<br />    以行为单位的实体,拥有一些基本的操作自身数据的行为(如上例中的GetName),同时包含有CRUD操作.<br />其实Active Record最符合某些简单的需求, 接近于E/R m.<br />通常也有很多人把它当作O/R m.不过需要注意的是Active Record中是充满了SQL语句的(不像orm的SQL透明), 所以有人想起来利用O/R m来实现"Active Record", 虽然在他们眼里看起来很方便, 其实根本就是返祖.<br />用CodeGenerator来实现Active Record也许是一个比较好的方法.<br />  4. Data Mapper<br />这才是真正的O/R m,Hibernate等等工具的目标.<br /><br />5.O/R M需要关注的地方 (希望大家帮忙完善一下)<br /> 1. 关联, O/R M是如何管理类之间的关联.当然这不仅于o/r m有关与设计者的设计水平也有很大关系.<br /> 2. O/R M对继承关系的处理.<br /> 3. O/R M对事务的支持.<br /> 4. O/R M对查询的支持.<br /> <br />以上观点仅属个人意见, 不过在大家讨论有关O/R m之前, 希望先就一些基本概念达成共识, 不然讨论下去会越离越远. <br /><br /><br />(建议: 如果对oo以及dp没有一定程度的了解, 最好别使用o/r m, dataset 加上codesmith或许是更好的选择)<br /><a href="http://www.cnblogs.com/idior/archive/2005/07/04/186086.html"><u><font color="#0000ff"></font></u></a></div>
<img src ="http://www.blogjava.net/GandofYan/aggbug/48945.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/GandofYan/" target="_blank">混沌中立</a> 2006-05-30 13:20 <a href="http://www.blogjava.net/GandofYan/archive/2006/05/30/48945.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>面向对象设计的基本原则(转)</title><link>http://www.blogjava.net/GandofYan/archive/2006/04/09/40087.html</link><dc:creator>混沌中立</dc:creator><author>混沌中立</author><pubDate>Sun, 09 Apr 2006 06:06:00 GMT</pubDate><guid>http://www.blogjava.net/GandofYan/archive/2006/04/09/40087.html</guid><wfw:comment>http://www.blogjava.net/GandofYan/comments/40087.html</wfw:comment><comments>http://www.blogjava.net/GandofYan/archive/2006/04/09/40087.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/GandofYan/comments/commentRss/40087.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/GandofYan/services/trackbacks/40087.html</trackback:ping><description><![CDATA[
		<font size="2">
				<span style="font-size: 32pt; font-family: 宋体;">
						<span style="font-size: 10pt;">
								<span style="font-size: 32pt; font-family: 宋体;">
										<span style="font-size: 32pt; font-family: 宋体;">
												<span style="font-size: 10pt;">
														<span lang="EN-US">
																<b>
																		<span>最近在看&lt;</span>
																</b>
														</span>
												</span>
										</span>
								</span>
						</span>
				</span>
				<b>敏捷软件开发：原则、模式与实践</b>
		</font>
		<span style="font-size: 32pt; font-family: 宋体;">
				<span style="font-size: 10pt;">
						<span style="font-size: 32pt; font-family: 宋体;">
								<span style="font-size: 32pt; font-family: 宋体;">
										<span style="font-size: 10pt;">
												<span lang="EN-US">
														<b>
																<span>
																		<font size="2">&gt;在网上找了一些资料,就把他们集合到了一起,便于自己学习</font>
																		<br />
																		<br />此篇内容来自一下两处<br /><br />http://blog.joycode.com/microhelper/archive/2004/11/30/40013.aspx<br /><br />http://www.blogjava.net/ghawk/<br /><br />另:关于面向对象设计的原则比较权威的是Uncle Bob--</span>
														</b>
												</span>
										</span>
								</span>
						</span>
				</span>
		</span>
Robert C. Martin的<br /><h1><font size="2"><a href="http://c2.com/cgi/fullSearch">Principles Of Object Oriented Design</a></font></h1>http://c2.com/cgi/wiki?PrinciplesOfObjectOrientedDesign<br /><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 10pt;"><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 10pt;"><span lang="EN-US"><b><span><br /><br />单一职责原则</span><span lang="EN-US">——SRP <br /></span></b></span></span></span></span></span></span><font face="Courier New" size="2">就一个类而言，应该仅有一个引起它的变化的原因</font><div> </div><div><strong><font face="Courier New" size="2">原则</font></strong></div><div><br /><font face="Courier New" size="2">最简单，最单纯的事情最容易控制，最有效<br />类的职责简单而且集中，避免相同的职责分散到不同的类之中，避免一个类承担过多的职责<br />减少类之间的耦合<br />当需求变化时，只修改一个地方</font></div><div><br /><strong><font face="Courier New" size="2">组件</font></strong></div><div><strong><br /></strong><font face="Courier New" size="2">每个组件集中做好一件事情<br />组件的颗粒度<br />发布的成本<br />可重用的成本</font></div><div> </div><div><strong><font face="Courier New" size="2">方法</font></strong></div><div><strong></strong><br /><font face="Courier New" size="2">避免写臃肿的方法<br />Extract Method</font></div><div> </div><div><strong><font face="Courier New" size="2">重构</font></strong></div><div><strong></strong><br /><font face="Courier New" size="2">Move Field/Move Class<br />Extract Method/Extract Class</font></div><div> </div><div><font face="Courier New" size="2">最简单的，也是最难以掌握的原则</font></div><div> </div><div><strong><font face="Courier New" size="2">实例分析</font></strong></div><div><strong></strong><br /><font face="Courier New" size="2"><br /></font>单一职责很容易理解，也很容易实现。所谓单一职责，就是一个设计元素只做一件事。什么是“只做一件事”？简单说就是少管闲事。现实中就是如此，如果要你专心做一件事情，任何人都有信心可以做得很出色。但如果，你整天被乱七八糟的事所累，还有心思和精力把每件事都作好么？<br /><img alt="fig-1.JPG" src="../../images/blogjava_net/ghawk/OOD/fig-1.JPG" align="left" border="0" height="250" width="127" /><br />     
“单一职责”就是要在设计中为每种职责设计一个类，彼此保持正交，互不干涉。这个雕塑（二重奏）就是正交的一个例子，钢琴家和小提琴家各自演奏自己的乐
谱，而结果就是一个和谐的交响乐。当然，真实世界中，演奏小提琴和弹钢琴的必须是两个人，但是在软件中，我们往往会把两者甚至更多搅和到一起，很多时候只
是为了方便或是最初设计的时候没有想到。 <br /><br />      这样的例子在设计中很常见，书中就给了一个很好的例子：调制解调器。这是一个调制
解调器最基本的功能。但是这个类事实上完成了两个职责：连接的建立和中断、数据的发送和接收。显然，这违反了SRP。这样做会有潜在的问题：当仅需要改变
数据连接方式时，必须修改Modem类，而修改Modem类的结果就是使得任何依赖Modem类的元素都需要重新编译，不管它是不是用到了数据连接功能。
解决的办法，书中也已经给出：重构Modem类，从中抽出两个接口，一个专门负责连接、另一个专门负责数据发送。依赖Modem类的元素也要做相应的细
化，根据职责的不同分别依赖不同的接口。最后由ModemImplementation类实现这两个接口。<br /><img alt="fig-2.JPG" src="../../images/blogjava_net/ghawk/OOD/fig-2.JPG" border="0" height="258" width="661" />
      从这个例子中，我们不难发现，违反SRP通常是由于过于“真实”地设计了一个类所造成的。因此，解决办法是往更高一层进行抽象
化提取，将对某个具体类的依赖改变为对一组接口或抽象类的依赖。当然，这个抽象化的提取应该根据需要设计，而不是盲目提取。比如刚才这个Modem的例子
中，如果有必要，还可以把DataChannel抽象为DataSender和DataReceiver两个接口。<br /></div><br /><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 10pt;"><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 10pt;"><span lang="EN-US"><b><span lang="EN-US"><br /></span></b><b><span>开放封闭原则</span><span lang="EN-US">——OCP <br /></span></b></span></span></span></span></span></span><font face="Courier New" size="2">软件实体（类，模块，函数）应该是可以扩展的，但是不可修改的</font><div> </div><div><strong><font face="Courier New" size="2">原则</font></strong></div><div><strong></strong> </div><div><font face="Courier New" size="2">对扩展是开放的，当需求改变时我们可以对模块进行扩展，使其具有新的功能<br />对更改是封闭的，对模块扩展时，不需要改动原来的代码<br />面对抽象而不是面对细节，抽象比细节活的更长<br />僵化的设计——如果程序中一处改动产生连锁反应。</font></div><div><br /><strong><font face="Courier New" size="2">方法</font></strong></div><div><strong><br /></strong><font face="Courier New" size="2">条件case   if/else 语句</font></div><div> </div><div><strong><font face="Courier New" size="2">重构</font></strong></div><div><strong></strong><br /><font face="Courier New" size="2">Replace Type Code With Class<br />Replace Type Code With State/Strategy<br />Replace Conditional with polymorphism</font></div><div> </div><div><strong><font face="Courier New" size="2">实例</font></strong></div><br /><p>开闭原则很简单，一句话：“Closed for Modification; Open for Extension”——“对变更关闭；对扩展开放”。开闭原则其实没什么好讲的，我将其归结为一个高层次的设计总则。就这一点来讲，OCP的地位应该比SRP优先。 
</p><p>OCP的动机很简单：软件是变化的。不论是优质的设计还是低劣的设计都无法回避这一问题。OCP说明了软件设计应该尽可能地使架构稳定而又容易满足不同的需求。 
</p><p>为什么要OCP？答案也很简单——重用。 
</p><p>“重用”，并不是什么软件工程的专业词汇，它是工程界所共用的词汇。早在软件出现前，工程师们就在实践“重用”了。比如机械产品，通过零部
件的组装得到最终的能够使用的工具。由于机械部件的设计和制造过程是极其复杂的，所以互换性是一个重要的特性。一辆车可以用不同的发动机、不同的变速箱、
不同的轮胎……很多东西我们直接买来装上就可以了。这也是一个OCP的例子。（可能是由于我是搞机械出身的吧，所以就举些机械方面的例子^_^）。 </p><p>如何在OO中引入OCP原则？把对实体的依赖改为对抽象的依赖就行了。下面的例子说明了这个过程：</p><p>05赛季的时候，一辆F1赛车有一台V10引擎。但是到了06赛季，国际汽联修改了规则，一辆F1赛车只能安装一台V8引擎。车队很快投入了新赛车
的研发，不幸的是，从工程师那里得到消息，旧车身的设计不能够装进新研发的引擎。我们不得不为新的引擎重新打造车身，于是一辆新的赛车诞生了。但是，麻烦
的事接踵而来，国际汽联频频修改规则，搞得设计师在“赛车”上改了又改，最终变得不成样子，只能把它废弃。 </p><p><img alt="OCP-fig1.JPG" src="../../images/blogjava_net/ghawk/OOD/OCP-fig1.JPG" border="0" height="183" width="437" /></p><p>为了能够重用这辆昂贵的赛车，工程师们提出了解决方案：首先，在车身的设计上预留出安装引擎的位置和管线。然后，根据这些设计好的规范设计引擎（或是引擎的适配器）。于是，新的赛车设计方案就这样诞生了。 
</p><p> <img alt="OCP-fig2.JPG" src="../../images/blogjava_net/ghawk/OOD/OCP-fig2.JPG" border="0" height="441" width="646" /></p>显然，通过重构，这里应用的是一个典型的Bridge模式。这个实现的关键之处在于我们预先给引擎留出了位置！我们不必因为对引擎的规则的频频变更而制造相当多的车身，而是尽可能地沿用和改良现有的车身。<br />说到这里，想说一说OO设计的一个误区。<br />学
习OO语言的时候，为了能够说明“继承”（或者说“is-a”）这个概念，教科书上经常用实际生活中的例子来解释。比如汽车是车，电车是车，F1赛车是汽
车，所以车是汽车、电车、F1赛车的上层抽象。这个例子并没有错。问题是，这样的例子过于“形象”了！如果OO设计直接就可以将现实生活中的概念引用过
来，那也就不需要什么软件工程师了！OO设计的关键概念是抽象。如果没有抽象，那所有的软件工程师的努力都是徒劳的。因为如果没有抽象，我们只能去构造世
界中每一个对象。上面这个例子中，我们应该看到“引擎”这个抽象的存在，因为车队的工程师们为它预留了位置，为它制定了设计规范。<br />上面这个设计也
实现了后面要说的DIP（依赖倒置原则）。但是请记住，OCP是OO设计原则中高层次的原则，其余的原则对OCP提供了不同程度的支持。为了实现OCP，
我们会自觉或者不自觉地用到其它原则或是诸如Bridge、Decorator等设计模式。然而，对于一个应用系统而言，实现OCP并不是设计目的，我们
所希望的只是一个稳定的架构。所以对OCP的追求也应该适可而止，不要陷入过渡设计。正如Martin本人所说：“No significant
program can be 100% closed.”“Closure not complete but strategic”<span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 10pt;"><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 10pt;"><span lang="EN-US"><b><span lang="EN-US"></span></b><p><b><span lang="EN-US">Liskov</span></b><b><span>替换原则</span></b><b><span>——</span><span lang="EN-US"> LSP </span></b><b><span lang="EN-US"><br /></span></b></p></span></span></span></span></span></span><p><font face="Courier New" size="2">子类型必须能够替换它的基类型</font></p><div><strong><font face="Courier New" size="2">原则</font></strong></div><div><strong><br /></strong><font face="Courier New" size="2">主要针对继承的设计原则<br />所有派生类的行为功能必须和客户程序对其基类所期望的保持一致。<br />派生类必须满足基类和客户程序的约定<br />IS-A是关于行为方式的，依赖客户程序的调用方式</font></div><div> </div><div><strong><font face="Courier New" size="2">重构</font></strong></div><div><strong></strong><br /><font face="Courier New" size="2">Extract Supper Class</font></div><div> </div><div><strong><font face="Courier New" size="2">实例</font></strong></div><strong></strong><div><br /><font face="Courier New" size="2">长方形和正方形<br /></font><p>OCP作为OO的高层原则，主张使用“抽象(Abstraction)”和“多态(Polymorphism)”将设计中的静态结构改为动态结构，维持设计的封闭性。 
</p><p>“抽象”是语言提供的功能。“多态”由继承语义实现。 
</p><p>如此，问题产生了：“我们如何去度量继承关系的质量？” 
</p><p>Liskov于1987年提出了一个关于继承的原则“Inheritance should ensure that any
property proved about supertype objects also holds for subtype
objects.”——“继承必须确保超类所拥有的性质在子类中仍然成立。”也就是说，当一个子类的实例应该能够替换任何其超类的实例时，它们之间才具有
is-A关系。 </p><p>该原则称为Liskov Substitution Principle——里氏替换原则。林先生在上课时风趣地称之为“老鼠的儿子会打洞”。^_^ 
</p><p>我们来研究一下LSP的实质。学习OO的时候，我们知道，一个对象是一组状态和一系列行为的组合体。状态是对象的内在特性，行为是对象的外在特性。LSP所表述的就是在同一个继承体系中的对象应该有共同的行为特征。 
</p><p>这一点上，表明了OO的继承与日常生活中的继承的本质区别。举一个例子：生物学的分类体系中把企鹅归属为鸟类。我们模仿这个体系，设计出这样的类和关系。 
</p><p> <img alt="lsp-fig1.jpg" src="../../images/blogjava_net/ghawk/OOD/lsp-fig1.jpg" border="0" height="283" width="451" /></p><p>类“鸟”中有个方法fly，企鹅自然也继承了这个方法，可是企鹅不能飞阿，于是，我们在企鹅的类中覆盖了fly方法，告诉方法的调用者：企
鹅是不会飞的。这完全符合常理。但是，这违反了LSP，企鹅是鸟的子类，可是企鹅却不能飞！需要注意的是，此处的“鸟”已经不再是生物学中的鸟了，它是软
件中的一个类、一个抽象。 </p><p>有人会说，企鹅不能飞很正常啊，而且这样编写代码也能正常编译，只要在使用这个类的客户代码中加一句判断就行了。但是，这就是问题所
在！首先，客户代码和“企鹅”的代码很有可能不是同时设计的，在当今软件外包一层又一层的开发模式下，你甚至根本不知道两个模块的原产地是哪里，也就谈不
上去修改客户代码了。客户程序很可能是遗留系统的一部分，很可能已经不再维护，如果因为设计出这么一个“企鹅”而导致必须修改客户代码，谁应该承担这部分
责任呢？（大概是上帝吧，谁叫他让“企鹅”不能飞的。^_^）“修改客户代码”直接违反了OCP，这就是OCP的重要性。违反LSP将使既有的设计不能封
闭！ </p><p>修正后的设计如下： 
</p><p> <img alt="lsp-fig2.jpg" src="../../images/blogjava_net/ghawk/OOD/lsp-fig2.jpg" border="0" height="353" width="498" /></p><p>但是，这就是LSP的全部了么？书中给了一个经典的例子，这又是一个不符合常理的例子：正方形不是一个长方形。这个悖论的详细内容能在网上找到，我就不多废话了。 
</p><p>LSP并没有提供解决这个问题的方案，而只是提出了这么一个问题。 
</p><p>于是，工程师们开始关注如何确保对象的行为。1988年，B. Meyer提出了Design by Contract（契约式设计）理论。DbC从形式化方法中借鉴了一套确保对象行为和自身状态的方法，其基本概念很简单： 
</p><ol><li>每个方法调用之前，该方法应该校验传入参数的正确性，只有正确才能执行该方法，否则认为调用方违反契约，不予执行。这称为前置条件(Pre-condition)。 
</li><li>一旦通过前置条件的校验，方法必须执行，并且必须确保执行结果符合契约，这称之为后置条件(Post-condition)。 
</li><li>对象本身有一套对自身状态进行校验的检查条件，以确保该对象的本质不发生改变，这称之为不变式(Invariant)。</li></ol><p>以上是单个对象的约束条件。为了满足LSP，当存在继承关系时，子类中方法的前置条件必须与超类中被覆盖的方法的前置条件相同或者更宽松；而子类中方法的后置条件必须与超类中被覆盖的方法的后置条件相同或者更为严格。 
</p><p>一些OO语言中的特性能够说明这一问题： 
</p><ul><li>继承并且覆盖超类方法的时候，子类中的方法的可见性必须等于或者大于超类中的方法的可见性，子类中的方法所抛出的受检异常只能是超类中对应方法所抛出的受检异常的子类。 
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img id="Codehighlighter1_23_72_Open_Image" onclick="this.style.display='none'; Codehighlighter1_23_72_Open_Text.style.display='none'; Codehighlighter1_23_72_Closed_Image.style.display='inline'; Codehighlighter1_23_72_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_23_72_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_23_72_Closed_Text.style.display='none'; Codehighlighter1_23_72_Open_Image.style.display='inline'; Codehighlighter1_23_72_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> SuperClass</span><span id="Codehighlighter1_23_72_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif" /></span><span id="Codehighlighter1_23_72_Open_Text"><span style="color: rgb(0, 0, 0);">{<br /><img id="Codehighlighter1_69_70_Open_Image" onclick="this.style.display='none'; Codehighlighter1_69_70_Open_Text.style.display='none'; Codehighlighter1_69_70_Closed_Image.style.display='inline'; Codehighlighter1_69_70_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_69_70_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_69_70_Closed_Text.style.display='none'; Codehighlighter1_69_70_Open_Image.style.display='inline'; Codehighlighter1_69_70_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> methodA() </span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);"> IOException</span><span id="Codehighlighter1_69_70_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif" /></span><span id="Codehighlighter1_69_70_Open_Text"><span style="color: rgb(0, 0, 0);">{}</span></span><span style="color: rgb(0, 0, 0);"><br /><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: rgb(0, 0, 0);"><br /><img src="../../Images/OutliningIndicators/None.gif" align="top" /><br /><img id="Codehighlighter1_116_198_Open_Image" onclick="this.style.display='none'; Codehighlighter1_116_198_Open_Text.style.display='none'; Codehighlighter1_116_198_Closed_Image.style.display='inline'; Codehighlighter1_116_198_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_116_198_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_116_198_Closed_Text.style.display='none'; Codehighlighter1_116_198_Open_Image.style.display='inline'; Codehighlighter1_116_198_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> SubClassA </span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);"> SuperClass</span><span id="Codehighlighter1_116_198_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif" /></span><span id="Codehighlighter1_116_198_Open_Text"><span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">this overriding is illegal.</span><span style="color: rgb(0, 128, 0);"><br /><img id="Codehighlighter1_195_196_Open_Image" onclick="this.style.display='none'; Codehighlighter1_195_196_Open_Text.style.display='none'; Codehighlighter1_195_196_Closed_Image.style.display='inline'; Codehighlighter1_195_196_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_195_196_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_195_196_Closed_Text.style.display='none'; Codehighlighter1_195_196_Open_Image.style.display='inline'; Codehighlighter1_195_196_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> methodA() </span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);"> Exception</span><span id="Codehighlighter1_195_196_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif" /></span><span id="Codehighlighter1_195_196_Open_Text"><span style="color: rgb(0, 0, 0);">{}</span></span><span style="color: rgb(0, 0, 0);"><br /><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: rgb(0, 0, 0);"><br /><img src="../../Images/OutliningIndicators/None.gif" align="top" /><br /><img id="Codehighlighter1_242_330_Open_Image" onclick="this.style.display='none'; Codehighlighter1_242_330_Open_Text.style.display='none'; Codehighlighter1_242_330_Closed_Image.style.display='inline'; Codehighlighter1_242_330_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_242_330_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_242_330_Closed_Text.style.display='none'; Codehighlighter1_242_330_Open_Image.style.display='inline'; Codehighlighter1_242_330_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> SubClassB </span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);"> SuperClass</span><span id="Codehighlighter1_242_330_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif" /></span><span id="Codehighlighter1_242_330_Open_Text"><span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">this overriding is OK.</span><span style="color: rgb(0, 128, 0);"><br /><img id="Codehighlighter1_327_328_Open_Image" onclick="this.style.display='none'; Codehighlighter1_327_328_Open_Text.style.display='none'; Codehighlighter1_327_328_Closed_Image.style.display='inline'; Codehighlighter1_327_328_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_327_328_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_327_328_Closed_Text.style.display='none'; Codehighlighter1_327_328_Open_Image.style.display='inline'; Codehighlighter1_327_328_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> methodA() </span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);"> FileNotFoundException</span><span id="Codehighlighter1_327_328_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif" /></span><span id="Codehighlighter1_327_328_Open_Text"><span style="color: rgb(0, 0, 0);">{}</span></span><span style="color: rgb(0, 0, 0);"><br /><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div><br /></li><li>从Java5开始，子类中的方法的返回值也可以是对应的超类方法的返回值的子类。这叫做“协变”(Covariant)<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img id="Codehighlighter1_24_71_Open_Image" onclick="this.style.display='none'; Codehighlighter1_24_71_Open_Text.style.display='none'; Codehighlighter1_24_71_Closed_Image.style.display='inline'; Codehighlighter1_24_71_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_24_71_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_24_71_Closed_Text.style.display='none'; Codehighlighter1_24_71_Open_Image.style.display='inline'; Codehighlighter1_24_71_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> SuperClass </span><span id="Codehighlighter1_24_71_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif" /></span><span id="Codehighlighter1_24_71_Open_Text"><span style="color: rgb(0, 0, 0);">{<br /><img id="Codehighlighter1_51_69_Open_Image" onclick="this.style.display='none'; Codehighlighter1_51_69_Open_Text.style.display='none'; Codehighlighter1_51_69_Closed_Image.style.display='inline'; Codehighlighter1_51_69_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_51_69_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_51_69_Closed_Text.style.display='none'; Codehighlighter1_51_69_Open_Image.style.display='inline'; Codehighlighter1_51_69_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> Number caculate()</span><span id="Codehighlighter1_51_69_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif" /></span><span id="Codehighlighter1_51_69_Open_Text"><span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br /><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="color: rgb(0, 0, 0);"><br /><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: rgb(0, 0, 0);"><br /><img src="../../Images/OutliningIndicators/None.gif" align="top" /><br /><img id="Codehighlighter1_114_199_Open_Image" onclick="this.style.display='none'; Codehighlighter1_114_199_Open_Text.style.display='none'; Codehighlighter1_114_199_Closed_Image.style.display='inline'; Codehighlighter1_114_199_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_114_199_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_114_199_Closed_Text.style.display='none'; Codehighlighter1_114_199_Open_Image.style.display='inline'; Codehighlighter1_114_199_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> SubClass </span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);"> SuperClass</span><span id="Codehighlighter1_114_199_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif" /></span><span id="Codehighlighter1_114_199_Open_Text"><span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">only compiles in Java 5 or later.</span><span style="color: rgb(0, 128, 0);"><br /><img id="Codehighlighter1_179_197_Open_Image" onclick="this.style.display='none'; Codehighlighter1_179_197_Open_Text.style.display='none'; Codehighlighter1_179_197_Closed_Image.style.display='inline'; Codehighlighter1_179_197_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_179_197_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_179_197_Closed_Text.style.display='none'; Codehighlighter1_179_197_Open_Image.style.display='inline'; Codehighlighter1_179_197_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> Integer caculate()</span><span id="Codehighlighter1_179_197_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif" /></span><span id="Codehighlighter1_179_197_Open_Text"><span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br /><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="color: rgb(0, 0, 0);"><br /><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div></li></ul><p>可以看出，以上这些特性都非常好地遵循了LSP。但是DbC呢？很遗憾，主流的面向对象语言（不论是动态语言还是静态语言）还没有加入对DbC的支持。但是随着AOP概念的产生，相信不久DbC也将成为OO语言的一个重要特性之一。 
</p><br /></div><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 10pt;"><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 10pt;"><span lang="EN-US"><p><b><span>依赖倒置原则</span><span lang="EN-US">—— DIP </span></b><b><span lang="EN-US"><br /></span></b></p><p><font face="Courier New" size="2">a：高层模块不应依赖于底层模块，两者都应该依赖于抽象<br />b：抽象不应该依赖于细节，细节应该依赖于抽象</font></p></span></span></span></span></span></span><div> </div><div><strong><font face="Courier New" size="2">原则</font></strong></div><div><strong></strong><br /><font face="Courier New" size="2">如何解释倒置<br />高层依赖底层，重用变得困难，而最经常重用的就是framework和各个独立的功能组件<br />高层依赖底层，底层的改动直接反馈到高层，形成依赖的传递</font></div><div><font face="Courier New" size="2">面向接口的编程</font></div><div> </div><div><br /><strong><font face="Courier New" size="2">实例</font></strong></div><div><strong><br /></strong><font face="Courier New" size="2">Ioc模式<br />DomainObject / DomianObjectDataService</font></div><div> </div><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 10pt;"><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 10pt;"><span lang="EN-US"><p><b><span>接口隔离原则</span><span lang="EN-US">—— ISP </span></b><span lang="EN-US"><br /></span></p></span></span></span></span></span></span><p>使用多个专门的接口比使用单一的总接口总要好。换而言之，从一个客户类的角度来讲：一个类对另外一个类的依赖性应当是建立在最小接口上的。</p><strong><font face="Courier New" size="2">原则</font></strong><p>过于臃肿的接口是对接口的污染。不应该强迫客户依赖于它们不用的方法。</p><p>My object-oriented umbrella（摘自Design Patterns Explained）</p><p>Let me tell you about my great umbrella. It is large enough to get
into! In fact, three or four other people can get in it with me. While
we are in it, staying out of the rain, I can move it from one place to
another. It has a stereo system to keep me entertained while I stay
dry. Amazingly enough, it can also condition the air to make it warmer
or colder. It is one cool umbrella.</p><p>My umbrella is convenient. It sits there waiting for me. It has
wheels on it so that I do not have to carry it around. I don't even
have to push it because it can propel itself. Sometimes, I will open
the top of my umbrella to let in the sun. (Why I am using my umbrella
when it is sunny outside is beyond me!)</p><p>In Seattle, there are hundreds of thousands of these umbrellas in all kinds of colors. Most people call them cars.</p><p>实现方法：<br />1、 使用委托分离接口<br />2、 使用多重继承分离接口</p><p>想到一个朋友说的话：所有的接口都只有一个方法，具体的类根据自己需要什么方法去实现接口<br /></p><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 10pt;"><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 32pt; font-family: 宋体;"><span style="font-size: 10pt;"><span lang="EN-US"></span></span></span></span></span></span><img src ="http://www.blogjava.net/GandofYan/aggbug/40087.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/GandofYan/" target="_blank">混沌中立</a> 2006-04-09 14:06 <a href="http://www.blogjava.net/GandofYan/archive/2006/04/09/40087.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>