??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲国产天堂久久综合,91免费精品,久久国产精品免费一区二区三区 http://www.aygfsteel.com/freesky/category/22432.html自由天空zh-cnMon, 14 May 2007 07:16:47 GMTMon, 14 May 2007 07:16:47 GMT60Java模式设计之模板方法模?http://www.aygfsteel.com/freesky/archive/2007/05/14/117275.htmlfreeskyfreeskyMon, 14 May 2007 02:40:00 GMThttp://www.aygfsteel.com/freesky/archive/2007/05/14/117275.htmlhttp://www.aygfsteel.com/freesky/comments/117275.htmlhttp://www.aygfsteel.com/freesky/archive/2007/05/14/117275.html#Feedback0http://www.aygfsteel.com/freesky/comments/commentRss/117275.htmlhttp://www.aygfsteel.com/freesky/services/trackbacks/117275.html q是一个很单的模式Q却被非常广泛的使用。之所以简单是因ؓ在这个模式中仅仅使用Cl承关系?br>
l承关系׃自n的缺P被专家们扣上?#8220;|恶”的帽子?#8220;使用委派关系代替l承关系”Q?#8220;量使用接口实现而不是抽象类l承”{等专家警告Q让我们q些菜鸟对?#8220;另眼相看”?br>
其实Q承还是有很多自n的优Ҏ(gu)在。只是被大家滥用的似乎缺Ҏ(gu)加明显了。合理的利用l承关系Q还是能对你的系l设计v到很好的作用的。而模板方法模式就是其中的一个用范例?br>
二、定义与l构

GOFl模板方法(Template MethodQ模式定义一个操作中的算法的骨架Q而将一些步骤gq到子类中。得子cd以不改变一个算法的l构卛_重定义该法的某些特定步骤。这里的?法的l构Q可以理解ؓ你根据需求设计出来的业务程。特定的步骤是指那些可能在内容上存在变数的环节?br>
可以看出来,模板Ҏ(gu)模式也是Z巧妙解决变化对系l带来的影响而设计的。用模板方法ɾpȝ扩展性增强,最化了变化对pȝ的媄响。这一点,在下面的举例中可以很明显的看出来?br>
来看下这个简单模式的l构吧:

1) AbstractClassQ抽象类Q:定义了一到多个的抽象Ҏ(gu)Q以供具体的子类来实现它们;而且q要实现一个模板方法,来定义一个算法的骨架。该模板Ҏ(gu)不仅调用前面的抽象方法,也可以调用其他的操作Q只要能完成自n的命?br>
2) ConcreteClassQ具体类Q:实现父类中的抽象Ҏ(gu)以完成算法中与特定子cȝ关的步骤?br>
下面是模板方法模式的l构图。直接把《设计模式》上的图拿过来用下:


三、D?/strong>

q是在我刚刚分析完源码的JUnit中找个例子吧。JUnit中的TestCase以及它的子类是一个模板方法模式的例子。在TestCaseq个?象类中将整个试的流E设|好了,比如先执行SetupҎ(gu)初始化测试前提,在运行测试方法,然后再TearDown来取消测试设|。但是你在 Setup、TearDown里面作些什么呢Q鬼才知道呢Q!因此Q而这些步骤的具体实现都gq到子类中去Q也是你实现的试cM?br>
来看下相关的源代码吧?br>
q是TestCase中,执行试的模板方法。你可以看到Q里面正像前面定义中所说的那样Q它制定?#8220;法”的框架——先执行setUpҎ(gu)来做下初始化Q然后执行测试方法,最后执行tearDown释放你得到的资源?br>
public void runBare() throws Throwable {
setUp();

try {
runTest();
}

finally {
tearDown();
}
}

q就是上面用的两个Ҏ(gu)。与定义中不同的是,q两个方法ƈ没有被实Cؓ抽象Ҏ(gu)Q而是两个I的无ؓҎ(gu)Q被UCؓ钩子Ҏ(gu)Q。这是因为在试中,我们q?不是必须要让试E序使用q两个方法来初始化和释放资源的。如果是抽象Ҏ(gu)Q则子类们必ȝ它一个实玎ͼ不管用到用不到。这昄是不合理的。用钩子方 法,则你在需要的时候,可以在子cM重写q些Ҏ(gu)?br>
protected void setUp() throws Exception {}
protected void tearDown() throws Exception {}

四、适用情况

Ҏ(gu)上面对定义的分析Q以及例子的说明Q可以看出模板方法适用于以下情况:

1) 一ơ性实C个算法的不变的部分,q将可变的行为留l子cL实现?br>
2) 各子cM公共的行为应被提取出来ƈ集中C个公qcM以避免代码重复。其实这可以说是一U好的编码习惯了?br>
3) 控制子类扩展。模板方法只在特定点调用操作Q这样就只允许在q些点进行扩展。比如上面runBareQ)Ҏ(gu)只在runTest前面适用setUp?法。如果你不愿子类来修改你的模板方法定义的框架Q你可以采用两种方式来做Q一是在API中不体现Z的模板方法;二、将你的模板Ҏ(gu)|ؓfinal可 以了?br>
可以看出Q用模板方法模式可以将代码的公p为提取出来,辑ֈ复用的目的。而且Q在模板Ҏ(gu)模式中,是由父类的模板方法来控制子类中的具体实现。这样你在实现子cȝ时候,Ҏ(gu)不需要对业务程有太多的了解?/td>


 

转蝲Q?a >http://fly-net-cn.javaeye.com/blog/78611



freesky 2007-05-14 10:40 发表评论
]]>
Java设计模式之策略模?/title><link>http://www.aygfsteel.com/freesky/archive/2007/05/14/117266.html</link><dc:creator>freesky</dc:creator><author>freesky</author><pubDate>Mon, 14 May 2007 02:28:00 GMT</pubDate><guid>http://www.aygfsteel.com/freesky/archive/2007/05/14/117266.html</guid><wfw:comment>http://www.aygfsteel.com/freesky/comments/117266.html</wfw:comment><comments>http://www.aygfsteel.com/freesky/archive/2007/05/14/117266.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/freesky/comments/commentRss/117266.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/freesky/services/trackbacks/117266.html</trackback:ping><description><![CDATA[<p>{略模式QStrategy PatternQ中体现了两个非常基本的面向对象设计的基本原则:装变化的概念;~程中用接口,而不是对接口实现。策略模式的定义如下Q?</p> <p>定义一l算法,每个算法都装hQƈ且它们之间可以互换。策略模式ɘq些法在客L调用它们的时候能够互不媄响地变化?</p> <p>{略模式使开发h员能够开发出p多可替换的部分组成的软gQƈ且各个部分之间是p接的关系。弱q接的特性软gh更强的可扩展性,易于l护Q更重要的是Q它大大提高了Y件的可重用性?</p> <p>Z说明{略模式Q我们将首先讨论一下在Swing中是如何利用{略模式来绘制组件边界的Q然后讨论在Swing中用策略模式带来的好处Q最后讨论如何在软g中实现策略模式?</p> <center><font color=#000099><strong>SwingҎ(gu)</strong></font></center> <p>Ҏ(gu)有的SwinglgQ例如按钮、列表单{,都还可以l制Ҏ(gu)。在Swing中提供了各种 Ҏ(gu)cdQ例如bevel、etched、line、titled{。Swinglg的边框是通过JComponentcLl制的,该类是所有Swing lg的基c,实现了所有Swinglg公共的功能。在JComponent中有一个paintBorder()Ҏ(gu)Q该Ҏ(gu)为组件绘制边框。Swing?开发h员可以象下面的例子中所C那hl制Ҏ(gu)Q?</p> <p><ccid_nobr></ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code bgColor=#e6e6e6> <pre><ccid_code>// 一D实现paintBorderQ)Ҏ(gu)代码<br>protected void paintBorder(Graphics g) {<br> switch(getBorderType()) {<br> case LINE_BORDER: paintLineBorder(g);<br> break;<br> case ETCHED_BORDER: paintEtchedBorder(g);<br> break;<br> case TITLED_BORDER: paintTitledBorder(g);<br> break;<br> ...<br> }<br>}</ccid_code></pre> </td> </tr> </tbody> </table> </p> <p>h意上面的代码只是一U假设,事实上Swing的开发h员ƈ没有q样实现 paintBorderQ)Ҏ(gu)。在上面的代码中Q在JComponent中绘制边框的代码被直接写入了paintBorderQ)Ҏ(gu)中,q意味着 JComponent和绘制边框的功能被紧密地l合在了一赗很自然地大家会联想到如果需要实CU新的边框类型,开发h员必M改至三处代码:首先?加一个常量,该常量代表新d的边框的cd|其次需要在Switch语句中增加一个case语句Q最后开发h员需要实现paintXXXBorder Q)Ҏ(gu)Q其中XXX代表新边框的名称?</p> <p>很显然要扩展上面paintBorder()Ҏ(gu)的功能是一件很困难的事情,不仅 仅是因ؓ开发h员需要增加一U新的边框类型,更麻烦的是开发h员很难修改JComponentcRJComponentcdl被~译CSwing的开?工具中,如果开发h员想修改它的话,必须获得Swing的源代码Q修改后重新~译Swing。同时在用户的计机上与需要用新~译的Swing API。另外所有的Swinglg都可以用开发h员新d的边框类型。有可能开发h员只希望新的Ҏ(gu)被某些组件用,但是现在开发h员无法对使用该边?的组件进行限制?</p> <p>开发h员有更好的实现方法吗Q答案就是策略模式。通过{略模式Q可以将 JComponent和实现绘制边框的代码分离开来,q样开发h员在增加或修改绘制边框的代码使就不需要修改JComponent的代码。通过应用{略?式,开发h员将变化的概念(在这个例子中是绘制边框)装hQ然后通过一个Border接口QɽE序能够重用l制Ҏ(gu)的功能。下面让我们来看 JComponent是如何利用策略模式来实现l制Ҏ(gu)的功能的Q?</p> <p><ccid_nobr></ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code bgColor=#e6e6e6> <pre><ccid_code>// Swing中paintBorder()Ҏ(gu)的源代码<br>protected void paintBorder(Graphics g) {<br> Border border = getBorder();<br> if (border != null) {<br> border.paintBorder(this, g, 0, 0, getWidth(), getHeight());<br> }<br>}</ccid_code></pre> </td> </tr> </tbody> </table> </p> <p>上面的paintBorder()Ҏ(gu)通过一个border对象l制了组件的Ҏ(gu)?q样border对象替代了前一个例子中的JComponent装了边框绘制的功能。我们还应该注意到JComponent一个对自己的引用传递给?Border.paintBorderQ)Ҏ(gu)Q这是因为Border的实例必ȝ道它对应的组件的信息Q这U方式通常被称为委托。通过q种方式Q一个对 象可以将功能委托l另一个对象来实现?</p> <p>在JComponentcM引用了一个Border对象Q通过JComponent.getBorderQ)Ҏ(gu)可以获得该Border对象。下面的代码演示了如何设定和获得Border对象Q?</p> <p><ccid_nobr></ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code bgColor=#e6e6e6> <pre><ccid_code>...<br>private Border border;<br>...<br>public void setBorder(Border border) {<br> Border oldBorder = this.border;<br> this.border = border;<br> firePropertyChange("border", oldBorder, border);<br> if (border != oldBorder) {<br> if (border == null || oldBorder == null || !(border.getBorderInsets(this).<br> equals(oldBorder.getBorderInsets(this)))) {<br> revalidate();<br> } <br> repaint();<br> }<br>}<br>...<br>public Border getBorder() {<br> return border;<br>}</ccid_code></pre> </td> </tr> </tbody> </table> </p> <p>当开发h员通过JComponent.setBorderQ)Ҏ(gu)讑֮了一个组件的 Ҏ(gu)后,JComponentcdZ个属性更C件。如果新的边框和以前的边框不同的话,setBorderQ)Ҏ(gu)重新绘制边框?getBorderQ)Ҏ(gu)仅仅q回对Border对象的引用。图1昄了Border的类l构图: </p> <center><img alt="" src="http://industry.ccidnet.com/col/attachment/2003/2/99506.jpg"></center> <center>? Border的类l构?/center> <p>通过cȝ构图我们可以看到QJComponentcM保存了一个对Border对象的引用。由于Border是一个接口,Swinglg可以使用M一个实CBorder接口的类?</p> <p>现在我们已经知道了JComponent是如何利用策略模式来l制lg的边框的。下面让我们通过实现一个新的边框类型来试一下它的可扩展性?</p> <center><font color=#000099><strong>实现一个新的边框类?/strong></font></center> <p>?中是一个有三个JPanel对象的小E序Q每个JPanel对象有各自不同的Ҏ(gu)Q每个边框对应一个HandleBorder实例?</p> <center><img alt="" src="http://industry.ccidnet.com/col/attachment/2003/2/99507.jpg"></center> <center>? 新的Ҏ(gu)cd</center> <p><ccid_nobr></ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code bgColor=#e6e6e6> <pre><ccid_code>// HandleBorder.java<br>import java.awt.*;<br>import javax.swing.*;<br>import javax.swing.border.*;<br>public class HandleBorder extends AbstractBorder {<br> protected Color lineColor;<br> protected int thick;<br> public HandleBorder() {<br> this(Color.black, 6);<br> }<br> public HandleBorder(Color lineColor, int thick) {<br> this.lineColor = lineColor;<br> this.thick = thick;<br> }<br> public void paintBorder(Component component, <br> Graphics g, int x, int y, int w, int h) {<br> Graphics copy = g.create();<br> if(copy != null) {<br> try {<br> copy.translate(x,y);<br> paintRectangle(component,copy,w,h);<br> paintHandles(component,copy,w,h);<br> }<br> finally {<br> copy.dispose();<br> }<br> }<br> }<br> public Insets getBorderInsets() {<br> return new Insets(thick,thick,thick,thick);<br> }<br> protected void paintRectangle(Component c, Graphics g,<br> int w, int h) {<br> g.setColor(lineColor);<br> g.drawRect(thick/2,thick/2,w-thick-1,h-thick-1);<br> }<br> protected void paintHandles(Component c, Graphics g,<br> int w, int h) {<br> g.setColor(lineColor);<br> g.fillRect(0,0,thick,thick); <br> g.fillRect(w-thick,0,thick,thick); <br> g.fillRect(0,h-thick,thick,thick); <br> g.fillRect(w-thick,h-thick,thick,thick); <br> g.fillRect(w/2-thick/2,0,thick,thick); <br> g.fillRect(0,h/2-thick/2,thick,thick); <br> g.fillRect(w/2-thick/2,h-thick,thick,thick); <br> g.fillRect(w-thick,h/2-thick/2,thick,thick); <br> } <br>}</ccid_code></pre> </td> </tr> </tbody> </table> </p> <p>HandleBordercȝ承了 javax.swing.border.AbstractBordercdƈ重写了paintBorderQ)和getBorderInsetsQ)?HandleBorder是如何实现的其实q不重要Q重要的是由于Swing使用了策略模型,开发h员能够很方便地增加新的边框类型。下面的代码昄了如 何用HandleBordercR在q个例子中创Z三个JPanel对象QƈҎ(gu)个JPanel对象讑֮一个HandleBorder实例作ؓҎ(gu)?</p> <p><ccid_nobr></ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code bgColor=#e6e6e6> <pre><ccid_code>// Test.java<br>import javax.swing.*;<br>import javax.swing.border.*;<br>import java.awt.*;<br>import java.awt.event.*;<br>public class Test extends JFrame {<br> public static void main(String[] args) {<br> JFrame frame = new Test();<br> frame.setBounds(100, 100, 500, 200);<br> frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);<br> frame.show();<br> }<br> public Test() {<br> super("实现一个新的边框类?);<br> Container contentPane = getContentPane();<br> JPanel[] panels = { new JPanel(), <br> new JPanel(), new JPanel() };<br> Border[] borders = { new HandleBorder(),<br> new HandleBorder(Color.red, 8),<br> new HandleBorder(Color.blue, 10) };<br> contentPane.setLayout(<br> new FlowLayout(FlowLayout.CENTER,20,20));<br> for(int i=0; i < panels.length; ++i) {<br> panels[i].setPreferredSize(new Dimension(100,100));<br> panels[i].setBorder(borders[i]);<br> contentPane.add(panels[i]);<br> }<br> }<br>}</ccid_code></pre> </td> </tr> </tbody> </table> </p> <p>q记得在上面的例子中曾提到在有些情况下,对组件的引用会作为参C递给 Border.paintBorderQ)Ҏ(gu)。虽然上面的HandleBordercL有保存对lg的引用,但是有些情况下Border接口的实现类?使用到对lg的引用ƈ从中获得关于lg的信息。例如在EtchedBorder中,paintBorderQ)Ҏ(gu)通过对组件的引用获得它对应的lg的阴 影和高光Ԍ </p> <p><ccid_nobr></ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code bgColor=#e6e6e6> <pre><ccid_code>// 下面的代码截取自javax.swing.border.EtchedBorder<br>public void paintBorder(Component component, Graphics g, int x, int y, <br> int width, int height) {<br> int w = width;<br> int h = height;<br> g.translate(x, y);<br> g.setColor(etchType == LOWERED? getShadowColor(component) : <br>getHighlightColor(component));<br> g.drawRect(0, 0, w-2, h-2);<br> g.setColor(etchType == LOWERED? getHighlightColor(component) : <br>getShadowColor(component));<br> g.drawLine(1, h-3, 1, 1);<br> g.drawLine(1, 1, w-3, 1);<br> g.drawLine(0, h-1, w-1, h-1);<br> g.drawLine(w-1, h-1, w-1, 0);<br> g.translate(-x, -y);<br>}</ccid_code></pre> </td> </tr> </tbody> </table> </p> <center><font color=#000099><strong>如何实现{略模型</strong></font></center> <p>通过以下步骤Q开发h员可以很Ҏ(gu)地在软g中实现策略模型: </p> <p>1Q对{略对象定义一个公共接口?</p> <p>2Q编写策略类Q该cdC上面的公共接口?</p> <p>3Q在使用{略对象的类中保存一个对{略对象的引用?</p> <p>4Q在使用{略对象的类中,实现对策略对象的set和getҎ(gu)?</p> <p>在SwingҎ(gu)的例子中Q公共接口是javax.swing.Border。策略类是LineBorder、EtchedBorder、HandleBorder{。而用策略对象的cLJComponent?</p> <p><br> </p> <p>转蝲Q?a >http://fly-net-cn.javaeye.com/blog/78615</a></p> <img src ="http://www.aygfsteel.com/freesky/aggbug/117266.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/freesky/" target="_blank">freesky</a> 2007-05-14 10:28 <a href="http://www.aygfsteel.com/freesky/archive/2007/05/14/117266.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">¹</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ѩ</a>| <a href="http://" target="_blank">ڳ</a>| <a href="http://" target="_blank">н</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ǩ</a>| <a href="http://" target="_blank">°Ͷ</a>| <a href="http://" target="_blank">µ</a>| <a href="http://" target="_blank">κ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">֦</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ͽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">质</a>| <a href="http://" target="_blank">¦</a>| <a href="http://" target="_blank">˾</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͨ</a>| <a href="http://" target="_blank">п</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ǭ</a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank">Ĭ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>