﻿<?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>C++博客-woaidongmao-随笔分类-OOP</title><link>http://www.cppblog.com/woaidongmao/category/9181.html</link><description>文章均收录自他人博客，但不喜标题前加-[转贴]，因其丑陋，见谅！~</description><language>zh-cn</language><lastBuildDate>Mon, 22 Dec 2008 14:32:10 GMT</lastBuildDate><pubDate>Mon, 22 Dec 2008 14:32:10 GMT</pubDate><ttl>60</ttl><item><title>OOP遵照：接口隔离原则--ISP</title><link>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70102.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 22 Dec 2008 13:36:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70102.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/70102.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70102.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/70102.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/70102.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><b><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">一、<span lang="EN-US">ISP</span>简介（<span lang="EN-US">ISP--Interface Segregation Principle</span>）：</span></b><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><?xml:namespace prefix = o /><o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">使用多个专门的接口比使用单一的总接口要好。<span lang="EN-US"><br></span>一个类对另外一个类的依赖性应当是建立在最小的接口上的。<span lang="EN-US"><br></span>一个接口代表一个角色，不应当将不同的角色都交给一个接口。没有关系的接口合并在一起，形成一个臃肿的大接口，这是对角色和接口的污染。<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">“</span><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">不应该强迫客户依赖于它们不用的方法。接口属于客户，不属于它所在的类层次结构。<span lang="EN-US">”</span>这个说得很明白了，再通俗点说，不要强迫客户使用它们不用的方法，如果强迫用户使用它们不使用的方法，那么这些客户就会面临由于这些不使用的方法的改变所带来的改变。<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><b><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">二、举例说明：</span></b><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">参考下图的设计，在这个设计里，取款、存款、转帐都使用一个通用界面接口，也就是说，每一个类都被强迫依赖了另两个类的接口方法，那么每个类有可能因为另外两个类的方法<span lang="EN-US">(</span>跟自己无关<span lang="EN-US">)</span>而被影响。拿取款来说，它根本不关心<span lang="EN-US">“</span>存款操作<span lang="EN-US">”</span>和<span lang="EN-US">“</span>转帐操作<span lang="EN-US">”</span>，可是它却要受到这两个方法的变化的影响。<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><a href="http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/OOPISP_12FAD/clip_image001_2.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="518" alt="clip_image001" src="http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/OOPISP_12FAD/clip_image001_thumb.jpg" width="379" border="0" v:shapes="_x0000_i1025"></a></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br></span><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">那么我们该如何解决这个问题呢？参考下图的设计，为每个类都单独设计专门的操作接口，使得它们只依赖于它们关系的方法，这样就不会互相影了！<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><b><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><a href="http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/OOPISP_12FAD/clip_image002_2.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="648" alt="clip_image002" src="http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/OOPISP_12FAD/clip_image002_thumb.jpg" width="408" border="0" v:shapes="_x0000_i1026"></a></span></b></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><b><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br></span></b><b><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">三、实现方法：</span></b><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br>1</span><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">、使用委托分离接口<span lang="EN-US"><br>2</span>、使用多重继承分离接口<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%"><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%"><o:p>&nbsp;</o:p></span></p><img src ="http://www.cppblog.com/woaidongmao/aggbug/70102.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-12-22 21:36 <a href="http://www.cppblog.com/woaidongmao/archive/2008/12/22/70102.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OOP遵照：依赖倒置原则(DIP)</title><link>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70101.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 22 Dec 2008 13:34:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70101.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/70101.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70101.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/70101.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/70101.html</trackback:ping><description><![CDATA[<p style="line-height: 200%"><span style="color: black">依赖倒置（<span lang="EN-US">Dependence Inversion Principle</span>）原则讲的是：要依赖于抽象，不要依赖于具体。<span lang="EN-US"><?xml:namespace prefix = o /><o:p></o:p></span></span></p> <p style="line-height: 200%"><span style="color: black">简单的说，依赖倒置原则要求客户端依赖于抽象耦合。原则表述：<span lang="EN-US">phpma</span>开源 罗江游鱼<span lang="EN-US"><o:p></o:p></span></span></p> <p style="line-height: 200%"><span style="color: black">抽象不应当依赖于细节；细节应当依赖于抽象；<span lang="EN-US"><br></span>要针对接口编程，不针对实现编程。<span lang="EN-US"><o:p></o:p></span></span></p> <p style="line-height: 200%"><span style="color: black">反面例子：<span lang="EN-US"><br><br>&nbsp;<a href="http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/OOPDIP_12F50/clip_image001_2.gif"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="87" alt="clip_image001" src="http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/OOPDIP_12F50/clip_image001_thumb.gif" width="246" border="0" v:shapes="_x0000_i1025"></a><br><br></span>缺点：耦合太紧密，<span lang="EN-US">Light</span>发生变化将影响<span lang="EN-US">ToggleSwitch</span>。<span lang="EN-US"><o:p></o:p></span></span></p> <p style="line-height: 200%"><span style="color: black">解决办法一：<span lang="EN-US"><br></span>将<span lang="EN-US">Light</span>作成<span lang="EN-US">Abstract</span>，然后具体类继承自<span lang="EN-US">Light</span>。<span lang="EN-US"><br>&nbsp;<a href="http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/OOPDIP_12F50/clip_image002_2.gif"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="186" alt="clip_image002" src="http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/OOPDIP_12F50/clip_image002_thumb.gif" width="292" border="0" v:shapes="_x0000_i1026"></a><o:p></o:p></span></span></p> <p style="line-height: 200%"><span style="color: black">优点：<span lang="EN-US">ToggleSwitch</span>依赖于抽象类<span lang="EN-US">Light</span>，具有更高的稳定性，而<span lang="EN-US">BulbLight</span>与<span lang="EN-US">TubeLight</span>继承自<span lang="EN-US">Light</span>，可以根据<span lang="EN-US">"</span>开放－封闭<span lang="EN-US">"</span>原则进行扩展。只要<span lang="EN-US">Light</span>不发生变化，<span lang="EN-US">BulbLight</span>与<span lang="EN-US">TubeLight</span>的变化就不会波及<span lang="EN-US">ToggleSwitch</span>。<span lang="EN-US"><o:p></o:p></span></span></p> <p style="line-height: 200%"><span style="color: black">缺点：如果用<span lang="EN-US">ToggleSwitch</span>控制一台电视就很困难了。总不能让<span lang="EN-US">TV</span>继承自<span lang="EN-US">Light</span>吧。<span lang="EN-US"><o:p></o:p></span></span></p> <p style="line-height: 200%"><span style="color: black">解决方法二：<span lang="EN-US"><br>&nbsp;<a href="http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/OOPDIP_12F50/clip_image003_2.gif"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="314" alt="clip_image003" src="http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/OOPDIP_12F50/clip_image003_thumb.gif" width="509" border="0" v:shapes="_x0000_i1027"></a><o:p></o:p></span></span></p> <p style="line-height: 200%"><span style="color: black">优点：更为通用、更为稳定。<span lang="EN-US"><o:p></o:p></span></span></p> <p style="line-height: 200%"><span style="color: black">结论：<span lang="EN-US"><br></span>使用传统过程化程序设计所创建的依赖关系，策略依赖于细节，这是糟糕的，因为策略受到细节改变的影响。依赖倒置原则使细节和策略都依赖于抽象，抽象的稳定性决定了系统的稳定性。<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 200%"><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 200%"><o:p>&nbsp;</o:p></span></p><img src ="http://www.cppblog.com/woaidongmao/aggbug/70101.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-12-22 21:34 <a href="http://www.cppblog.com/woaidongmao/archive/2008/12/22/70101.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OOP遵照：Liskov替换原则--LSP</title><link>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70100.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 22 Dec 2008 13:32:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70100.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/70100.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70100.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/70100.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/70100.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="line-height: 150%"><font color="#000000"><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体"><strong>一、<span lang="EN-US">LSP</span>简介（<span lang="EN-US">LSP--Liskov Substitution Principle</span>）：</strong></span></font></p> <p class="MsoNormal" style="line-height: 150%"><font color="#000000"><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体"></span></font><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体"><font color="#000000">定义：如果对于类型<span lang="EN-US">S</span>的每一个对象<span lang="EN-US">o1</span>，都有一个类型<span lang="EN-US">T</span>的对象<span lang="EN-US">o2</span>，使对于任意用类型<span lang="EN-US">T</span>定义的程序<span lang="EN-US">P</span>，将<span lang="EN-US">o2</span>替换为<span lang="EN-US">o1</span>，<span lang="EN-US">P</span>的行为保持不变，则称<span lang="EN-US">S</span>为<span lang="EN-US">T</span>的一个子类型。</font><span lang="EN-US"><br></span><font color="#000000">子类型必须能够替换它的基类型。<span lang="EN-US">LSP</span>又称里氏替换原则。</font><span lang="EN-US"><br></span><font color="#000000">对于这个原则，通俗一些的理解就是，父类的方法都要在子类中实现或者重写。</font><span lang="EN-US"><br><font color="#000000">&nbsp;<br></font></span><strong><font color="#000000">二、举例说明：</font></strong><span lang="EN-US"><br></span><font color="#000000">对于依赖倒置原则，说的是父类不能依赖子类，它们都要依赖抽象类。这种依赖是我们实现代码扩展和运行期内绑定（多态）的基础。因为一旦类的使用者依赖某个具体的类，那么对该依赖的扩展就无从谈起；而依赖某个抽象类，则只要实现了该抽象类的子类，都可以被类的使用者使用，从而实现了系统的扩展。</font></span><font color="#000000"><span lang="EN-US" style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体">phpma</span><span style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体">开源</span></font><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体"><br></span><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体"><font color="#000000">但是，光有依赖倒置原则，并不一定就使我们的代码真正具有良好的扩展性和运行期内绑定。请看下面的代码：</font><span lang="EN-US"><br><font color="#000000">public class Animal<br>{<br>&nbsp;&nbsp;&nbsp; private string name;<br>&nbsp;&nbsp;&nbsp; public Animal(string name)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.name = name;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; public void Description()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("This is a(an) " + name);<br>&nbsp;&nbsp;&nbsp; }<br>}<br>&nbsp;<br>//</font></span><font color="#000000">下面是它的子类猫类：</font></span><font color="#000000"><span lang="EN-US" style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体">phpma</span><span style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体">开源</span></font><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体"><br><font color="#000000">public class Cat : Animal<br>{<br>&nbsp;&nbsp;&nbsp; public Cat(string name)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; public void Mew()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("The cat is saying like 'mew'");<br>&nbsp;&nbsp;&nbsp; }<br>}<br>&nbsp;<br>//</font></span><font color="#000000"><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体">下面是它的子类狗类：</span><span lang="EN-US" style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体">phpma</span><span style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体">开源</span></font><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体"><br><font color="#000000">public class Dog : Animal<br>{<br>&nbsp;&nbsp;&nbsp; public Dog(string name)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; public void Bark()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("The dog is saying like 'bark'");<br>&nbsp;&nbsp;&nbsp; }<br>}<?xml:namespace prefix = o /><o:p></o:p></font></span></p> <p class="MsoNormal" style="line-height: 150%"><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体"><o:p><font color="#000000">&nbsp;</font></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><font color="#000000">//</font></span><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><font color="#000000">最后，我们来看客户端的调用：</font><span lang="EN-US"><br><font color="#000000">public void DecriptionTheAnimal(Animal animal)<br>{<br>&nbsp;&nbsp;&nbsp; if (typeof(animal) is Cat)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cat cat = (Cat)animal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cat.Decription();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cat.Mew();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; else if (typeof(animal) is Dog)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dog dog = (Dog)animal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dog.Decription();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dog.Bark();<br>&nbsp;&nbsp;&nbsp; }<br>}<br></font></span><font color="#000000">通过上面的代码，我们可以看到虽然客户端的依赖是对抽象的依赖，但依然这个设计的扩展性不好，运行期绑定没有实现。</font></span><font color="#000000"><span lang="EN-US" style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">phpma</span><span style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">开源</span></font><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br></span><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><font color="#000000">是什么原因呢？其实就是因为不满足里氏替换原则，子类如<span lang="EN-US">Cat</span>有<span lang="EN-US">Mew()</span>方法父类根本没有，<span lang="EN-US">Dog</span>类有<span lang="EN-US">Bark()</span>方法父类也没有，两个子类都不能替换父类。这样导致了系统的扩展性不好和没有实现运行期内绑定。</font><span lang="EN-US"><br></span><font color="#000000">现在看来，一个系统或子系统要拥有良好的扩展性和实现运行期内绑定，有两个必要条件：第一是依赖倒置原则；第二是里氏替换原则。这两个原则缺一不可。</font><span lang="EN-US"><br><font color="#000000">&nbsp;<br></font></span><font color="#000000">我们知道，在我们的大多数的模式中，我们都有一个共同的接口，然后子类和扩展类都去实现该接口。</font><span lang="EN-US"><br></span><font color="#000000">下面是一段原始代码：</font><span lang="EN-US"><br><font color="#000000">if(action.Equals(“add”))<br>{<br>&nbsp; //do add action<br>}<br>else if(action.Equals(“view”))<br>{<br>&nbsp; //do view action<br>}<br>else if(action.Equals(“delete”))<br>{<br>&nbsp; //do delete action<br>}<br>else if(action.Equals(“modify”))<br>{<br>&nbsp; //do modify action<br>}<br></font></span><font color="#000000">我们首先想到的是把这些动作分离出来，就可能写出如下的代码：</font></span><font color="#000000"><span lang="EN-US" style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">phpma</span><span style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">开源</span></font><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br><font color="#000000">public class AddAction<br>{<br>&nbsp;&nbsp;&nbsp; public void add()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //do add action<br>&nbsp;&nbsp;&nbsp; }<br>}<br>public class ViewAction<br>{<br>&nbsp;&nbsp;&nbsp; public void view()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //do view action<br>&nbsp;&nbsp;&nbsp; }<br>}<br>public class deleteAction<br>{<br>&nbsp;&nbsp;&nbsp; public void delete()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //do delete action<br>&nbsp;&nbsp;&nbsp; }<br>}<br>public class ModifyAction<br>{<br>&nbsp;&nbsp;&nbsp; public void modify()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //do modify action<br>&nbsp;&nbsp;&nbsp; }<br>}<br></font></span><font color="#000000"><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">我们可以看到，这样代码将各个行为独立出来，满足了单一职责原则，但这远远不够，因为它不满足依赖颠倒原则和里氏替换原则。</span><span lang="EN-US" style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">phpma</span><span style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">开源</span></font><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br></span><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><font color="#000000">下面我们来看看命令模式对该问题的解决方法：</font><span lang="EN-US"><br><font color="#000000">public interface Action<br>{<br>&nbsp;&nbsp;&nbsp; public void doAction();<br>}<br>//</font></span><font color="#000000">然后是各个实现：</font><span lang="EN-US"><br><font color="#000000">public class AddAction : Action<br>{<br>&nbsp;&nbsp;&nbsp; public void doAction()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //do add action<br>&nbsp;&nbsp;&nbsp; }<br>}<br>public class ViewAction : Action<br>{<br>&nbsp;&nbsp;&nbsp; public void doAction()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //do view action<br>&nbsp;&nbsp;&nbsp; }<br>}<br>public class deleteAction : Action<br>{<br>&nbsp;&nbsp;&nbsp; public void doAction()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //do delete action<br>&nbsp;&nbsp;&nbsp; }<br>}<br>public class ModifyAction : Action<br>{<br>&nbsp;&nbsp;&nbsp; public void doAction()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //do modify action<br>&nbsp;&nbsp;&nbsp; }<br>}<br>//</font></span><font color="#000000">这样，客户端的调用大概如下：</font><span lang="EN-US"><br><font color="#000000">public void execute(Action action)<br>{<br>&nbsp;&nbsp;&nbsp; action.doAction();<br>}<br></font></span><font color="#000000">看，上面的客户端代码再也没有出现过<span lang="EN-US">typeof</span>这样的语句，扩展性良好，也有了运行期内绑定的优点。 </font></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span lang="EN-US"><o:p></o:p></span></span>&nbsp;</p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align="left"><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><strong><font color="#000000">三、<span lang="EN-US">LSP</span>优点：</font></strong><span lang="EN-US"><br><font color="#000000">1</font></span><font color="#000000">、保证系统或子系统有良好的扩展性。只有子类能够完全替换父类，才能保证系统或子系统在运行期内识别子类就可以了，因而使得系统或子系统有了良好的扩展性。</font><span lang="EN-US"><br><font color="#000000">2</font></span><font color="#000000">、实现运行期内绑定，即保证了面向对象多态性的顺利进行。这节省了大量的代码重复或冗余。避免了类似<span lang="EN-US">instanceof</span>这样的语句，或者<span lang="EN-US">getClass()</span>这样的语句，这些语句是面向对象所忌讳的。</font><span lang="EN-US"><br><font color="#000000">3</font></span><font color="#000000">、有利于实现契约式编程。契约式编程有利于系统的分析和设计，指我们在分析和设计的时候，定义好系统的接口，然后再编码的时候实现这些接口即可。在父类里定义好子类需要实现的功能，而子类只要实现这些功能即可。</font><span lang="EN-US"><br><font color="#000000">&nbsp;<br></font></span><strong><font color="#000000">四、使用<span lang="EN-US">LSP</span>注意点：</font></strong><span lang="EN-US"><br><font color="#000000">1</font></span><font color="#000000">、此原则和<span lang="EN-US">OCP</span>的作用有点类似，其实这些面向对象的基本原则就<span lang="EN-US">2</span>条：<span lang="EN-US">1</span>：面向接口编程，而不是面向实现；<span lang="EN-US">2</span>：用组合而不主张用继承</font><span lang="EN-US"><br><font color="#000000">2</font></span><font color="#000000">、<span lang="EN-US">LSP</span>是保证<span lang="EN-US">OCP</span>的重要原则</font><span lang="EN-US"><br><font color="#000000">3</font></span><font color="#000000">、这些基本的原则在实现方法上也有个共同层次，就是使用中间接口层，以此来达到类对象的低偶合，也就是抽象偶合！</font><span lang="EN-US"><br><font color="#000000">4</font></span><font color="#000000">、派生类的退化函数：派生类的某些函数退化（变得没有用处），<span lang="EN-US">Base</span>的使用者不知道不能调用<span lang="EN-US">f</span>，会导致替换违规。在派生类中存在退化函数并不总是表示违反了<span lang="EN-US">LSP</span>，但是当存在这种情况时，应该引起注意。</font><font color="#000000"><span lang="EN-US"> <br>5</span>、从派生类抛出异常：如果在派生类的方法中添加了其基类不会抛出的异常。如果基类的使用者不期望这些异常，那么把他们添加到派生类的方法中就可以能会导致不可替换性。<span lang="EN-US"><o:p></o:p></span></font></span></p> <p class="MsoNormal" style="line-height: 150%"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体"><o:p>&nbsp;</o:p></span></p><img src ="http://www.cppblog.com/woaidongmao/aggbug/70100.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-12-22 21:32 <a href="http://www.cppblog.com/woaidongmao/archive/2008/12/22/70100.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OOP遵照：单一职责原则--SRP</title><link>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70098.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 22 Dec 2008 13:29:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70098.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/70098.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70098.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/70098.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/70098.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><b><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">一、<span lang="EN-US">SRP</span>简介（<span lang="EN-US">SRP--Single-Responsibility Principle</span>）：</span></b><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><?xml:namespace prefix = o /><o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">就一个类而言，应该只专注于做一件事和仅有一个引起它变化的原因。</span><span lang="EN-US" style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">PHP</span><span style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">开源<span lang="EN-US">com</span></span><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">所谓职责，我们可以理解他为功能，就是设计的这个类功能应该只有一个，而不是两个或更多。也可以理解为引用变化的原因，当你发现有两个变化会要求我们修改这个类，那么你就要考虑撤分这个类了。因为职责是变化的一个轴线，当需求变化时，该变化会反映类的职责的变化</span><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">。</span><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: blue; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">“</span><span style="font-size: 12pt; color: blue; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">就像一个人身兼数职，而这些事情相互关联不大，，甚至有冲突，那他就无法很好的解决这些职责，应该分到不同的人身上去做才对。<span lang="EN-US">”</span></span><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><b><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">二、举例说明：</span></b><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">违反<span lang="EN-US">SRP</span>原则代码<span lang="EN-US">: </span></span><span lang="EN-US" style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">PHP</span><span style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">开源<span lang="EN-US">com</span></span><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br>modem</span><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">接口明显具有两个职责：连接管理和数据通讯；<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="background: #e6e6e6; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">interface Modem<br>{<br>&nbsp;&nbsp;&nbsp; public void dial(string pno);<br>&nbsp;&nbsp;&nbsp; public void hangup();<br>&nbsp;&nbsp;&nbsp; public void send(char c);<br>&nbsp;&nbsp;&nbsp; public void recv();<br>}</span><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">如果应用程序变化影响连接函数，那么就需要重构：<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="background: #e6e6e6; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">interface DataChannel<br>{<br>&nbsp;&nbsp;&nbsp; public void send(char c);<br>&nbsp;&nbsp;&nbsp; public void recv();<br>}<br>interface Connection<br>{<br>&nbsp;&nbsp;&nbsp; public void dial(string pno);<br>&nbsp;&nbsp;&nbsp; public void hangup();<br>}</span><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><b><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">三、<span lang="EN-US">SRP</span>优点：</span></b><span lang="EN-US" style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">PHP</span><span style="font-size: 12pt; color: white; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">开源<span lang="EN-US">com</span></span><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">消除耦合，减小因需求变化引起代码僵化性臭味 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><b><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">四、使用<span lang="EN-US">SRP</span>注意点：</span></b><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">1</span><span style="font-size: 12pt; color: #444444; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">、一个合理的类，应该仅有一个引起它变化的原因，即单一职责；<span lang="EN-US"> <br>2</span>、在没有变化征兆的情况下应用<span lang="EN-US">SRP</span>或其他原则是不明智的；<span lang="EN-US"> <br>3</span>、在需求实际发生变化时就应该应用<span lang="EN-US">SRP</span>等原则来重构代码；<span lang="EN-US"> <br>4</span>、使用测试驱动开发会迫使我们在设计出现臭味之前分离不合理代码；<span lang="EN-US"> <br>5</span>、如果测试不能迫使职责分离，僵化性和脆弱性的臭味会变得很强烈，那就应该用<span lang="EN-US">Facade</span>或<span lang="EN-US">Proxy</span>模式对代码重构；<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%"><span lang="EN-US" style="font-size: 12pt; line-height: 150%"><o:p>&nbsp;</o:p></span></p><img src ="http://www.cppblog.com/woaidongmao/aggbug/70098.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-12-22 21:29 <a href="http://www.cppblog.com/woaidongmao/archive/2008/12/22/70098.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OOP遵照：开放封闭原则--OCP</title><link>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70097.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 22 Dec 2008 13:27:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70097.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/70097.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70097.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/70097.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/70097.html</trackback:ping><description><![CDATA[<p style="line-height: 150%"><b style="mso-bidi-font-weight: normal"><span style="color: black">一、<span lang="EN-US">OCP</span>简介（<span lang="EN-US">OCP--Open-Closed Principle</span>）：</span></b><span lang="EN-US" style="color: black"><br>Software entities(classes,modules,functions,etc.) should be open for extension, but closed for modification</span><span style="color: black">。<span lang="EN-US"><br></span>软件实体应当对扩展开放，对修改关闭，即软件实体应当在不修改（在<span lang="EN-US">.Net</span>当中可能通过代理模式来达到这个目的）的前提下扩展。<span lang="EN-US"><br>Open for extension:</span>当新需求出现的时候，可以通过扩展现有模型达到目的。<span lang="EN-US">&nbsp;&nbsp;&nbsp; <br>Close for modification:</span>对已有的二进制代码，如<span lang="EN-US">dll,jar</span>等，则不允许做任何修改。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp; <br></span><b style="mso-bidi-font-weight: normal">二、<span lang="EN-US">OCP</span>举例：</b><span lang="EN-US"><br>1</span>、例子一<span lang="EN-US"><br></span>假如我们要写一个工资税类，工资税在不同国家有不同计算规则，如果我们不坚持<span lang="EN-US">OCP</span>，直接写一个类封装工资税的算税方法，而每个国家对工资税的具体实现细节是不尽相同的！如果我们允许修改，即把现在系统需要的所有工资税（中国工资税、美国工资税等）都放在一个类里实现，谁也不能保证未来系统不会被卖到日本，一旦出现新的工资税，而在软件中必须要实现这种工资税，这个时候我们能做的只有找出这个类文件，在每个方法里加上日本税的实现细节并重新编译成<span lang="EN-US">DLL</span>！虽然在<span lang="EN-US">.NET</span>的运行环境中，我们只要将新的<span lang="EN-US">DLL</span>覆盖到原有的<span lang="EN-US">DLL</span>即可，并不影响现有程序的正常运行，但每次出现新情况都要找出类文件，添加新的实现细节，这个类文件不断扩大，以后维护起来就变的越来越困难，也并不满足我们以前说的单一职责原则（<span lang="EN-US">SRP</span>），因为不同国家的工资税变化都会引起对这个类的改变动机！如果我们在设计这个类的时候坚持了<span lang="EN-US">OCP</span>的话，把工资税的公共方法抽象出来做成一个接口，封闭修改，在客户端<span lang="EN-US">(</span>使用该接口的类对象<span lang="EN-US">)</span>只依赖这个接口来实现对自己所需要的工资税，以后如果系统需要增加新的工资税，只要扩展一个具体国家的工资税实现我们先前定义的接口，就可以正常使用，而不必重新修改原有类文件！<span lang="EN-US"><br>&nbsp;<br>2</span>、例子二<span lang="EN-US"><br></span>下面这个例子就是既不开放也不封闭的，因为<span lang="EN-US">Client</span>和<span lang="EN-US">Server</span>都是具体类，如果我要<span lang="EN-US">Client</span>使用不同的一个<span lang="EN-US">Server</span>类那就要修改<span lang="EN-US">Client</span>类中所有使用<span lang="EN-US">Server</span>类的地方为新的<span lang="EN-US">Server</span>类。<span lang="EN-US"><?xml:namespace prefix = o /><o:p></o:p></span></span></p> <p style="line-height: 150%"><span lang="EN-US" style="color: black">class Client<br>{<br>&nbsp;&nbsp; Server server;<br>&nbsp;&nbsp; void GetMessage()<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; server.Message();<br>&nbsp;&nbsp; }<br>}<br>&nbsp;<br>class Server<br>{<br>&nbsp;&nbsp; void Message();<br>}<br>&nbsp;<o:p></o:p></span></p> <p style="line-height: 150%"><span lang="EN-US" style="color: black"><br></span><span style="color: black">下面为修改后符合<span lang="EN-US">OCP</span>原则的实现，我们看到<span lang="EN-US">Server</span>类是从<span lang="EN-US">ClientInterface</span>继承的，不过<span lang="EN-US">ClientInterface</span>却不叫<span lang="EN-US">ServerInterface</span>，原因是我们希望对<span lang="EN-US">Client</span>来说<span lang="EN-US">ClientInterface</span>是固定下来的，变化的只是<span lang="EN-US">Server</span>。这实际上就变成了一种策略模式<span lang="EN-US">(Gof Strategy</span>）<span lang="EN-US"><o:p></o:p></span></span></p> <p style="line-height: 150%"><span lang="EN-US" style="color: black"><br>interface ClientInterface<br>{<br>&nbsp;&nbsp;&nbsp; public void Message();<br>&nbsp;&nbsp;&nbsp; //Other functions<br>}<br>&nbsp;<br>class Server:ClientInterface<br>{<br>&nbsp;&nbsp;&nbsp; public void Message();<br>}<br>&nbsp;<br>class Client <br>{<br>&nbsp;&nbsp; ClientInterface ci;<br>&nbsp;&nbsp; public void GetMessage()<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ci.Message();<br>&nbsp;&nbsp; }<br>&nbsp;&nbsp; public void Client(ClientInterface paramCi)<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ci=paramCi;<br>&nbsp;&nbsp; }<br>}<br>&nbsp;<br>//</span><span style="color: black">那么在主函数<span lang="EN-US">(</span>或主控端<span lang="EN-US">)</span>则<span lang="EN-US"><br>public static void Main()<br>{<br>&nbsp;&nbsp; ClientInterface ci = new Server();<br>&nbsp;&nbsp; //</span>在上面如果有新的<span lang="EN-US">Server</span>类只要替换<span lang="EN-US">Server()</span>就行了．<span lang="EN-US"><br>&nbsp;&nbsp; Client client = new Client(ci);<br>&nbsp;&nbsp; client.GetMessage();<br>}<br>&nbsp;<o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%"><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体">3</span><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体">、例子三<span lang="EN-US"><br></span>使用<span lang="EN-US">Template Method</span>实现<span lang="EN-US">OCP</span>：<span lang="EN-US"><br>public abstract class Policy<br>{<br>&nbsp;&nbsp;&nbsp; private int[] i ={ 1, 1234, 1234, 1234, 132 };<br>&nbsp;&nbsp;&nbsp; public bool Sort()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SortImp();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; protected virtual bool SortImp()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; }<br>}<br>&nbsp;<br>class Bubbleimp : Policy<br>{<br>&nbsp;&nbsp;&nbsp; protected override bool SortImp()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span>冒泡排序<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp; }<br>}<br>class Bintreeimp : Policy<br>{<br>&nbsp;&nbsp;&nbsp; protected override bool SortImp()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span>二分法排序<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp; }<br>}<br>&nbsp;<br>//</span>主函数中实现<span lang="EN-US"><br>static void Main(string[] args)<br>{<br>&nbsp;&nbsp;&nbsp; //</span>如果要使用冒泡排序，只要把下面的<span lang="EN-US">Bintreeimp</span>改为<span lang="EN-US">Bubbleimp<br>&nbsp;&nbsp;&nbsp; Policy sort = new Bintreeimp();<br>&nbsp;&nbsp;&nbsp; sort.Sort();<br>}<br>&nbsp;<br></span><b style="mso-bidi-font-weight: normal">三、<span lang="EN-US">OCP</span>优点：</b><span lang="EN-US"><br>1</span>、降低程序各部分之间的耦合性，使程序模块互换成为可能；<span lang="EN-US"><br>2</span>、使软件各部分便于单元测试，通过编制与接口一致的模拟类（<span lang="EN-US">Mock</span>），可以很容易地实现软件各部分的单元测试；<span lang="EN-US"><br>3</span>、利于实现软件的模块的呼唤，软件升级时可以只部署发生变化的部分，而不会影响其它部分；<span lang="EN-US"><br>&nbsp;<br></span><b style="mso-bidi-font-weight: normal">四、使用<span lang="EN-US">OCP</span>注意点：</b><span lang="EN-US"><br>1</span>、实现<span lang="EN-US">OCP</span>原则的关键是抽象；<span lang="EN-US"><br>2</span>、两种安全的实现开闭原则的设计模式是：<span lang="EN-US">Strategy pattern</span>（策略模式），<span lang="EN-US">Template Methord</span>（模版方法模式）；<span lang="EN-US"><br>3</span>、依据开闭原则<span lang="EN-US">,</span>我们尽量不要修改类<span lang="EN-US">,</span>只扩展类<span lang="EN-US">,</span>但在有些情况下会出现一些比较怪异的状况，这时可以采用几个类进行组合来完成；<span lang="EN-US"><br>4</span>、将可能发生变化的部分封装成一个对象<span lang="EN-US">,</span>如<span lang="EN-US">: </span>状态<span lang="EN-US">, </span>消息<span lang="EN-US">,,</span>算法<span lang="EN-US">,</span>数据结构等等<span lang="EN-US"> , </span>封装变化是实现<span lang="EN-US">"</span>开闭原则<span lang="EN-US">"</span>的一个重要手段，如经常发生变化的状态值<span lang="EN-US">,</span>如温度<span lang="EN-US">,</span>气压<span lang="EN-US">,</span>颜色<span lang="EN-US">,</span>积分<span lang="EN-US">,</span>排名等等<span lang="EN-US">,</span>可以将这些作为独立的属性<span lang="EN-US">,</span>如果参数之间有关系<span lang="EN-US">,</span>有必要进行抽象。对于行为<span lang="EN-US">,</span>如果是基本不变的<span lang="EN-US">,</span>则可以直接作为对象的方法<span lang="EN-US">,</span>否则考虑抽象或者封装这些行为；<span lang="EN-US"><br>5</span>、在许多方面，<span lang="EN-US">OCP</span>是面向对象设计的核心所在。遵循这个原则可带来面向对象技术所声称的巨大好处（灵活性、可重用性以及可维护性）。然而，对于应用程序的每个部分都肆意地进行抽象并不是一个好主意。应该仅仅对程序中呈现出频繁变化的那部分作出抽象。拒绝不成熟的抽象和抽象本身一样重要；<span lang="EN-US"><o:p></o:p></span></span></p><img src ="http://www.cppblog.com/woaidongmao/aggbug/70097.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-12-22 21:27 <a href="http://www.cppblog.com/woaidongmao/archive/2008/12/22/70097.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OOP之五大原则</title><link>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70096.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 22 Dec 2008 13:19:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70096.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/70096.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70096.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/70096.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/70096.html</trackback:ping><description><![CDATA[<p></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-outline-level: 1" align="left"><b><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 18.0pt; mso-bidi-font-family: 宋体">基本原则<span lang="EN-US"> <?xml:namespace prefix = o /><o:p></o:p></span></span></b></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 10pt; line-height: 150%; font-family: symbol; mso-font-kerning: 0pt; mso-bidi-font-family: symbol; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: symbol"><span style="mso-list: ignore">·<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">封装变化<span lang="EN-US">Encapsulate what varies. <o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 10pt; line-height: 150%; font-family: symbol; mso-font-kerning: 0pt; mso-bidi-font-family: symbol; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: symbol"><span style="mso-list: ignore">·<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">面向接口变成而不是实现<span lang="EN-US"> Code to an interface rather than to an implementation. <o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 10pt; line-height: 150%; font-family: symbol; mso-font-kerning: 0pt; mso-bidi-font-family: symbol; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: symbol"><span style="mso-list: ignore">·<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">优先使用组合而非继承 </span><span lang="EN-US" style="font-size: 12pt; color: black; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: arial">Favor Composition Over Inheritance</span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"> <o:p></o:p></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-outline-level: 1" align="left"><b><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 18.0pt; mso-bidi-font-family: 宋体">SRP: The single responsibility principle </span></b><b><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 18.0pt; mso-bidi-font-family: 宋体">单一职责 <span lang="EN-US"><o:p></o:p></span></span></b></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">系统中的每一个对象都应该只有一个单独的职责，而所有对象所关注的就是自身职责的完成。<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">Every object in your system should have a single responsibility ,and all the object s services should<span style="mso-spacerun: yes">&nbsp; </span>be focused on carrying out that single responsibility .<o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l2 level1 lfo2; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">每一个职责都是一个设计的变因，需求变化的时候，需求变化反映为类职责的变化。当你系统里面的对象都只有一个变化的原因的时候，你就已经很好的遵循了<span lang="EN-US">SRP</span>原则。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l2 level1 lfo3; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">如果一个类承担的职责过多，就等于把这些职责耦合在了一起。一个职责的变化就可能削弱或者抑制这个类其它职责的能力。这种设计会导致脆弱的设计。当变化发生的时候，设计会遭到意想不到的破坏。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l2 level1 lfo4; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">SRP </span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">让这个系统更容易管理维护，因为不是所有的问题都搅在一起。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l2 level1 lfo5; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">内聚<span lang="EN-US">Cohesion </span>其实是<span lang="EN-US">SRP</span>原则的另外一个名字<span lang="EN-US">.</span>你写了高内聚的软件其实就是说你很好的应用了<span lang="EN-US">SRP</span>原则。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l2 level1 lfo6; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">怎么判断一个职责是不是一个对象的呢？你试着让这个对象自己来完成这个职责，比如：“书自己阅读内容”，阅读的职责显然不是书自己的。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l2 level1 lfo7; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">6.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">仅当变化发生时，变化的轴线才具有实际的意义，如果没有征兆，那么应用<span lang="EN-US">SRP</span>或者任何其它的原则都是不明智的。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-outline-level: 1" align="left"><b><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 18.0pt; mso-bidi-font-family: 宋体">DRY : Don't repeat yourself Principle <o:p></o:p></span></b></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">通过抽取公共部分放置在一个地方避免代码重复<span lang="EN-US">.<o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">Avoid duplicate code by abstracting out things that are common and placing those thing in a single location .<o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l6 level1 lfo8; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">DRY </span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">很简单，但却是确保我们代码容易维护和复用的关键。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l6 level1 lfo9; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">你尽力避免重复代码候实际上在做一件什么事情呢？是在确保每一个需求和功能在你的系统中只实现一次，否则就存在浪费！系统用例不存在交集，所以我们的代码更不应该重复，从这个角度看<span lang="EN-US">DRY</span>可就不只是在说代码了。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l6 level1 lfo10; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">DRY </span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">关注的是系统内的信息和行为都放在一个单一的，明显的位置。就像你可以猜到正则表达式在<span lang="EN-US">.net</span>中的位置一样，因为合理所以可以猜到。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l6 level1 lfo11; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">DRY </span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">原则：如何对系统职能进行良好的分割！职责清晰的界限一定程度上保证了代码的单一性。<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-outline-level: 1" align="left"><b><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 18.0pt; mso-bidi-font-family: 宋体">OCP : Open-Close Principle</span></b><b><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 18.0pt; mso-bidi-font-family: 宋体">开闭原则<span lang="EN-US"><o:p></o:p></span></span></b></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">类应该对修改关闭，对扩展打开；<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">Classes should be open for extension ,and closed<span style="mso-spacerun: yes">&nbsp; </span>for modification .<o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l5 level1 lfo12; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">OCP </span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">关注的是灵活性，改动是通过增加代码进行的，而不是改动现有的代码； <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l5 level1 lfo13; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">OCP</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">的应用限定在可能会发生的变化上，通过创建抽象来隔离以后发生的同类变化 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l5 level1 lfo14; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">OCP</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">原则传递出来这样一个思想：一旦你写出来了可以工作的代码，就要努力保证这段代码一直可以工作。这可以说是一个底线。稍微提高一点要求<span lang="EN-US">,</span>一旦我们的代码质量到了一个水平，我们要尽最大努力保证代码质量不回退。这样的要求使我们面对一个问题的时候不会使用凑活的方法来解决，或者说是放任自流的方式来解决一个问题；比如代码添加了无数对特定数据的处理，特化的代码越来越多，代码意图开始含混不清，开始退化。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l5 level1 lfo15; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">OCP </span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">背后的机制：封装和抽象；封闭是建立在抽象基础上的，使用抽象获得显示的封闭；继承是<span lang="EN-US">OCP</span>最简单的例子。除了子类化和方法重载我们还有一些更优雅的方法来实现比如组合； <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">怎样在不改变源代码（关闭修改）的情况下更改它的行为呢？答案就是抽象，<span lang="EN-US">OCP</span>背后的机制就是抽象和多态<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l3 level1 lfo16; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">没有一个可以适应所有情况的贴切的模型！一定会有变化，不可能完全封闭<span lang="EN-US">.</span>对程序中的每一个部分都肆意的抽象不是一个好主意，正确的做法是开发人员仅仅对频繁变化的部分做出抽象。拒绝不成熟的抽象和抽象本身一样重要。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l3 level1 lfo17; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">6.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">OCP</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">是<span lang="EN-US">OOD</span>很多说法的核心，如果这个原则有效应用，我们就可以获更强的可维护性可重用 灵活性 健壮性<span lang="EN-US"> LSP</span>是<span lang="EN-US">OCP</span>成为可能的主要原则之一 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-outline-level: 1" align="left"><b><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 18.0pt; mso-bidi-font-family: 宋体">LSP: The Liskov substitution principle <o:p></o:p></span></b></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">子类必须能够替换基类。<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">Subtypes must be substitutable<span style="mso-spacerun: yes">&nbsp; </span>for their base types.<o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l4 level1 lfo18; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">LSP</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">关注的是怎样良好的使用继承<span lang="EN-US">. <o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l4 level1 lfo19; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">必须要清楚是使用一个<span lang="EN-US">Method</span>还是要扩展它，但是绝对不是改变它。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l4 level1 lfo20; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">LSP</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">清晰的指出，<span lang="EN-US">OOD</span>的<span lang="EN-US">IS-A</span>关系是就行为方式而言，行为方式是可以进行合理假设的，是客户程序所依赖的。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l4 level1 lfo21; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">LSP</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">让我们得出一个重要的结论：一个模型如果孤立的看，并不具有真正意义的有效性。模型的有效性只能通过它的客户程序来表现。必须根据设计的使用者做出的合理假设来审视它。而假设是难以预测的，直到设计臭味出现的时候才处理它们。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l4 level1 lfo22; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">对于<span lang="EN-US">LSP</span>的违反也潜在的违反了<span lang="EN-US">OCP <o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-outline-level: 1" align="left"><b><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 18.0pt; mso-bidi-font-family: 宋体">DIP</span></b><b><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 18.0pt; mso-bidi-font-family: 宋体">：依赖倒置原则<span lang="EN-US"><o:p></o:p></span></span></b></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">高层模块不应该依赖于底层模块二者都应该依赖于抽象<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">抽象不应该依赖于细节细节应该依赖于抽象<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l7 level1 lfo23; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">什么是高层模块？高层模块包含了应用程序中重要的策略选择和业务模型。这些高层模块使其所在的应用程序区别于其它。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l7 level1 lfo24; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">如果高层模块依赖于底层模块，那么在不同的上下文中重用高层模块就会变得十分困难。然而，如果高层模块独立于底层模块，那么高层模块就可以非常容易的被重用。该原则就是框架设计的核心原则。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l7 level1 lfo25; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">这里的倒置不仅仅是依赖关系的倒置也是接口所有权的倒置。应用了<span lang="EN-US">DIP</span>我们会发现往往是客户拥有抽象的接口，而服务者从这些抽象接口派生。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l7 level1 lfo26; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">这就是著名的<span lang="EN-US">Hollywood</span>原则<span lang="EN-US">:"Don't call us we'll call you."</span>底层模块实现了在高层模块声明并被高层模块调用的接口。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l7 level1 lfo27; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">通过倒置我们创建了更灵活 更持久更容易改变的结构 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l7 level1 lfo28; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">6.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">DIP</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">的简单的启发规则：依赖于抽象；这是一个简单的陈述，该规则建议不应该依赖于具体的类，也就是说程序汇总所有的依赖都应该种植于抽象类或者接口。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l7 level1 lfo29; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">7.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">如果一个类很稳定，那么依赖于它不会造成伤害。然而我们自己的具体类大多是不稳定的，通过把他们隐藏在抽象接口后面可以隔离不稳定性。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l7 level1 lfo30; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">8.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">依赖倒置可以应用于任何存在一个类向另一个类发送消息的地方 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l7 level1 lfo31; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">9.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">依赖倒置原则是实现许多面向对象技术多宣称的好处的基本底层机制，是面向对象的标志所在。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-outline-level: 1" align="left"><b><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 18.0pt; mso-bidi-font-family: 宋体">ISP:</span></b><b><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 18.0pt; mso-bidi-font-family: 宋体">接口隔离原则<span lang="EN-US"><o:p></o:p></span></span></b></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">不应该强迫客户程序依赖它们不需要的使用的方法。<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l0 level1 lfo32; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">接口不是高内聚的，一个接口可以分成<span lang="EN-US">N</span>组方法，那么这个接口就需要使用<span lang="EN-US">ISP</span>处理一下。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l0 level1 lfo33; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">接口的划分是由使用它的客户程序决定的，客户程序是分离的接口也应该是分离的。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l0 level1 lfo34; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">一个接口中包含太多行为时候，导致它们的客户程序之间产生不正常的依赖关系，我们要做的就是分离接口，实现解耦。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-left: 27pt; vertical-align: middle; text-indent: -18pt; line-height: 150%; text-align: left; mso-pagination: widow-orphan; mso-list: l0 level1 lfo35; tab-stops: list 36.0pt" align="left"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><span style="mso-list: ignore">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">应用了<span lang="EN-US">ISP</span>之后，客户程序看到的是多个内聚的接口。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="line-height: 150%"><span lang="EN-US" style="font-size: 12pt; line-height: 150%; font-family: 宋体"><o:p>&nbsp;</o:p></span></p><img src ="http://www.cppblog.com/woaidongmao/aggbug/70096.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-12-22 21:19 <a href="http://www.cppblog.com/woaidongmao/archive/2008/12/22/70096.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OOP 设计原则之概览</title><link>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70095.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 22 Dec 2008 13:17:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70095.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/70095.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/12/22/70095.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/70095.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/70095.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana">SRP </span></strong><strong><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">单一职责原则</span></strong><b><span lang="EN-US" style="font-size: 11.5pt; color: #006699; font-family: verdana; mso-font-kerning: 18.0pt"><?xml:namespace prefix = o /><o:p></o:p></span></b></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">就一个类而言，应该仅有一个引起它变化的原因。</span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana"></span><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span>&nbsp;</p> <p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana">OCP </span></strong><strong><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">开放</span></strong><strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana">————</span></strong><strong><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">封闭原则</span></strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">软件实体（类、模块、函数等）应该是可以开展的，但是不可修改。</span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana"></span><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span>&nbsp;</p> <p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana">LSP Liskov </span></strong><strong><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">替换原则</span></strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">子类型必须能够替换掉它们的父类型。</span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana"></span><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span>&nbsp;</p> <p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana">DIP </span></strong><strong><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">依赖倒置原则</span></strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">抽象不应该依赖于细节。细节应该依赖于抽象。</span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana"></span><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span>&nbsp;</p> <p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana">ISP </span></strong><strong><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">接口隔离原则</span></strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">不应该强迫客户依赖于它们不用的方法。接口属于客户，不属于它所在的类层次结构</span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana"></span><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span>&nbsp;</p> <p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana">REP </span></strong><strong><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">重用发布等价原则</span></strong><b><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span></b></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">重用的粒度就是发布的粒度</span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana"></span><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span>&nbsp;</p> <p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana">CCP </span></strong><strong><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">共同封闭原则</span></strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">包中的所有类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包产生影响，则将对该包中的所有类产生影响，而对于其它的包不造成任何影响。</span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana"></span><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span>&nbsp;</p> <p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana">CRP </span></strong><strong><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">共同重用原则</span></strong><b><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span></b></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">一个包中的所有类应该是共同重用的。如果重用了包中的一个类，那么就要重用包中的所有类。</span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana"></span><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span>&nbsp;</p> <p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana">ADP </span></strong><strong><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">无环依赖原则</span></strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">在包的依赖关系图中不允许存在环。</span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana"></span><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span>&nbsp;</p> <p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana">SDP </span></strong><strong><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">稳定依赖原则</span></strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">朝着稳定的方向进行依赖</span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana"></span><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span>&nbsp;</p> <p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana">SAP </span></strong><strong><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">稳定抽象原则</span></strong><span lang="EN-US" style="font-size: 13.5pt; color: black; font-family: verdana"><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 13.5pt; color: black; font-family: 宋体; mso-ascii-font-family: verdana; mso-hansi-font-family: verdana">包的抽象程度应该和其稳定程度一致。</span></p><img src ="http://www.cppblog.com/woaidongmao/aggbug/70095.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-12-22 21:17 <a href="http://www.cppblog.com/woaidongmao/archive/2008/12/22/70095.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OOP之里氏代换原则</title><link>http://www.cppblog.com/woaidongmao/archive/2008/12/16/69567.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Tue, 16 Dec 2008 06:24:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/12/16/69567.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/69567.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/12/16/69567.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/69567.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/69567.html</trackback:ping><description><![CDATA[<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　里氏代换原则<span lang=EN-US>(Liskov Substitution Principle LSP)</span>面向对象设计的基本原则之一。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　里氏代换原则中说，任何基类可以出现的地方，子类一定可以出现。<span lang=EN-US> LSP</span>是继承复用的基石，只有当衍生类可以替换掉基类，软件单位的功能不受到影响时，基类才能真正被复用，而衍生类也能够在基类的基础上增加新的行为。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　里氏代换原则是对<span lang=EN-US>&#8220;</span>开<span lang=EN-US>-</span>闭<span lang=EN-US>&#8221;</span>原则的补充。实现<span lang=EN-US>&#8220;</span>开<span lang=EN-US>-</span>闭<span lang=EN-US>&#8221;</span>原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现，所以里氏代换原则是对实现抽象化的具体步骤的规范。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　一般而言，违反里氏代换原则的，也违背<span lang=EN-US>&#8220;</span>开<span lang=EN-US>-</span>闭<span lang=EN-US>&#8221;</span>原则，反过来不一定成立。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>LSP</span>讲的是基类和子类的关系。只有当这种关系存在时，里氏代换关系才存在。如果两个具体的类<span lang=EN-US>A</span>，<span lang=EN-US>B</span>之间的关系违反了<span lang=EN-US>LSP</span>的设计，<span lang=EN-US>(</span>假设是从<span lang=EN-US>B</span>到<span lang=EN-US>A</span>的继承关系<span lang=EN-US>)</span>那么根据具体的情况可以在下面的两种重构方案中选择一种。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>-----</span>创建一个新的抽象类<span lang=EN-US>C</span>，作为两个具体类的超类，将<span lang=EN-US>A</span>，<span lang=EN-US>B</span>的共同行为移动到<span lang=EN-US>C</span>中来解决问题。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>-----</span>从<span lang=EN-US>B</span>到<span lang=EN-US>A</span>的继承关系改为委派关系。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　为了说明，我们先用第一种方法来看一个例子，第二种办法在另外一个原则中说明。我们就看那个著名的长方形和正方形的例子。对于长方形的类，如果它的长宽相等，那么它就是一个正方形，因此，长方形类的对象中有一些正方形的对象。对于一个正方形的类，它的方法有个<span lang=EN-US>setSide</span>和<span lang=EN-US>getSide</span>，它不是长方形的子类，和长方形也不会符合<span lang=EN-US>LSP</span>。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>eg:<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　长方形类：<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>public class Rectangle{<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>...<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>setWidth(int width){<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>this.width=width;<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>}<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>setHeight(int height){<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>this.height=height<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>}<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>}<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　正方形类：<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>public class Square{<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>...<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>setWidth(int width){<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>this.width=width;<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>this. height=width;<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>}<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>setHeight(int height){<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>this.setWidth(height);<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>}<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>}<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　例子中改变边长的函数：<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>public void resize(Rectangle r){<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>while(r.getHeight()&lt;r.getWidth){<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>r.setHeight(r.getWidth+1);<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>}<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　<span lang=EN-US>}<o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　那么，如果让正方形当做是长方形的子类，会出现什么情况呢？我们让正方形从长方形继承，然后在它的内部设置<span lang=EN-US>width</span>等于<span lang=EN-US>height</span>，这样，只要<span lang=EN-US>width</span>或者<span lang=EN-US>height</span>被赋值，那么<span lang=EN-US>width</span>和<span lang=EN-US>height</span>会被同时赋值，这样就保证了正方形类中，<span lang=EN-US>width</span>和<span lang=EN-US>height</span>总是相等的<span lang=EN-US>.</span>现在我们假设有个客户类，其中有个方法，规则是这样的，测试传入的长方形的宽度是否大于高度，如果满足就停止下来，否则就增加宽度的值。现在我们来看，如果传入的是基类长方形，这个运行的很好。根据<span lang=EN-US>LSP</span>，我们把基类替换成它的子类，结果应该也是一样的，但是因为正方形类的<span lang=EN-US>width</span>和<span lang=EN-US>height</span>会同时赋值，这个方法没有结束的时候，条件总是不满足，也就是说，替换成子类后，程序的行为发生了变化，它不满足<span lang=EN-US>LSP</span>。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　那么我们用第一种方案进行重构，我们构造一个抽象的四边形类，把长方形和正方形共同的行为放到这个四边形类里面，让长方形和正方形都是它的子类，问题就<span lang=EN-US>OK</span>了。对于长方形和正方形，取<span lang=EN-US>width</span>和<span lang=EN-US>height</span>是它们共同的行为，但是给<span lang=EN-US>width</span>和<span lang=EN-US>height</span>赋值，两者行为不同，因此，这个抽象的四边形的类只有取值方法，没有赋值方法。上面的例子中那个方法只会适用于不同的子类，<span lang=EN-US>LSP</span>也就不会被破坏。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="LINE-HEIGHT: 150%"><span style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; LETTER-SPACING: 0.4pt; mso-bidi-font-family: arial; mso-font-kerning: 0pt">　　在进行设计的时候，我们尽量从抽象类继承，而不是从具体类继承。如果从继承等级树来看，所有叶子节点应当是具体类，而所有的树枝节点应当是抽象类或者接口。当然这个只是一个一般性的指导原则，使用的时候还要具体情况具体分析。</span><span lang=EN-US style="FONT-SIZE: 12pt; COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-bidi-font-family: arial"><o:p></o:p></span></p>
<img src ="http://www.cppblog.com/woaidongmao/aggbug/69567.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-12-16 14:24 <a href="http://www.cppblog.com/woaidongmao/archive/2008/12/16/69567.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>