??xml version="1.0" encoding="utf-8" standalone="yes"?>国产亚洲精品福利在线无卡一,亚洲日本在线看片,91亚洲性爱在线视频http://www.tkk7.com/GandofYan/category/9719.htmlQ-Q-Q-Q-QԒ望星I,心中只剩下一片深?/description>zh-cnSun, 22 Jun 2014 15:19:54 GMTSun, 22 Jun 2014 15:19:54 GMT60一个简单的Java集合范围qo的多个方式对?/title><link>http://www.tkk7.com/GandofYan/archive/2014/06/21/415009.html</link><dc:creator>h中立</dc:creator><author>h中立</author><pubDate>Sat, 21 Jun 2014 15:33:00 GMT</pubDate><guid>http://www.tkk7.com/GandofYan/archive/2014/06/21/415009.html</guid><wfw:comment>http://www.tkk7.com/GandofYan/comments/415009.html</wfw:comment><comments>http://www.tkk7.com/GandofYan/archive/2014/06/21/415009.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.tkk7.com/GandofYan/comments/commentRss/415009.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/GandofYan/services/trackbacks/415009.html</trackback:ping><description><![CDATA[在一个项目里面有q么一个技术需?<br />1.集合中元素个?10M<br />2.Ҏ上限和下限从一个Set中过滤出满要求的元素集?<br /><br />实际q个是个很典型的技术要? 之前的项目也遇见q?但是因ؓ当时的类库不? 都是直接手写实现? 方式基本{同于第一个方?<br /><br />在这个过E中, 我写了四个方? 基本记录C?<br />W一个方?对Setq行q代器遍? 判断每个元素是否都在上限和下限范围中.如果满则添加到l果集合? 最后返回结果集?<br />            试效果:集合大小100K, q算旉 3000ms+<br />qo部分的逻辑如下:<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; "> 1</span>     <span style="color: #0000FF; ">void</span> filerSet(Set<BigDecimal> targetSet, String lower, String higher) {<br /><span style="color: #008080; "> 2</span>         BigDecimal bdLower = <span style="color: #0000FF; ">new</span> BigDecimal(Double.parseDouble(lower));<br /><span style="color: #008080; "> 3</span>         BigDecimal bdHigher = <span style="color: #0000FF; ">new</span> BigDecimal(Double.parseDouble(higher));<br /><span style="color: #008080; "> 4</span> <br /><span style="color: #008080; "> 5</span>         Set<BigDecimal> returnSet = <span style="color: #0000FF; ">new</span> HashSet<BigDecimal>();<br /><span style="color: #008080; "> 6</span>         <span style="color: #0000FF; ">for</span> (BigDecimal object : targetSet) {<br /><span style="color: #008080; "> 7</span>             <span style="color: #0000FF; ">if</span> (isInRange(object, bdLower, bdHigher)) {<br /><span style="color: #008080; "> 8</span>                 returnSet.add(object);<br /><span style="color: #008080; "> 9</span>             }<br /><span style="color: #008080; ">10</span>         }<br /><span style="color: #008080; ">11</span>     }<br /><span style="color: #008080; ">12</span> <br /><span style="color: #008080; ">13</span>     <span style="color: #0000FF; ">private</span> <span style="color: #0000FF; ">boolean</span> isInRange(BigDecimal object, BigDecimal bdLower,<br /><span style="color: #008080; ">14</span>             BigDecimal bdHigher) {<br /><span style="color: #008080; ">15</span>         <span style="color: #0000FF; ">return</span> object.compareTo(bdLower) >= 0<br /><span style="color: #008080; ">16</span>                 && object.compareTo(bdHigher) <= 0;<br /><span style="color: #008080; ">17</span>     }</div>W二个方? 借助TreeSet, 原始集合q行排序, 然后直接subset.<br />            试效果: 集合大小10M, q算旉: 12000ms+(获得TreeSet) , 200ms(获得l果)<br />qo部分的逻辑如下(非常J琐):<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; ">  1</span>     Set<BigDecimal> getSubSet(TreeSet<BigDecimal> targetSet, String lower,<br /><span style="color: #008080; ">  2</span>             String higher) {<br /><span style="color: #008080; ">  3</span> <br /><span style="color: #008080; ">  4</span>         BigDecimal bdLower = <span style="color: #0000FF; ">new</span> BigDecimal(Double.parseDouble(lower));<br /><span style="color: #008080; ">  5</span>         BigDecimal bdHigher = <span style="color: #0000FF; ">new</span> BigDecimal(Double.parseDouble(higher));<br /><span style="color: #008080; ">  6</span> <br /><span style="color: #008080; ">  7</span>         <span style="color: #0000FF; ">if</span> ((bdHigher.compareTo(targetSet.first()) == -1)<br /><span style="color: #008080; ">  8</span>                 || (bdLower.compareTo(targetSet.last()) == 1)) {<br /><span style="color: #008080; ">  9</span>             <span style="color: #0000FF; ">return</span> <span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; "> 10</span>         }<br /><span style="color: #008080; "> 11</span> <br /><span style="color: #008080; "> 12</span>         <span style="color: #0000FF; ">boolean</span> hasLower = targetSet.contains(bdLower);<br /><span style="color: #008080; "> 13</span>         <span style="color: #0000FF; ">boolean</span> hasHigher = targetSet.contains(bdHigher);<br /><span style="color: #008080; "> 14</span>         <span style="color: #0000FF; ">if</span> (hasLower) {<br /><span style="color: #008080; "> 15</span>             <span style="color: #0000FF; ">if</span> (hasHigher) {<br /><span style="color: #008080; "> 16</span>                 System.out.println("get start:" + bdLower);<br /><span style="color: #008080; "> 17</span>                 System.out.println("get end:" + bdHigher);<br /><span style="color: #008080; "> 18</span>                 <span style="color: #0000FF; ">return</span> targetSet.subSet(bdLower, <span style="color: #0000FF; ">true</span>, bdHigher, <span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; "> 19</span>             } <span style="color: #0000FF; ">else</span> {<br /><span style="color: #008080; "> 20</span>                 BigDecimal newEnd = <span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; "> 21</span>                 System.out.println("get start:" + bdLower);<br /><span style="color: #008080; "> 22</span>                 SortedSet<BigDecimal> returnSet = <span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; "> 23</span>                 <span style="color: #0000FF; ">if</span> (bdHigher.compareTo(targetSet.last()) != -1) {<br /><span style="color: #008080; "> 24</span>                     newEnd = targetSet.last();<br /><span style="color: #008080; "> 25</span>                 } <span style="color: #0000FF; ">else</span> {<br /><span style="color: #008080; "> 26</span>                     SortedSet<BigDecimal> newTargetSet = targetSet<br /><span style="color: #008080; "> 27</span>                             .tailSet(bdLower);<br /><span style="color: #008080; "> 28</span>                     <span style="color: #0000FF; ">for</span> (BigDecimal object : newTargetSet) {<br /><span style="color: #008080; "> 29</span>                         <span style="color: #0000FF; ">if</span> (object.compareTo(bdHigher) == 1) {<br /><span style="color: #008080; "> 30</span>                             newEnd = object;<br /><span style="color: #008080; "> 31</span>                             <span style="color: #0000FF; ">break</span>;<br /><span style="color: #008080; "> 32</span>                         } <span style="color: #0000FF; ">else</span> <span style="color: #0000FF; ">if</span> (object.compareTo(bdHigher) == 0) {<br /><span style="color: #008080; "> 33</span>                             newEnd = object;<br /><span style="color: #008080; "> 34</span>                             <span style="color: #0000FF; ">break</span>;<br /><span style="color: #008080; "> 35</span>                         }<br /><span style="color: #008080; "> 36</span>                     }<br /><span style="color: #008080; "> 37</span>                 }<br /><span style="color: #008080; "> 38</span>                 returnSet = targetSet.subSet(bdLower, <span style="color: #0000FF; ">true</span>, newEnd, <span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; "> 39</span>                 <span style="color: #0000FF; ">if</span> (newEnd.compareTo(bdHigher) == 1) {<br /><span style="color: #008080; "> 40</span>                     returnSet.remove(newEnd);<br /><span style="color: #008080; "> 41</span>                 }<br /><span style="color: #008080; "> 42</span>                 <span style="color: #0000FF; ">return</span> returnSet;<br /><span style="color: #008080; "> 43</span>             }<br /><span style="color: #008080; "> 44</span> <br /><span style="color: #008080; "> 45</span>         } <span style="color: #0000FF; ">else</span> {<br /><span style="color: #008080; "> 46</span>             <span style="color: #0000FF; ">if</span> (hasHigher) {<br /><span style="color: #008080; "> 47</span>                 System.out.println("get end:" + bdHigher);<br /><span style="color: #008080; "> 48</span>                 TreeSet<BigDecimal> newTargetSet = (TreeSet<BigDecimal>) targetSet<br /><span style="color: #008080; "> 49</span>                         .headSet(bdHigher, <span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; "> 50</span>                 BigDecimal newStart = <span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; "> 51</span>                 SortedSet<BigDecimal> returnSet = <span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; "> 52</span> <br /><span style="color: #008080; "> 53</span>                 <span style="color: #0000FF; ">if</span> (bdLower.compareTo(targetSet.first()) == -1) {<br /><span style="color: #008080; "> 54</span>                     newStart = targetSet.first();<br /><span style="color: #008080; "> 55</span>                 } <span style="color: #0000FF; ">else</span> {<br /><span style="color: #008080; "> 56</span>                     <span style="color: #0000FF; ">for</span> (BigDecimal object : newTargetSet) {<br /><span style="color: #008080; "> 57</span>                         <span style="color: #0000FF; ">if</span> (object.compareTo(bdLower) != -1) {<br /><span style="color: #008080; "> 58</span>                             newStart = object;<br /><span style="color: #008080; "> 59</span>                             <span style="color: #0000FF; ">break</span>;<br /><span style="color: #008080; "> 60</span>                         }<br /><span style="color: #008080; "> 61</span>                     }<br /><span style="color: #008080; "> 62</span>                 }<br /><span style="color: #008080; "> 63</span>                 returnSet = targetSet.subSet(newStart, <span style="color: #0000FF; ">true</span>, bdHigher, <span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; "> 64</span> <br /><span style="color: #008080; "> 65</span>                 <span style="color: #0000FF; ">return</span> returnSet;<br /><span style="color: #008080; "> 66</span>             } <span style="color: #0000FF; ">else</span> {<br /><span style="color: #008080; "> 67</span>                 System.out.println("Not get start:" + bdLower);<br /><span style="color: #008080; "> 68</span>                 System.out.println("Not get end:" + bdHigher);<br /><span style="color: #008080; "> 69</span>                 BigDecimal newStart = <span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; "> 70</span>                 BigDecimal newEnd = <span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; "> 71</span>                 <span style="color: #0000FF; ">if</span> (bdHigher.compareTo(targetSet.last()) != -1) {<br /><span style="color: #008080; "> 72</span>                     newEnd = targetSet.last();<br /><span style="color: #008080; "> 73</span>                 }<br /><span style="color: #008080; "> 74</span>                 <span style="color: #0000FF; ">if</span> (bdLower.compareTo(targetSet.first()) == -1) {<br /><span style="color: #008080; "> 75</span>                     newStart = targetSet.first();<br /><span style="color: #008080; "> 76</span>                 }<br /><span style="color: #008080; "> 77</span>                 <span style="color: #0000FF; ">for</span> (BigDecimal object : targetSet) {<br /><span style="color: #008080; "> 78</span>                     <span style="color: #0000FF; ">if</span> (newStart == <span style="color: #0000FF; ">null</span>) {<br /><span style="color: #008080; "> 79</span>                         <span style="color: #0000FF; ">if</span> (object.compareTo(bdLower) != -1) {<br /><span style="color: #008080; "> 80</span>                             newStart = object;<br /><span style="color: #008080; "> 81</span>                             <span style="color: #0000FF; ">if</span> (newEnd != <span style="color: #0000FF; ">null</span>) {<br /><span style="color: #008080; "> 82</span>                                 <span style="color: #0000FF; ">break</span>;<br /><span style="color: #008080; "> 83</span>                             }<br /><span style="color: #008080; "> 84</span>                         }<br /><span style="color: #008080; "> 85</span>                     }<br /><span style="color: #008080; "> 86</span> <br /><span style="color: #008080; "> 87</span>                     <span style="color: #0000FF; ">if</span> (newEnd == <span style="color: #0000FF; ">null</span>) {<br /><span style="color: #008080; "> 88</span>                         <span style="color: #0000FF; ">if</span> (object.compareTo(bdHigher) != -1) {<br /><span style="color: #008080; "> 89</span>                             newEnd = object;<br /><span style="color: #008080; "> 90</span>                             <span style="color: #0000FF; ">if</span> (newStart != <span style="color: #0000FF; ">null</span>) {<br /><span style="color: #008080; "> 91</span>                                 <span style="color: #0000FF; ">break</span>;<br /><span style="color: #008080; "> 92</span>                             }<br /><span style="color: #008080; "> 93</span>                         }<br /><span style="color: #008080; "> 94</span>                     }<br /><span style="color: #008080; "> 95</span>                 }<br /><span style="color: #008080; "> 96</span> <br /><span style="color: #008080; "> 97</span>                 <span style="color: #0000FF; ">if</span> (newStart == <span style="color: #0000FF; ">null</span>) {<br /><span style="color: #008080; "> 98</span>                     <span style="color: #0000FF; ">if</span> (newEnd == <span style="color: #0000FF; ">null</span>) {<br /><span style="color: #008080; "> 99</span>                         <span style="color: #0000FF; ">if</span> ((bdHigher.compareTo(targetSet.first()) == -1)<br /><span style="color: #008080; ">100</span>                                 || (bdLower.compareTo(targetSet.last()) == 1)) {<br /><span style="color: #008080; ">101</span>                             <span style="color: #0000FF; ">return</span> <span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; ">102</span>                         }<br /><span style="color: #008080; ">103</span>                         <span style="color: #0000FF; ">return</span> targetSet;<br /><span style="color: #008080; ">104</span>                     } <span style="color: #0000FF; ">else</span> {<br /><span style="color: #008080; ">105</span>                         SortedSet<BigDecimal> newTargetSet = targetSet.headSet(<br /><span style="color: #008080; ">106</span>                                 newEnd, <span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; ">107</span>                         <span style="color: #0000FF; ">if</span> (newEnd.compareTo(bdHigher) == 1) {<br /><span style="color: #008080; ">108</span>                             newTargetSet.remove(newEnd);<br /><span style="color: #008080; ">109</span>                         }<br /><span style="color: #008080; ">110</span>                         <span style="color: #0000FF; ">return</span> newTargetSet;<br /><span style="color: #008080; ">111</span>                     }<br /><span style="color: #008080; ">112</span>                 } <span style="color: #0000FF; ">else</span> {<br /><span style="color: #008080; ">113</span>                     <span style="color: #0000FF; ">if</span> (newEnd == <span style="color: #0000FF; ">null</span>) {<br /><span style="color: #008080; ">114</span>                         SortedSet<BigDecimal> newTargetSet = targetSet.tailSet(<br /><span style="color: #008080; ">115</span>                                 newStart, <span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; ">116</span>                         <span style="color: #0000FF; ">return</span> newTargetSet;<br /><span style="color: #008080; ">117</span>                     } <span style="color: #0000FF; ">else</span> {<br /><span style="color: #008080; ">118</span>                         SortedSet<BigDecimal> newTargetSet = targetSet.subSet(<br /><span style="color: #008080; ">119</span>                                 newStart, <span style="color: #0000FF; ">true</span>, newEnd, <span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; ">120</span>                         <span style="color: #0000FF; ">if</span> (newEnd.compareTo(bdHigher) == 1) {<br /><span style="color: #008080; ">121</span>                             newTargetSet.remove(newEnd);<br /><span style="color: #008080; ">122</span>                         }<br /><span style="color: #008080; ">123</span>                         <span style="color: #0000FF; ">return</span> newTargetSet;<br /><span style="color: #008080; ">124</span>                     }<br /><span style="color: #008080; ">125</span>                 }<br /><span style="color: #008080; ">126</span>             }<br /><span style="color: #008080; ">127</span>         }<br /><span style="color: #008080; ">128</span>     }</div>W三U方? 使用Apache Commons Collections, 直接对于原始Setq行filter.<br />            试效果:集合大小10M,qol果1M, q算旉: 1000ms+<br />qo部分的代码如?<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; "> 1</span> <span style="color: #008000; ">//</span><span style="color: #008000; ">qo的主体逻辑</span><span style="color: #008000; "><br /></span><span style="color: #008080; "> 2</span> <span style="color: #008000; "></span>    <span style="color: #0000FF; ">void</span> filterSet(Set<BigDecimal> targetSet, String lower, String higher) {<br /><span style="color: #008080; "> 3</span>         <span style="color: #0000FF; ">final</span> BigDecimal bdLower = <span style="color: #0000FF; ">new</span> BigDecimal(Double.parseDouble(lower));<br /><span style="color: #008080; "> 4</span>         <span style="color: #0000FF; ">final</span> BigDecimal bdHigher = <span style="color: #0000FF; ">new</span> BigDecimal(Double.parseDouble(higher));<br /><span style="color: #008080; "> 5</span> <br /><span style="color: #008080; "> 6</span>         Predicate predicate = <span style="color: #0000FF; ">new</span> Predicate() {<br /><span style="color: #008080; "> 7</span>             <span style="color: #0000FF; ">public</span> <span style="color: #0000FF; ">boolean</span> evaluate(Object object) {<br /><span style="color: #008080; "> 8</span>                 BigDecimal bDObject = (BigDecimal) object;<br /><span style="color: #008080; "> 9</span>                 <span style="color: #0000FF; ">return</span> bDObject.compareTo(bdLower) >= 0<br /><span style="color: #008080; ">10</span>                         && bDObject.compareTo(bdHigher) <= 0;<br /><span style="color: #008080; ">11</span>             }<br /><span style="color: #008080; ">12</span>         };<br /><span style="color: #008080; ">13</span> <br /><span style="color: #008080; ">14</span>         CollectionUtils.filter(targetSet, predicate);<br /><span style="color: #008080; ">15</span>     }</div><br />W四U方?使用Guava(google Collections), 直接对于原始Setq行Filter<br />            试效果:集合大小10M,qol果1M, q算旉: 100ms-<br />qo部分的代码如?<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; "> 1</span> <span style="color: #008000; ">//</span><span style="color: #008000; ">guava filter</span><span style="color: #008000; "><br /></span><span style="color: #008080; "> 2</span> <span style="color: #008000; "></span><br /><span style="color: #008080; "> 3</span>     Set<BigDecimal> filterSet(Set<BigDecimal> targetSet, String lower,<br /><span style="color: #008080; "> 4</span>             String higher) {<br /><span style="color: #008080; "> 5</span>         <span style="color: #0000FF; ">final</span> BigDecimal bdLower = <span style="color: #0000FF; ">new</span> BigDecimal(Double.parseDouble(lower));<br /><span style="color: #008080; "> 6</span>         <span style="color: #0000FF; ">final</span> BigDecimal bdHigher = <span style="color: #0000FF; ">new</span> BigDecimal(Double.parseDouble(higher));<br /><span style="color: #008080; "> 7</span> <br /><span style="color: #008080; "> 8</span>         Set<BigDecimal> filterCollection = Sets.filter(targetSet,<br /><span style="color: #008080; "> 9</span>                 <span style="color: #0000FF; ">new</span> Predicate<BigDecimal>() {<br /><span style="color: #008080; ">10</span>                     @Override<br /><span style="color: #008080; ">11</span>                     <span style="color: #0000FF; ">public</span> <span style="color: #0000FF; ">boolean</span> apply(BigDecimal input) {<br /><span style="color: #008080; ">12</span>                         BigDecimal bDObject = (BigDecimal) input;<br /><span style="color: #008080; ">13</span>                         <span style="color: #0000FF; ">return</span> bDObject.compareTo(bdLower) >= 0<br /><span style="color: #008080; ">14</span>                                 && bDObject.compareTo(bdHigher) <= 0;<br /><span style="color: #008080; ">15</span>                     }<br /><span style="color: #008080; ">16</span>                 });<br /><span style="color: #008080; ">17</span> <br /><span style="color: #008080; ">18</span>         <span style="color: #0000FF; ">return</span> filterCollection;<br /><span style="color: #008080; ">19</span>     }</div><br /><br />四种方式Ҏ如下:<br />W一U方?  仅依赖于JAVA原生cd 遍历旉最? 代码量很?br />W二U方?  仅依赖于JAVA原生cd 遍历旉比较?主要慢在生成有序Set), 代码量最?br />W三U方?  依赖于Apache Commons Collections, 遍历旉比较? 代码量很?br />W四U方?  依赖于Guava, 遍历旉最? 代码量很?br /><br />Z目前个h的技术水q_视野, W四U方式可能是最佳选择.<br /><br />记录一? 以后可能q会有更好的Ҏ.<br /><br /><br /><br /><br /><div id="xdpn33x" class="vimiumReset vimiumHUD" style="right: 150px; opacity: 0; display: none;"></div><img src ="http://www.tkk7.com/GandofYan/aggbug/415009.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/GandofYan/" target="_blank">h中立</a> 2014-06-21 23:33 <a href="http://www.tkk7.com/GandofYan/archive/2014/06/21/415009.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个Sudoku的java求解法http://www.tkk7.com/GandofYan/archive/2006/07/13/58004.htmlh中立h中立Thu, 13 Jul 2006 08:19:00 GMThttp://www.tkk7.com/GandofYan/archive/2006/07/13/58004.htmlhttp://www.tkk7.com/GandofYan/comments/58004.htmlhttp://www.tkk7.com/GandofYan/archive/2006/07/13/58004.html#Feedback4http://www.tkk7.com/GandofYan/comments/commentRss/58004.htmlhttp://www.tkk7.com/GandofYan/services/trackbacks/58004.html正好当时在看Uncle Bob的《Agile Software Development: Principles, Patterns, and Practices?Q敏捯Y件开发:原则、模式与实践Q?所以就按照自己对书中的一些概念和Ҏ的理解,l合自己之前的开发经验写出来一D小的代码?br />
代码行数Q?< 900
cȝ个数Q?18
抽象cȝ个数Q?
工厂cȝ个数Q?
包的个数Q?

一些关于类和包作用的说明:
1.Cell:表示一个CellQ是一个游戏中的一个单元格?br />  Cell主要?个部分组成,Point,Value,Status.
2.Point:表示一个坐标,主要格式?(2,3).
  Q!Q注意:׃个h比较?所以开始的错误被诏M下来?br />  q个错误是Q?Q?Q表C的是由最左上的位|ؓ坐标原点Q第二行和第三列所定的那个单元格。也是U坐标在前,横坐标在后了?br />3.Value:表示一个?br />4.Status:表示Cell的状态,只有两个状态,一个是NotSure,另一个是Sure.

5.AbstractCellsQ表CZ些cell的集合,主要有三个子c?br />     BlockCellsQ表CZ个由多个Celll成的块Q例如一?*2?个Celll成的块Q或者一?*3?个Celll成的块
     HorizonCells:表示一个横行,卻I从(0Q?Q到(0,n)坐标定的所有Cell的集合?br />     VerticalCells:表示一个纵行,卻I从(0Q?Q到(n,0)坐标定的所有Cell的集合?br />6.AbstractPolicy:是游戏的策略?br />   q个主要表示的是Q?*4的游戏,q是9*9的游戏?br />   可以在以后对此类q行l承和扩展,例如16*16的游戏我没有实现?br />   主要扩展3个方法:
                  1QgetValueRangeQ返回当前policy的value的个数?*4的游戏的getValueRangeq回的就应该??br />          2QgetStepQ表C当前policy中相ȝ两个BlockCells的坐标差?br />          3QgetIncreaseQ说不明白了Q)Q只可意会不可言传。)
7.GameQ进行Policy的场所Q我一直想抛弃q个c)
8.TestGame:游戏q行的地方,包括从PolicyFactory取得指定的Policy,讄输入输出文g的\径?br />9.PolicyFactoryQ取得Policy的工厂?br />    getPolicy(int x) :q个Ҏ获得的是正方形的sudoku的策略。例?4*4的,9*9,16*16?br />    getPolicy(int x, int y)Q这个方法获得的是长方Ş的Sudoku的策略。例如:9*12的?br />

虽然是尽量避免bad code smellQ但是由于能力有限,q是出现了一些不好的地方?br />例如Q之间的兌关系q是很多Q而且很强Q抽象的Ҏ和抽象类的个数偏等{?br />
里面实现了三个解决sudoku的方法:
1.在一个Cell中出现的Value,不会在和q个Cell处在同一个AbstractCells中的所有Cell中出玎ͼ
2.如果一个Cell中,所有可能出现的Value的个Cؓ1Q那么Cell的Value必然是这个最后的ValueQ?br />2.如果一个Value,如果在当前AbstractCells的所有其他的Cell中都不可能出玎ͼ那么它必然是最后一个Cell的Value?br />
附g1Qsrc code
http://www.tkk7.com/Files/GandofYan/sudoku.rar
附g2Q输入输出文件的example
http://www.tkk7.com/Files/GandofYan/temp.rar



h中立 2006-07-13 16:19 发表评论
]]>
javaEye上面对于domain object的讨?/title><link>http://www.tkk7.com/GandofYan/archive/2006/05/30/48954.html</link><dc:creator>h中立</dc:creator><author>h中立</author><pubDate>Tue, 30 May 2006 05:31:00 GMT</pubDate><guid>http://www.tkk7.com/GandofYan/archive/2006/05/30/48954.html</guid><wfw:comment>http://www.tkk7.com/GandofYan/comments/48954.html</wfw:comment><comments>http://www.tkk7.com/GandofYan/archive/2006/05/30/48954.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.tkk7.com/GandofYan/comments/commentRss/48954.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/GandofYan/services/trackbacks/48954.html</trackback:ping><description><![CDATA[ <div> <a > <u> <font color="#0000ff">ȝ一下最q关于domain object以及相关的讨?/font> </u> </a> </div> <div> </div> <div> <span>在最q的围绕domain object的讨Z现出来了三U模型,(q有一些其他的旁枝Q不一一分析?Q经q一番讨论,各种问题逐渐清晰hQ在q里我试囑ց一个ȝQ便于大家了解和掌握? <br /><br />W一U模型:只有getter/setterҎ的纯数据c,所有的业务逻辑完全由business object来完?又称TransactionScript)Q这U模型下的domain object被Martin FowlerUC为“血的domain object”。下面用举一个具体的代码来说明,代码来自Hibernate的caveatemptorQ但l过我的改写Q? <br /><br />一个实体类叫做ItemQ指的是一个拍卖项?<br />一个DAO接口cd做ItemDao <br />一个DAO接口实现cd做ItemDaoHibernateImpl <br />一个业务逻辑cd做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Ҏ省略不写Q避免篇q太?/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定义持久化操作的接口Q用于隔L久化代码? <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完成具体的持久化工作Q请注意Q数据库资源的获取和释放是在ItemDaoHibernateImpl 里面处理的,每个DAOҎ调用之前打开SessionQDAOҎ调用之后Q关闭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> && 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> > <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 />事务的管理是在ItemMangerq一层完成的QItemManager实现具体的业务逻辑。除了常见的和CRUD有关的简单逻辑之外Q这里还有一个placeBid的逻辑Q即目的竞标? <br /><br />以上是一个完整的W一U模型的CZ代码。在q个CZ中,placeBidQloadItemByIdQfindAll{等业务逻辑l统攑֜ItemManager中实玎ͼ而Item只有getter/setterҎ?/span> </div> <p> </p> <p> </p> <p> <span>W二U模型,也就是Martin Fowler指的rich domain object是下面这样子的: <br /><br />一个带有业务逻辑的实体类Q即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Ҏ同上Q省?/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> && 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> > <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);">// h意这一句,透明的进行了持久化,但是不能在这里调用ItemDaoQItem不能对ItemDao产生依赖Q?/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 />竞标q个业务逻辑被放入到Item中来。请注意this.getBids.add(newBid); 如果没有Hibernate或者JDOq种O/R Mapping的支持,我们是无法实现这U透明的持久化行ؓ的。但是请注意QItem里面不能去调用ItemDAOQ对ItemDAO产生依赖Q? <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);">// 必须昑ּ的调用DAOQ保持持久化</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中实现的Q而loadItemById和findAll业务逻辑是放? ItemManager中实现的。不q值得注意的是Q即使placeBid业务逻辑攑֜Item中,你仍焉要在ItemManager中简单的装一层,以保证对placeBid业务逻辑q行事务的管理和持久化的触发? <br /><br />q种模型是Martin Fowler所指的真正的domain model。在q种模型中,有三个业务逻辑ҎQplaceBidQloadItemById和findAllQ现在的问题是哪个逻辑应该攑֜Item 中,哪个逻辑应该攑֜ItemManager中。在我们q个例子中,placeBid攑֜Item?但是ItemManager也需要对它进行简单的装)QloadItemById和findAll是放在ItemManager中的? <br /><br />切分的原则是什么呢Q?Rod Johnson提出原则是“case by case”,可重用度高的Q和domain object状态密切关联的攑֜Item中,可重用度低的Q和domain object状态没有密切关联的攑֜ItemManager中?<br /><br /><span style="color: red;">我提出的原则是:看业务方法是否显式的依赖持久化?/span><br /><br />Item的placeBidq个业务逻辑Ҏ没有昑ּ的对持久化ItemDao接口产生依赖Q所以要攑֜Item中?span style="color: red;">h意,如果q了Hibernateq个持久化框ӞItemq个domain object是可以进行单元测试的Q他不依赖于Hibernate的持久化机制。它是一个独立的Q可UL的,完整的,自包含的域对?/span>? <br /><br />而loadItemById和findAllq两个业务逻辑Ҏ是必L式的Ҏ久化ItemDao接口产生依赖Q否则这个业务逻辑无法完成。如果你要把q两个方法放在Item中,那么Item无法脱Hibernate框架Q无法在Hibernate框架之外独立存在?/span> <p> </p> <p> </p> <p> <span>W三U模型印象中好像是firebody或者是Archie提出?也有可能不是Q记不清楚了)Q简单的来说Q这U模型就是把W二U模型的domain object和business object合二Z了。所以ItemManager׃需要了Q在q种模型下面Q只有三个类Q他们分别是Q? <br /><br />ItemQ包含了实体cM息,也包含了所有的业务逻辑 <br />ItemDaoQ持久化DAO接口c? <br />ItemDaoHibernateImplQDAO接口的实现类 <br /><br />׃ItemDao和ItemDaoHibernateImpl和上面完全相同,q略了?<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> && 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> > <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);">//  调用DAOq行昑ּ持久?/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 />在这U模型中Q所有的业务逻辑全部都在Item中,事务理也在Item中实现?/span> <p> </p> <p> </p> <p> <span>在上面三U模型之外,q有很多q三U模型的变种Q例如partech的模型就是把W二U模型中的DAO? Manager三个cdqؓ一个类后Ş成的模型Q例如frain....(id很长C?的模型就是把W三U模型的三个cd全合qؓ一个单cd形成的模型;例如Archie是把W三U模型的Item又分出来一些纯数据c?可能是,不确?形成的一个模型? <br /><br />但是不管怎么变,基本模型归纳h是上面的三U模型,下面分别单评价一下: <br /><br />W一U模型绝大多Ch都反对,因此反对理由我也不多讲了。但遗憾的是Q我观察到的实际情Ş是,很多使用Hibernate的公司最后都是这U模型,q里面有很大的原因是很多公司的技术水qx有达到这U层ơ,所以导致了q种贫血模型的出现。从q一Ҏ_Martin Fowler的批评声音不是太响了Q而是太弱了,q需要再l箋呐喊?<br /><br />W二U模型就是Martin Fowler一直主张的模型Q实际上也是我一直在实际目中采用这U模型。我没有看过Martin的POEAAQ之所以能够自己摸索到q种模型Q也是因Z02q我已经开始思考这个问题ƈ且寻求解x案了Q但是当时没有看到HibernateQ那时候做的一个小型项目我已经按照q种模型来做了,但是׃没有O/R Mapping的支持,写到后来又不得不全部Ҏ贫血的domain objectQ项目做完以后再l箋找,随后发CHibernate。当Ӟ现在很多Z开始就是用Hibernate做项目,没有l历q我l历的那个阶Dc? <br /><br />不过我觉得这U模型仍然不够完,因ؓ你还是需要一个业务逻辑层来装所有的domain logicQ这昑־非常|嗦Qƈ且业务逻辑对象的接口也不够E_。如果不考虑业务逻辑对象的重用性的?业务逻辑对象的可重用性也不可能好)Q很多hq脆去掉了xxxManagerq一层,在Web层的Action代码直接调用xxxDaoQ同时容器事务管理配|到Actionq一层上来? Hibernate的caveatemptor是q样架构的一个典型应用?<br /><br />W三U模型是我很反对的一U模型,q种模型下面QDomain Object和DAO形成了双向依赖关p,无法q框架试Qƈ且业务逻辑层的服务也和持久层对象的状态耦合C一P会造成E序的高度的复杂性,很差的灵zL和p糕的可l护性。也许将来技术进步导致的O/R Mapping理下的domain object发展到够的动态持久透明化的话,q种模型才会成ؓ一个理想的选择。就像O/R Mapping的流行得第二种模型成ؓ了可?O/R Mapping行以前Q我们只能用W一U模型,W二U模型那时候是不现实的)?/span> </p> <p> </p> <p> </p> <p> <span>既然大家都统一了观点,那么有了一个很好的讨论问题的基了。Martin Fowler的Domain ModelQ或者说我们的第二种模型N是完无~的吗?当然不是Q接下来我就要分析一下它的不I以及可能的解军_法,而这些都来源于我个h的实跉|索? <br /><br />在第二种模型中,我们可以清楚的把q?个类分ؓ三层Q?<br /><br />1、实体类层,即ItemQ带有domain logic的domain object <br />2、DAO层,即ItemDao和ItemDaoHibernateImplQ抽象持久化操作的接口和实现c? <br />3、业务逻辑层,即ItemManagerQ接受容器事务控Ӟ向Web层提供统一的服务调?<br /><br />在这三层中我们大家可以看刎ͼdomain object和DAO都是非常E_的层Q其实原因也很简单,因ؓdomain object是映数据库字段的,数据库字D不会频J变动,所以domain object也相对稳定,而面向数据库持久化编E的DAO层也不过是CRUD而已Q不会有更多的花P所以也很稳定? <br /><br />问题在于这个充当business workflow facade的业务逻辑对象Q它的变动是相当频繁的?span style="color: red;">业务逻辑对象通常都是无状态的、受事务控制的、Singletonc?/span>Q我们可以考察一下业务逻辑对象都有哪几cM务逻辑ҎQ? <br /><br /><span style="color: red;">W一c:DAO接口Ҏ的代?/span>Q就是上面例子中的loadItemByIdҎ和findAllҎ? <br /><br />ItemManager之所以要代理q种c,目的有两个:<span style="color: red;">向Web层提供统一的服务调用入口点和给持久化方法增加事务控制功?/span>。这两点都很Ҏ理解Q你不能既给Web层程序员提供xxxManagerQ也l他提供xxxDaoQ所以你需要用xxxManager装xxxDaoQ在q里Q充当了一个简单代理功能;而事务控制也是持久化Ҏ必须的,事务可能需要跨多个DAOҎ调用Q所以必L在业务逻辑层,而不能放在DAO层? <br /><br />但是必须看到Q对于一个典型的web应用来说Q绝大多数的业务逻辑都是单的CRUD逻辑Q所以这U情况下Q针Ҏ个DAOҎQxxxManager都需要提供一个对应的装ҎQ这不但是非常枯燥的Q也是o人感觉非怸好的? <br /><br /><br /><span style="color: red;">W二c:domain logic的方法代?/span>。就是上面例子中placeBidҎ。虽然Item已经有了placeBidҎQ但是ItemManager仍然需要封装一下Item的placeBidQ然后再提供一个简单封装之后的代理Ҏ? <br /><br />q和W一U情늱|其原因也一P也是ZlWeb层提供一个统一的服务调用入口点和给隐式的持久化动作提供事务控制? <br /><br />同样Q和W一U情况一P针对每个domain logicҎQxxxManager都需要提供一个对应的装ҎQ同h枯燥的,令h不爽的? <br /><br /><br /><span style="color: red;">W三c:需要多个domain object和DAO参与协作的business workflow</span>。这U情冉|业务逻辑对象真正应该完成的职责? <br /><br />在这个简单的例子中,没有涉及到这U情况,不过大家都可以想像的出来q种应用场景Q因此不必D例说明了? <br /><br />通过上面的分析可以看出,只有W三cM务逻辑Ҏ才是业务逻辑对象真正应该承担的职责,而前两类业务逻辑Ҏ都是“无奈之䏀,不得不ؓ之的事情Q不但枯燥,而且令h沮? <br /><br /><br /><br /><br />分析完了业务逻辑对象Q我们再回头看一下domain objectQ我们要仔细考察一下domain logic的话Q会发现domain logic也分Zc: <br /><br /><span style="color: red;">W一c:需要持久层框架隐式的实现透明持久化的domain logic</span>Q例如Item的placeBidҎ中的q一句: <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 />上面已经着重提刎ͼ虽然q仅仅只是一个Java集合的添加新元素的操作,但是实际上通过事务的控Ӟ会潜在的触发两条SQLQ一条是insert一条记录到bid表,一条是更新item表相应的记录。如果我们让ItemqHibernateq行单元试Q它是一个单U的Java集合操作Q如果我们把他加入到Hibernate框架中,他就会潜在的触发两条SQLQ?span style="color: red;">q就是隐式的依赖于持久化的domain logic</span>? <br />特别h意的一ҎQ在没有Hibernate/JDOq类可以实现“透明的持久化”工具出C前,q类domain logic是无法实现的? <br /><br />对于q一cdomain logicQ业务逻辑对象必须提供相应的封装方法,以实C务控制?<br /><br /><br /><span style="color: red;">W二c:完全不依赖持久化的domain logic</span>Q例如readonly例子中的TopicQ如下: <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 />注意q个isAllowReplyҎQ他和持久化完全不发生一丁点关系。在实际的开发中Q我们同样会遇到很多q种不需要持久化的业务逻辑(主要发生在日期运、数D和枚Dq算斚w)Q这Udomain logic不管q不脱L在的框架Q它的行为都是一致的。对于这Udomain logicQ业务逻辑层ƈ不需要提供封装方法,它可以适用于Q何场合?/span> <img src ="http://www.tkk7.com/GandofYan/aggbug/48954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/GandofYan/" target="_blank">h中立</a> 2006-05-30 13:31 <a href="http://www.tkk7.com/GandofYan/archive/2006/05/30/48954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]O/R Mapping 基本概念http://www.tkk7.com/GandofYan/archive/2006/05/30/48945.htmlh中立h中立Tue, 30 May 2006 05:20:00 GMThttp://www.tkk7.com/GandofYan/archive/2006/05/30/48945.htmlhttp://www.tkk7.com/GandofYan/comments/48945.htmlhttp://www.tkk7.com/GandofYan/archive/2006/05/30/48945.html#Feedback0http://www.tkk7.com/GandofYan/comments/commentRss/48945.htmlhttp://www.tkk7.com/GandofYan/services/trackbacks/48945.html
原文地址Q?a >http://www.cnblogs.com/idior/archive/2005/07/04/186086.html

q日 有关o/r m的讨论突然多了v? 在这里觉得有必要澄清一些概? 免的大家讨论来讨论去, 才发现最Ҏ的理解有问题.

1. 何谓实体?
实体(cM于j2ee中的Entity Bean)通常指一个承载数据的对象, 但是注意它也是可以有行ؓ? 只不q它的行Z般只操作自n的数? 比如下面q个例子:


class Person
{
  string firstName;
  string lastName;

  public void GetName()
  {
     return  lastName+firstName;
  }   
}


GetName是它的一个行?

2 何谓对象?
对象最重要的特性在于它拥有行ؓ. 仅仅拥有数据,你可以称它ؓ对象, 但是它却失去它最重要的灵? 


class Person
{
  string firstName;
  string lastName;
  Role role;
  int baseWage;
  public void GetSalary()
  {
     return baseWage*role.GetFactory();
  }   
}

q样需要和别的对象(不是Value Object)打交道的对象,我就不再U其为实? 领域模型是指由q些h业务逻辑的对象构成的模型.

3. E/R M or O/R M?!!
仔细x我们Z么需要o/r m,无非是想利用oo的多态来处理复杂的业务逻辑, 而不是靠一堆的if else. 
而现在在很多人的手上o/r m全变成了e/r m.他们不考虑对象的行? 而全x于如何保存数?q样也难怪他们会产生CRUDq些操作攑օ对象中的念头. 如果你不能深ȝ解oo, 那么我不推荐你用o/r m, Table Gateway, Row Gateway才是你想要的东西.


作ؓ一个O/R M框架Q很重要的一点就是实现映的透明性(TransparentQ,比较显著的特点就是在代码中我们是看不到SQL语句的(框架自动生成了)。这里所指的O/R M是cM于此的框Ӟ

4. POEAA中的相关概念
  很多ơ发现有人错用其中的概念, q里Zȝ一?
  1. Table Gateway
    以表为单位的实体,基本没有行ؓ,只有CRUD操作.
  2. Row Gateway
    以行为单位的实体,基本没有行ؓ,只有CRUD操作.
  3. Active Record
    以行为单位的实体,拥有一些基本的操作自n数据的行?如上例中的GetName),同时包含有CRUD操作.
其实Active Record最W合某些单的需? 接近于E/R m.
通常也有很多人把它当作O/R m.不过需要注意的是Active Record中是充满了SQL语句?不像orm的SQL透明), 所以有人想h利用O/R m来实?Active Record", 虽然在他们眼里看h很方? 其实Ҏ是q祖.
用CodeGenerator来实现Active Record也许是一个比较好的方?
  4. Data Mapper
q才是真正的O/R m,Hibernate{等工具的目?

5.O/R M需要关注的地方 (希望大家帮忙完善一?
 1. 兌, O/R M是如何管理类之间的关?当然q不仅于o/r m有关与设计者的设计水^也有很大关系.
 2. O/R M对承关pȝ处理.
 3. O/R M对事务的支持.
 4. O/R MҎ询的支持.
 
以上观点仅属个h意见, 不过在大家讨论有关O/R m之前, 希望先就一些基本概念达成共? 不然讨论下去会越越q? 


(: 如果对oo以及dp没有一定程度的了解, 最好别使用o/r m, dataset 加上codesmith或许是更好的选择)


h中立 2006-05-30 13:20 发表评论
]]>
面向对象设计的基本原??http://www.tkk7.com/GandofYan/archive/2006/04/09/40087.htmlh中立h中立Sun, 09 Apr 2006 06:06:00 GMThttp://www.tkk7.com/GandofYan/archive/2006/04/09/40087.htmlhttp://www.tkk7.com/GandofYan/comments/40087.htmlhttp://www.tkk7.com/GandofYan/archive/2006/04/09/40087.html#Feedback0http://www.tkk7.com/GandofYan/comments/commentRss/40087.htmlhttp://www.tkk7.com/GandofYan/services/trackbacks/40087.html 最q在?lt; 敏捷软g开发:原则、模式与实践 >在网上找了一些资?把他们集合C一?便于自己学习

此篇内容来自一下两?br />
http://blog.joycode.com/microhelper/archive/2004/11/30/40013.aspx

http://www.tkk7.com/ghawk/

?关于面向对象设计的原则比较权威的是Uncle Bob--
Robert C. Martin?br />

Principles Of Object Oriented Design

http://c2.com/cgi/wiki?PrinciplesOfObjectOrientedDesign


单一职责原则
——SRP
׃个类而言Q应该仅有一个引起它的变化的原因
 
原则

最单,最单纯的事情最Ҏ控制Q最有效
cȝ职责单而且集中Q避免相同的职责分散C同的cM中,避免一个类承担q多的职?br />减少cM间的耦合
当需求变化时Q只修改一个地?/font>

lg

每个lg集中做好一件事?br />lg的颗_度
发布的成?br />可重用的成本
 
Ҏ

避免写臃肿的Ҏ
Extract Method
 
重构

Move Field/Move Class
Extract Method/Extract Class
 
最单的Q也是最难以掌握的原?/font>
 
实例分析


单一职责很容易理解,也很Ҏ实现。所谓单一职责Q就是一个设计元素只做一件事。什么是“只做一件事”?单说是管闲事。现实中是如此Q如果要你专心做一件事情,M人都有信心可以做得很。但如果Q你整天被ؕ七八p的事所累,q有心思和_֊把每件事都作好么Q?br />fig-1.JPG
      “单一职责”就是要在设计中为每U职责设计一个类Q彼此保持正交,互不q涉。这个雕塑(二重奏)是正交的一个例子,钢琴家和提琴家各自演奏自己的乐 谱,而结果就是一个和谐的交响乐。当Ӟ真实世界中,演奏提琴和弚w琴的必须是两个hQ但是在软g中,我们往往会把两者甚x多搅和到一P很多时候只 是ؓ了方便或是最初设计的时候没有想到。?br />
      q样的例子在设计中很常见Q书中就l了一个很好的例子Q调制解调器。这是一个调? 解调器最基本的功能。但是这个类事实上完成了两个职责Q连接的建立和中断、数据的发送和接收。显Ӟq违反了SRP。这样做会有潜在的问题:当仅需要改? 数据q接方式Ӟ必须修改Modemc,而修改Modemcȝl果是使得M依赖Modemcȝ元素都需要重新编译,不管它是不是用到了数据连接功能? 解决的办法,书中也已l给出:重构Modemc,从中抽出两个接口Q一个专门负责连接、另一个专门负责数据发送。依赖Modemcȝ元素也要做相应的l? 化,Ҏ职责的不同分别依赖不同的接口。最后由ModemImplementationcd现这两个接口?br />fig-2.JPG       从这个例子中Q我们不隑֏玎ͼq反SRP通常是由于过于“真实”地设计了一个类所造成的。因此,解决办法是往更高一层进行抽? 化提取,对某个具体cȝ依赖改变为对一l接口或抽象cȝ依赖。当Ӟq个抽象化的提取应该Ҏ需要设计,而不是盲目提取。比如刚才这个Modem的例? 中,如果有必要,q可以把DataChannel抽象为DataSender和DataReceiver两个接口?br />


开攑ְ闭原?/span>——OCP
软g实体Q类Q模块,函数Q应该是可以扩展的,但是不可修改?/font>
 
原则
 
Ҏ展是开攄Q当需求改变时我们可以Ҏ块进行扩展,使其h新的功能
ҎҎ闭的,Ҏ块扩展时Q不需要改动原来的代码
面对抽象而不是面对细节,抽象比细节活的更?br />僵化的设计——如果程序中一处改动生连锁反应?/font>

Ҏ

条gcase   if/else 语句
 
重构

Replace Type Code With Class
Replace Type Code With State/Strategy
Replace Conditional with polymorphism
 
实例

开闭原则很单,一句话Q“Closed for Modification; Open for Extension”——“对变更关闭Q对扩展开䏀。开闭原则其实没什么好讲的Q我其归结Z个高层次的设计d。就q一ҎԌOCP的地位应该比SRP优先?

OCP的动机很单:软g是变化的。不论是优质的设计还是低劣的设计都无法回避这一问题。OCP说明了Y件设计应该尽可能C架构E_而又Ҏ满不同的需求?

Z么要OCPQ答案也很简单——重用?

“重用”,q不是什么Y件工E的专业词汇Q它是工E界所q的词汇。早在Y件出现前Q工E师们就在实践“重用”了。比如机C品,通过雉 件的l装得到最l的能够使用的工兗由于机械部件的设计和制造过E是极其复杂的,所以互换性是一个重要的Ҏ。一辆R可以用不同的发动机、不同的变速箱? 不同的轮胎……很多东西我们直接买来装上就可以了。这也是一个OCP的例子。(可能是由于我是搞机械n的吧Q所以就举些机械斚w的例子^_^Q?

如何在OO中引入OCP原则Q把对实体的依赖改ؓҎ象的依赖p了。下面的例子说明了这个过E:

05赛季的时候,一辆F1赛R有一台V10引擎。但是到?6赛季Q国际汽联修改了规则Q一辆F1赛R只能安装一台V8引擎。R队很快投入了新赛? 的研发,不幸的是Q从工程师那里得到消息,旧Rw的设计不能够装q新研发的引擎。我们不得不为新的引擎重新打造Rw,于是一辆新的赛车诞生了。但是,ȝ 的事接踵而来Q国际汽联频频修改规则,搞得设计师在“赛车”上改了又改Q最l变得不成样子,只能把它废弃?

OCP-fig1.JPG

Z能够重用q辆昂贵的赛车,工程师们提出了解x案:首先Q在车n的设计上预留出安装引擎的位置和管Uѝ然后,Ҏq些设计好的规范设计引擎Q或是引擎的适配器)。于是,新的赛R设计Ҏp栯生了?

 OCP-fig2.JPG

昄Q通过重构Q这里应用的是一个典型的Bridge模式。这个实现的关键之处在于我们预先l引擎留Z位置Q我们不必因为对引擎的规则的频频变更而制造相当多的Rw,而是可能地沿用和改良现有的车n?br />说到q里Q想说一说OO设计的一个误区?br />? 习OO语言的时候,Z能够说明“扎쀝(或者说“is-a”)q个概念Q教U书上经常用实际生活中的例子来解释。比如汽车是车,电R是RQF1赛R是汽 车,所以R是汽车、电车、F1赛R的上层抽象。这个例子ƈ没有错。问题是Q这L例子q于“Ş象”了Q如果OO设计直接可以将现实生活中的概念引用q? 来,那也׃需要什么Y件工E师了!OO设计的关键概忉|抽象。如果没有抽象,那所有的软g工程师的努力都是徒劳的。因为如果没有抽象,我们只能L造世 界中每一个对象。上面这个例子中Q我们应该看到“引擎”这个抽象的存在Q因R队的工程师们为它预留了位|,为它制定了设计规范?br />上面q个设计? 实现了后面要说的DIPQ依赖倒置原则Q。但是请CQOCP是OO设计原则中高层次的原则,其余的原则对OCP提供了不同程度的支持。ؓ了实现OCPQ? 我们会自觉或者不自觉地用到其它原则或是诸如Bridge、Decorator{设计模式。然而,对于一个应用系l而言Q实现OCPq不是设计目的,我们 所希望的只是一个稳定的架构。所以对OCP的追求也应该适可而止Q不要陷入过渡设计。正如Martin本h所_“No significant program can be 100% closed.”“Closure not complete but strategic?span style="font-size: 32pt; font-family: 宋体;">

Liskov替换原则—?/span> LSP 

子类型必能够替换它的基cd

原则

主要针对l承的设计原?br />所有派生类的行为功能必d客户E序对其基类所期望的保持一致?br />zcdL_cd客户E序的约?br />IS-A是关于行为方式的Q依赖客L序的调用方式
 
重构

Extract Supper Class
 
实例

长方形和正方?br />

OCP作ؓOO的高层原则,d使用“抽?Abstraction)”和“多?Polymorphism)”将设计中的静态结构改为动态结构,l持设计的封闭性?

“抽象”是语言提供的功能。“多态”由l承语义实现?

如此Q问题生了Q“我们如何去度量l承关系的质量??

Liskov?987q提Z一个关于承的原则“Inheritance should ensure that any property proved about supertype objects also holds for subtype objects.”——“承必ȝ保超cL拥有的性质在子cM仍然成立。”也是_当一个子cȝ实例应该能够替换M其超cȝ实例Ӟ它们之间才具? is-A关系?

该原则称为Liskov Substitution Principle——里氏替换原则。林先生在上课时风趣地称之ؓ“老鼠的儿子会打洞”。^_^

我们来研I一下LSP的实质。学习OO的时候,我们知道Q一个对象是一l状态和一pd行ؓ的组合体。状态是对象的内在特性,行ؓ是对象的外在Ҏ。LSP所表述的就是在同一个承体pM的对象应该有共同的行为特征?

q一点上Q表明了OO的承与日常生活中的l承的本质区别。D一个例子:生物学的分类体系中把企鹅归属为鸟cR我们模仿这个体p,设计Lcd关系?

 lsp-fig1.jpg

cZ鸟”中有个ҎflyQ企鹅自然也l承了这个方法,可是企鹅不能飞阿Q于是,我们在企鹅的cM覆盖了flyҎQ告诉方法的调用者:? 鹅是不会飞的。这完全W合常理。但是,q违反了LSPQ企鹅是鸟的子类Q可是企鹅却不能飞!需要注意的是,此处的“鸟”已l不再是生物学中的鸟了,它是? 件中的一个类、一个抽象?

有h会说Q企鹅不能飞很正常啊Q而且q样~写代码也能正常~译Q只要在使用q个cȝ客户代码中加一句判断就行了。但是,q就是问题所 在!首先Q客户代码和“企鹅”的代码很有可能不是同时设计的,在当今Y件外包一层又一层的开发模式下Q你甚至Ҏ不知道两个模块的原地是哪里Q也p? 上去修改客户代码了。客L序很可能是遗留系l的一部分Q很可能已经不再l护Q如果因计出q么一个“企鹅”而导致必M改客户代码,谁应该承担这部分 责Q呢?Q大概是上帝吧,谁叫他让“企鹅”不能飞的。^_^Q“修改客户代码”直接违反了OCPQ这是OCP的重要性。违反LSP既有的设计不能封 闭!

修正后的设计如下Q?

 lsp-fig2.jpg

但是Q这是LSP的全部了么?书中l了一个经典的例子Q这又是一个不W合常理的例子:正方形不是一个长方Ş。这个悖论的详细内容能在|上扑ֈQ我׃多废话了?

LSPq没有提供解册个问题的ҎQ而只是提Zq么一个问题?

于是Q工E师们开始关注如何确保对象的行ؓ?988q_B. Meyer提出了Design by ContractQ契U式设计Q理论。DbC从Ş式化Ҏ中借鉴了一套确保对象行为和自n状态的ҎQ其基本概念很简单:

  1. 每个Ҏ调用之前Q该Ҏ应该校验传入参数的正性,只有正确才能执行该方法,否则认ؓ调用方违反契U,不予执行。这UCؓ前置条g(Pre-condition)?
  2. 一旦通过前置条g的校验,Ҏ必须执行Qƈ且必ȝ保执行结果符合契U,q称之ؓ后置条g(Post-condition)?
  3. 对象本n有一套对自n状态进行校验的查条Ӟ以确保该对象的本质不发生改变Q这UCZ变式(Invariant)?/li>

以上是单个对象的U束条g。ؓ了满LSPQ当存在l承关系Ӟ子类中方法的前置条g必须与超cM被覆盖的Ҏ的前|条件相同或者更宽松Q而子cMҎ的后|条件必M类中被覆盖的方法的后置条g相同或者更Z根{?

一些OO语言中的Ҏ能够说明这一问题Q?

  • l承q且覆盖类Ҏ的时候,子类中的Ҏ的可见性必ȝ于或者大于超cM的方法的可见性,子类中的Ҏ所抛出的受异常只能是超cM对应Ҏ所抛出的受异常的子cR?
    public class SuperClass{
        
    public void methodA() throws IOException{}
    }


    public class SubClassA extends SuperClass{
        
    //this overriding is illegal.
        private void methodA() throws Exception{}
    }


    public class SubClassB extends SuperClass{
        
    //this overriding is OK.
        public void methodA() throws FileNotFoundException{}
    }

  • 从Java5开始,子类中的Ҏ的返回g可以是对应的类Ҏ的返回值的子类。这叫做“协变?Covariant)
    public class SuperClass {
        
    public Number caculate(){
            
    return null;
        }

    }


    public class SubClass extends SuperClass{
        
    //only compiles in Java 5 or later.
        public Integer caculate(){
            
    return null;
        }

    }

可以看出Q以上这些特性都非常好地遵@了LSP。但是DbC呢?很遗憾,L的面向对象语aQ不论是动态语aq是静态语aQ还没有加入对DbC的支持。但是随着AOP概念的生,怿不久DbC也将成ؓOO语言的一个重要特性之一?


依赖倒置原则—?DIP 

aQ高层模块不应依赖于底层模块Q两者都应该依赖于抽?br />bQ抽象不应该依赖于细节,l节应该依赖于抽?/font>

 
原则

如何解释倒置
高层依赖底层Q重用变得困难,而最l常重用的就是framework和各个独立的功能lg
高层依赖底层Q底层的改动直接反馈到高层,形成依赖的传?/font>
面向接口的编E?/font>
 

实例

Ioc模式
DomainObject / DomianObjectDataService
 

接口隔离原则—?ISP 

使用多个专门的接口比使用单一的L口总要好。换而言之,从一个客L的角度来Ԍ一个类对另外一个类的依赖性应当是建立在最接口上的?/p>原则

q于臃肿的接口是Ҏ口的污染。不应该客户依赖于它们不用的Ҏ?/p>

My object-oriented umbrellaQ摘自Design Patterns ExplainedQ?/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.

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!)

In Seattle, there are hundreds of thousands of these umbrellas in all kinds of colors. Most people call them cars.

实现ҎQ?br />1、 用委托分L?br />2、 用多重承分L?/p>

惛_一个朋友说的话Q所有的接口都只有一个方法,具体的类Ҏ自己需要什么方法去实现接口



h中立 2006-04-09 14:06 发表评论
]]>
վ֩ģ壺 һ߹ۿ| ޸XXXXɫ | ػaaëƬƵ| þþþAVۺϲҰ | avҹӰ߹ۿ| ?vŮ˵߹ۿ| þþþƷƵ| þþù޾Ʒ| þþƷƷ| 91ѹԲ2021| A˵߹ۿ| ޾Ʒþþþþþþþþþ| ѹۿҹ| һëƬѹۿշ| ˵Ӱ| ŷһ| freežž| Ʒþþþþù| avӰ| պƷAƬ| պav | һѹۿ | ޳aëƬ| ޳ߵӰ| ˳Ƶ| Ƶ| 99ȲƷ99| WWWɫ.COM| wŷs| avr | ƵƷһ| һƵ| þ޹vwww| ޹뾫ƷŮ˾þþò| ޻ɫѵӰ| 㶮ַѹ| ɫַȫ| պþۺĻ| þþƷavպ| ɫ͵ר| AVһ|