﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-JAVA~~~i love you-随笔分类-面向对象思想</title><link>http://www.blogjava.net/ayato/category/13710.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 12:19:41 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 12:19:41 GMT</pubDate><ttl>60</ttl><item><title>面向对象设计之LSP</title><link>http://www.blogjava.net/ayato/archive/2006/08/03/61427.html</link><dc:creator>it民工</dc:creator><author>it民工</author><pubDate>Wed, 02 Aug 2006 16:28:00 GMT</pubDate><guid>http://www.blogjava.net/ayato/archive/2006/08/03/61427.html</guid><wfw:comment>http://www.blogjava.net/ayato/comments/61427.html</wfw:comment><comments>http://www.blogjava.net/ayato/archive/2006/08/03/61427.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/ayato/comments/commentRss/61427.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ayato/services/trackbacks/61427.html</trackback:ping><description><![CDATA[
		<p>      前段时间完成我的毕业论文，是关于面向对象设计原则和设计模式的一些讨论，为此重读了Robert C.Martin的《Aglile Software Development Principles，Patterns and Pratices》这本著作，对面向对象设计有了一个新的认识，在这里和大家分享一下。<br />      《Agile》一书中提到一系列的面向对象设计原则，其中一条是叫作LSP---Liskov替换原则。LSP是Barbara Liskov在她1988年的论文中提出的，其内容是：子类必须能够完全替换掉它的父类。LSP是使OCP成立的条件之一（关于OCP在以后的文章会作讨论），二者都是面向对象的多态和抽象的基础。<br />      举个例子，当我们有一个Car这个类</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000"> Car {<br />    <br />    </span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000"> run(){<br />        System.out.println(</span>
				<span style="COLOR: #000000">"</span>
				<span style="COLOR: #000000">I am running</span>
				<span style="COLOR: #000000">"</span>
				<span style="COLOR: #000000">);<br />    }<br />    <br />    </span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000"> stop(){<br />        System.out.println(</span>
				<span style="COLOR: #000000">"</span>
				<span style="COLOR: #000000">I am stop</span>
				<span style="COLOR: #000000">"</span>
				<span style="COLOR: #000000">);<br />    }<br />}</span>
		</div>
		<br />现在，如果有一个类与Car类有关系，在面向对象中，类之间的关系就是组合和继承。当确定这个类为另外一个类的使用者、拥有者时就用组合，譬如Person类使用Car类。使用者的类有一个特征就是运行时多态放在它们之间是不管用的，譬如Person可能有一些eat、laugh等公共方法，如果Person是Car的子类，根据运行时多态就可以用Car来替换Person，Car就有得eat这个方法，显然是不合逻辑的。<br />    如果确定是有一种特殊的Car会飞的，除了run和stop之外还有一个fly的方法，现在就是使用继承的场合。<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> FlyingCar </span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000"> Car {<br /><br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> fly(){<br />        System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">I am Fly</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />    }<br />}</span></div><br />虽然使用了继承，但是确违反了LSP。因为Car中并没有fly这个方法，运行时多态便被破坏。为了获得多态性，将Car重构为抽象类，在其中添加一个抽象的fly方法，多态性便得以保存。但是这样做的话就说明所有Car的抽象都是会fly的，这显然是不合理。为此，应该去掉Car中的fly方法，Car就不是抽象类，再由Car这个抽象类派生出抽象的FlyingCar，里面包含fly的抽象方法。这样，FlyingCar抽象类和它的派生类就确保遵守了LSP了。<br />      还有一种做法，将fly方法抽象到一个Flyable接口中。FlyingCar在继承Car的同时实现Flyable接口，就是说，FlyingCar的上级父类就是Car和Flyable，按照LSP是完全可以覆盖父类的。<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">interface</span><span style="COLOR: #000000"> Flyable {<br /><br />    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> fly();<br />}</span></div><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> FlyingCar </span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000"> Car </span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000"> Flyable {<br /><br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> fly(){<br />        System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">I am fly</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />    }<br />}</span></div><br />使用运行时多态时要获得fly方法必须转型为Flyable接口<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> CarMain {<br /><br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> main(String[] args) {<br />        Car car</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> FlyingCar();<br />        car.run();<br />        car.stop();<br />        ((Flyable)car).fly();<br />    }<br />}</span></div><br />LSP是指导使用继承的准则。继承肯定是子类添加父类所不具有的新方法的，此时若忽略LSP，多态性便会在设计中消失。所以当使用继承时，为了保证多态性，就需要遵守LSP多做一些工作了。<img src ="http://www.blogjava.net/ayato/aggbug/61427.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ayato/" target="_blank">it民工</a> 2006-08-03 00:28 <a href="http://www.blogjava.net/ayato/archive/2006/08/03/61427.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>