﻿<?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 Tools-随笔分类-文档</title><link>http://www.blogjava.net/simie/category/23727.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 03 Jul 2007 01:27:21 GMT</lastBuildDate><pubDate>Tue, 03 Jul 2007 01:27:21 GMT</pubDate><ttl>60</ttl><item><title>软件需求说明书（需求设计说明文档）（</title><link>http://www.blogjava.net/simie/archive/2007/07/02/127528.html</link><dc:creator>和田雨</dc:creator><author>和田雨</author><pubDate>Mon, 02 Jul 2007 05:13:00 GMT</pubDate><guid>http://www.blogjava.net/simie/archive/2007/07/02/127528.html</guid><wfw:comment>http://www.blogjava.net/simie/comments/127528.html</wfw:comment><comments>http://www.blogjava.net/simie/archive/2007/07/02/127528.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/simie/comments/commentRss/127528.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/simie/services/trackbacks/127528.html</trackback:ping><description><![CDATA[<div>软件需求说明书 <br>1． 引言 <br>1.1 项目名称 <br>1.2 项目背景和内容概要 <br>（项目的委托单位、开发单位、主管部门、与其它项目的关系，与其他机构的关系等） <br><br>1.3 相关资料、缩略语、定义 <br>（相关项目计划、合同及上级机关批文，引用的文件、采用的标准等） <br>（缩写词和名词定义） <br>2. 任务概述 <br>2.1 目标 <br>（项目的开发目标和应用目标。如果是其他系统的一部分，则说明其关系） <br>2.2 范围 <br>（包含的业务，不包含的业务） <br>2.3 假定条件与约束限制 <br>（尽量列出开展本项目的假定和约束，例如：经费限制，开发期限，设备条件，用户现 <br>场环境准备等） <br>3．业务流程 <br>4．数据描述 <br>4.1 原始数据描述 <br>a. 静态数据 <br>b. 动态数据 <br>4.2 数据流向图 <br>4.3 数据概念模型和描述 <br>5．功能需求 <br>5.1 功能描述 <br>6．界面要求 <br>6．1报表格式 <br>6．2图形要求 <br>6．3输入输出要求 <br>7．接口要求 <br>(描述与本系统相连的系统的接口的数据格式，数据交换协议，接口功能等) <br>8．性能需求 <br>8．1数据精确度 <br>（例如，数据内部精度，外部显示精度） <br>8． 2数据量 <br>8． 3时间特性要求 <br>（根据所开发系统的特点，规定系统对时间的特性的要求。例如： <br>系统响应时间、界面更新处理时间、数据转换与传输时间） <br>9． 运行环境需求 <br>9．1网络和硬件设备平台 <br>（网络拓扑图及设备类型描述） <br>操作系统平台 <br>数据库系统平台 <br>10.1编程工具 <br>10.2其它支撑软件 <br>11． 其它专门需求 <br>11.1安装和操作 <br>11.2安全保密 <br>11.3维护服务 <br></div>
<img src ="http://www.blogjava.net/simie/aggbug/127528.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/simie/" target="_blank">和田雨</a> 2007-07-02 13:13 <a href="http://www.blogjava.net/simie/archive/2007/07/02/127528.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>面向对象的设计法则（转载）</title><link>http://www.blogjava.net/simie/archive/2007/07/02/127527.html</link><dc:creator>和田雨</dc:creator><author>和田雨</author><pubDate>Mon, 02 Jul 2007 05:11:00 GMT</pubDate><guid>http://www.blogjava.net/simie/archive/2007/07/02/127527.html</guid><wfw:comment>http://www.blogjava.net/simie/comments/127527.html</wfw:comment><comments>http://www.blogjava.net/simie/archive/2007/07/02/127527.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/simie/comments/commentRss/127527.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/simie/services/trackbacks/127527.html</trackback:ping><description><![CDATA[<h2>法则1：优先使用（对象）组合，而非（类）继承<br><br>[ Favor Composition Over Inheritance ]<br><br></h2>
<br>
<ul><br>
    <li><br>
    <h3><strong>组合</strong><br><br></h3>
    <br>
    <blockquote><br>
    <p>1.（对象）组合是一种通过创建一个组合了其它对象的对象，从而获得新功能的复用方法。<br><br>2.将功能委托给所组合的一个对象，从而获得新功能。<br><br>3.有些时候也称之为"聚合"（aggregation）或"包容"（containment），尽管有些作者对这些术语赋予了专门的含义<br><br>4.例如：<br><br>a.<strong>聚合</strong>：一个对象拥有另一个对象或对另一个对象负责（即一个对象包含另一个对象或是另一个对象的一部分），并且聚合对象和其所有者具有相同的生命周期。（译者注：即所谓的"同生共死"关系，可参见GOF的Design <br>Patterns: Elements of Reusable Object-Oriented Software的引言部分。）<br><br>b.<strong>包容</strong>：一种特殊类型的组合，对于其它对象而言，容器中的被包含对象是不可见的，其它对象仅能通过容器对象来访问被包含对象。（Coad）</p>
    <br></blockquote><br><br>
    <blockquote><br>
    <p>5.包含可以通过以下两种方式实现：<br><br>a.根据引用（By reference）<br><br>b.根据值（By value）<br><br>6.C＋＋允许根据值或引用来实现包含。<br><br>7.但是在Java中，一切皆为对象的引用！<br><br></p>
    <br></blockquote><br>
    <li><br>
    <h3>组合的优点和缺点 </h3>
    <br><br></li>
</ul>
<br>
<ul><br>
    <blockquote><br>
    <p><strong>1.优点：</strong><br><br>a.容器类仅能通过被包含对象的接口来对其进行访问。<br><br>b."黑盒"复用，因为被包含对象的内部细节对外是不可见。<br><br>c.对装性好。<br><br>d.实现上的相互依赖性比较小。（译者注：被包含对象与容器对象之间的依赖关系比较少）<br><br>e.每一个类只专注于一项任务。<br><br>f.通过获取指向其它的具有相同类型的对象引用，可以在运行期间动态地定义（对象的）组合。</p>
    <br></blockquote><br>
    <blockquote><br>
    <p><strong>2.缺点：</strong><br><br>a.从而导致系统中的对象过多。<br><br>b为了能将多个不同的对象作为组合块（composition block）来使用，必须仔细地对接口进行定义。<br><br></p>
    <br></blockquote><br>
    <li><br>
    <h3>继承</h3>
    <br>
    <blockquote><br>
    <p><br><br>1.（类）继承是一种通过扩展一个已有对象的实现，从而获得新功能的复用方法。<br><br>2.泛化类（超类）可以显式地捕获那些公共的属性和方法。<br><br>3.特殊类（子类）则通过附加属性和方法来进行实现的扩展。<br><br></p>
    <br></blockquote><br><br>
    <li><br>
    <h3>继承的优点和缺点</h3>
    <br>
    <blockquote><br>
    <p><br><br><strong>1.优点：</strong><br><br>a.容易进行新的实现，因为其大多数可继承而来。<br><br>b.易于修改或扩展那些被复用的实现。<br><br><strong>2.缺点：</strong><br><br>a.破坏了封装性，因为这会将父类的实现细节暴露给子类。<br><br>b. "白盒"复用，因为父类的内部细节对于子类而言通常是可见的。<br><br>c.当父类的实现更改时，子类也不得不会随之更改。<br><br>d.从父类继承来的实现将不能在运行期间进行改变。<br><br></p>
    <br></blockquote><br><br>
    <li><br>
    <h3>Coad规则</h3>
    <br>
    <blockquote><br>
    <p><br><br>仅当下列的所有标准被满足时，方可使用继承：<br><br>a.子类表达了"是一个&#8230;的特殊类型"，而非"是一个由&#8230;所扮演的角色"。<br><br>b子类的一个实例永远不需要转化（transmute）为其它类的一个对象。<br><br>c.子类是对其父类的职责（responsibility）进行扩展，而非重写或废除（nullify）。<br><br>d.子类没有对那些仅作为一个工具类（utility class）的功能进行扩展。<br><br>e.对于一个位于实际的问题域（Problem Domain）的类而言，其子类特指一种角色（role），交易（transaction）或设备（device）。<br><br></p>
    <br></blockquote><br><br>
    <li><br>
    <h3>继承/组合示例1</h3>
    <br><br></li>
</ul>
<br>
<p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_1.gif"></p>
<br>
<blockquote><br>
<blockquote><br>
<p>1."是一个&#8230;的特殊类型"，而非"是一个由&#8230;所扮演的角色"<br><br>--&gt;失败。乘客是人所扮演的一种角色。代理人亦然。<br><br>2.永远不需要转化<br><br>--&gt;失败。随着时间的发展，一个Person的子类实例可能会从Passenger转变成Agent，再到Agent Passenger。<br><br>3.扩展，而非重写和废除<br><br>--&gt;通过。<br><br>4.不要扩展一个工具类<br><br>--&gt;通过。<br><br>5.在问题域内，特指一种角色，交易或设备<br><br>--&gt;失败。Person不是一种角色，交易或设备。</p>
<br></blockquote><br></blockquote><br>
<p align=center><br><br><font color=#ff0000>继承并非适用于此处！</font></p>
<br>
<p align=center><font color=#ff0000>使用组合进行挽救！<br><br></font></p>
<br>
<p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_2.gif"></p>
<br>
<ul><br>
    <li><br>
    <h3>继承/组合示例2</h3>
    <br><br></li>
</ul>
<br>
<p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_3.gif"></p>
<br>
<blockquote><br>
<blockquote><br>
<p>1."是一个&#8230;的特殊类型"，而非"是一个由&#8230;所扮演的角色"<br><br>--&gt;通过。乘客和代理人都是特殊类型的人所扮演的角色。<br><br>2.永远不需要转化<br><br>--&gt;通过。一个Passenger对象将保持不变；Agent对象亦然。<br><br>3.扩展，而非重写和废除<br><br>--&gt;通过。<br><br>4.不要扩展一个工具类<br><br>--&gt;通过。<br><br>5.在问题域内，特指一种角色，交易或设备<br><br>--&gt;通过。PersonRole是一种类型的角色。<br><br></p>
<br></blockquote><br></blockquote><br>
<p align=center><font color=#ff0000>继承适用于此处！</font><br><br></p>
<br>
<ul><br>
    <li><br>
    <h3 align=left>继承/组合示例3</h3>
    <br><br></li>
</ul>
<br>
<p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_4.gif"></p>
<br>
<blockquote><br>
<blockquote><br>
<p>1."是一个&#8230;的特殊类型"，而非"是一个由&#8230;所扮演的角色"<br><br>--&gt;通过。预订和购买都是一种特殊类型的交易。<br><br>2.永远不需要转化<br><br>--&gt;通过。一个Reservation对象将保持不变；Purchase对象亦然。<br><br>3.扩展，而非重写和废除<br><br>--&gt;通过。<br><br>4.不要扩展一个工具类<br><br>--&gt;通过。<br><br>5.在问题域内，特指一种角色，交易或设备<br><br>--&gt;通过。是一种交易。<br><br></p>
<br></blockquote><br></blockquote><br>
<p align=center><font color=#ff0000>继承适用于此处！</font><br><br></p>
<br>
<ul><br>
    <li><br>
    <h3 align=left>继承/组合示例4</h3>
    <br><br></li>
</ul>
<br>
<p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_5.gif"></p>
<br>
<blockquote><br>
<blockquote><br>
<p>1."是一个&#8230;的特殊类型"，而非"是一个由&#8230;所扮演的角色"<br><br>--&gt;失败。预订不是一种特殊类型的observable。<br><br>2.永远不需要转化<br><br>--&gt;通过。一个Reservation对象将保持不变。<br><br>3.扩展，而非重写和废除<br><br>--&gt;通过。<br><br>4.不要扩展一个工具类<br><br>--&gt;失败。Observable就是一个工具类。<br><br>5.在问题域内，特指一种角色，交易或设备<br><br>--&gt;不适用。Observable是一个工具类，并非一个问题域的类。。<br><br></p>
<br></blockquote><br></blockquote><br>
<p align=center><font color=#ff0000>继承并非适用于此处！</font><br><br></p>
<br>
<ul><br>
    <li><br>
    <h3 align=left>继承/组合总结</h3>
    <br>
    <blockquote><br>
    <p><br><br>1.组合与继承都是重要的重用方法<br><br>2.在OO开发的早期，继承被过度地使用<br><br>3.随着时间的发展，我们发现优先使用组合可以获得重用性与简单性更佳的设计<br><br>4.当然可以通过继承，以扩充（enlarge）可用的组合类集（the set of composable classes）。<br><br>5.因此组合与继承可以一起工作<br><br>6.但是我们的基本法则是：<br><br><strong>优先使用对象组合，而非（类）继承<br><br>[ Favor Composition Over Inheritance ]<br><br></p>
    <h2>法则2：针对接口编程，而非（接口的）实现<br><br>[ Program To An Interface, Not An Implementation ]<br><br></h2>
    <p><br><br></p>
    <ul><br>
        <li><br>
        <h3>接口</h3>
        <br>
        <blockquote><br>
        <p>1.接口是一个对象在对其它的对象进行调用时所知道的方法集合。<br><br>2.一个对象可以有多个接口（实际上，接口是对象所有方法的一个子集）<br><br>3.类型是对象的一个特定的接口。<br><br>4.不同的对象可以具有相同的类型，而且一个对象可以具有多个不同的类型。<br><br>5.一个对象仅能通过其接口才会被其它对象所了解。<br><br>6.某种意义上，接口是以一种非常局限的方式，将"是一种&#8230;"表达为"一种支持该接口的&#8230;"。<br><br>7.接口是实现插件化（pluggability）的关键<br><br></p>
        <br></blockquote><br><br>
        <li><br>
        <h3>实现继承和接口继承<br><br></h3>
        <br>
        <blockquote><br>
        <p>1.实现继承（类继承）：一个对象的实现是根据另一个对象的实现来定义的。<br><br>2.接口继承（子类型化）：描述了一个对象可在什么时候被用来替代另一个对象。<br><br>3.C++的继承机制既指类继承，又指接口继承。<br><br>4.C++通过继承纯虚类来实现接口继承。<br><br>5.Java对接口继承具有单独的语言构造方式－Java接口。<br><br>6.Java接口构造方式更加易于表达和实现那些专注于对象接口的设计。<br><br></p>
        <br></blockquote><br><br>
        <li><br>
        <h3>接口的好处<br><br></h3>
        <br>
        <blockquote><br>
        <p><strong>1.优点</strong>：<br><br>a.Client不必知道其使用对象的具体所属类。<br><br>b.一个对象可以很容易地被（实现了相同接口的）的另一个对象所替换。<br><br>c.对象间的连接不必硬绑定（hardwire）到一个具体类的对象上，因此增加了灵活性。<br><br>e.松散藕合（loosens coupling）。<br><br>f.增加了重用的可能性。<br><br>e.提高了（对象）组合的机率，因为被包含对象可以是任何实现了一个指定接口的类。<br><br><strong>2.缺点：</strong><br><br>a.设计的复杂性略有增加<br><br>（译者注：接口表示"&#8230;像&#8230;"（LikeA）的关系，继承表示"&#8230;是&#8230;"（IsA）的关系，组合表示"&#8230;有&#8230;"（HasA）的关系。）</p>
        <br></blockquote><br><br>
        <li><br>
        <h3>接口实例</h3>
        <br><br></li>
    </ul>
    <p><br></p>
    <p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_6.gif"></p>
    <p><br></p>
    <p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_7.gif"></p>
    <p><br></p>
    <blockquote><br>
    <blockquote><br>
    <p>该方法是指其它的一些类可以进行交通工具的驾驶，而不必关心其实际上是（汽车，轮船，潜艇或是其它任何实现了IManeuverabre的对象）。 </p>
    <br>
    <h2>法则3：开放－封闭法则（OCP）<br><br>软件组成实体应该是可扩展的，但是不可修改的。<br><br>[ Software Entities Should Be Open For Extension, Yet Closed For Modification <br>]<br><br></h2>
    <br>
    <ul><br>
        <li><br>
        <h3>开放－封闭法则</h3>
        <br>
        <blockquote><br>
        <p><br><br>1.开放-封闭法则认为我们应该试图去设计出永远也不需要改变的模块。<br><br>2我们可以添加新代码来扩展系统的行为。我们不能对已有的代码进行修改。<br><br>3.符合OCP的模块需满足两个标准：<br><br>4.可扩展，即"对扩展是开放的"（Open For Extension）－模块的行为可以被扩展，以需要满足新的需求。<br><br>5.不可更改，即"对更改是封闭的"（Closed for Modification）－模块的源代码是不允许进行改动的。<br><br>6.我们能如何去做呢？<br><br>a.抽象（Abstraction）<br><br>b.多态（Polymorphism）<br><br>c.继承（Inheritance）<br><br>d.接口（Interface）</p>
        <br>
        <p>7. 一个软件系统的所有模块不可能都满足OCP，但是我们应该努力最小化这些不满足OCP的模块数量。<br><br>8.开放－封闭法则是OO设计的真正核心。<br><br>9.符合该法则便意味着最高等级的复用性（reusability）和可维护性（maintainability）。<br><br></p>
        <br></blockquote><br><br>
        <li><br>
        <h3>OCP示例<br><br></h3>
        <br>
        <blockquote><br>
        <p>1. 考虑下面某类的方法：</p>
        <br>
        <p align=center><br><br><img src="http://www.360doc.com/DownloadImg/10587/268694_8.gif"> </p>
        <br>
        <p>2.以上函数的工作是在制订的部件数组中计算各个部件价格的总和。<br><br>3.若Part是一个基类或接口且使用了多态，则该类可很容易地来适应新类型的部件，而不必对其进行修改。<br><br>4.其将符合OCP</p>
        <br>
        <p>5. 但是在计算总价格时，若财务部颁布主板和内存应使用额外费用，则将如何去做。<br><br>6.下列的代码是如何来做的呢？</p>
        <br>
        <p align=center><br><br><img src="http://www.360doc.com/DownloadImg/10587/268694_9.gif"> </p>
        <br>
        <p>7.这符合OCP吗？<br><br>8.当每次财务部提出新的计价策略，我们都不得不要修改totalPrice()方法！这并非"对更改是封闭的"。显然，策略的变更便意味着我们不得不要在一些地方修改代码的，因此我们该如何去做呢？<br><br>9.为了使用我们第一个版本的totalPrice()，我们可以将计价策略合并到Part的getPrice()方法中。</p>
        <br>
        <p>10.这里是Part和ConcretePart类的示例：<br><br></p>
        <br>
        <p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_10.gif"> </p>
        <br>
        <p>11. 但是现在每当计价策略发生改变，我们就必须修改Part的每个子类！<br><br>12.一个更好的思路是采用一个PricePolicy类，通过对其进行继承以提供不同的计价策略：<br><br></p>
        <br>
        <p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_11.gif"></p>
        <br>
        <p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_12.gif"></p>
        <br>
        <p>13.看起来我们所做的就是将问题推迟到另一个类中。但是使用该解决方案，我们可通过改变Part对象，在运行期间动态地来设定计价的策略。<br><br>14.另一个解决方案是使每个ConcretePart从数据库或属性文件中获取其当前的价格。<br><br></p>
        <br></blockquote><br><br>
        <li><br>
        <h3>单选法则<br><br></h3>
        <br>
        <blockquote><br>
        <p>单选法则（the Single Choice Principle）是OCP的一个推论。<br><br>无论在什么时候，一个软件系统必须支持一组备选项，理想情况下，在系统中只能有一个类能够知道整个的备选项集合。<br><br></p>
        <br>
        <h2>法则4：Liskov替换法则（LSP）<br><br>使用指向基类（超类）的引用的函数，必须能够在不知道具体派生类（子类）对象类型的情况下使用它们。<br><br>[ Function Thar Use Referennces To Base(Super) Classes Must Be Able To Use Objects <br>Of Derived(Sub) Classes Without Knowing It ]<br><br></h2>
        <br>
        <ul><br>
            <li><br>
            <h3>Liskov替换法则</h3>
            <br>
            <blockquote><br>
            <p><br><br>1.显而易见，Liskov替换法则（LSP）是根据我所熟知的"多态"而得出的。<br><br>2.例如：<br><br><br><br>方法drawShape应该可与Sharp超类的任何子类一起工作（或者，若Sharp为Java接口，则该方法可与任何实现了Sharp接口的类一起工作）<br><br>但是当我们在实现子类时必须要谨慎对待，以确保我们不会无意中违背了LSP。</p>
            <br></blockquote><br><br>
            <blockquote><br>
            <p>3.若一个函数未能满足LSP，那么可能是因为它显式地引用了超类的一些或所有子类。这样的函数也违背了OCP，因为当我们创建一个新的子类时，会不得不进行代码的修改。<br><br></p>
            <br></blockquote><br>
            <li><br>
            <h3>LSP示例<br><br></h3>
            <br>
            <blockquote><br>
            <p>1. 考虑下面Rectangle类：<br><br></p>
            <br>
            <p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_13.gif"> </p>
            <br>
            <p>2.现在，Square类会如何呢？显然，一个正方形是一个四边形，因此Square类应该从Rectangle类派生而来，对否？让我们看一看！<br><br>3.观察可得：<br><br>a.正方形不需要将高和宽都作为属性，但是总之它将继承自Rectangle。因此，每一个Square对象会浪费一点内存，但这并不是一个主要问题。<br><br>b.继承而来的setWidth()和setHeight()方法对于Square而言并非真正地适合，因为一个正方形的高和宽是相同。因此我们将需要重写setWidth()和setHeight()方法。不得不重写这些简单的方法有可能是一种不恰当的继承使用方式。</p>
            <br>
            <p>3.Square类如下：</p>
            <br></blockquote><br><br></li>
        </ul>
        <br>
        <p align=center><br><br><img src="http://www.360doc.com/DownloadImg/10587/268694_14.gif"> </p>
        <br>
        <blockquote><br>
        <blockquote><br>
        <p>4. 看起来都还不错。但是让我们检验一下！</p>
        <br></blockquote><br></blockquote><br>
        <p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_15.gif"> </p>
        <br>
        <p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_16.gif"></p>
        <br>
        <blockquote><br>
        <blockquote><br>
        <p>5. 测试程序输出： </p>
        <br></blockquote><br></blockquote><br>
        <p align=center><img src="http://www.360doc.com/DownloadImg/10587/268694_17.gif"></p>
        <br>
        <blockquote><br>
        <blockquote><br>
        <p>6.看上去好像我们违背了LSP！</p>
        <br>
        <p>7.这里的问题出在哪里呢？编写testLsp()方法的程序员做了一个合理的假设，即改变Rectangle的宽而保持它的高不变。<br><br>8.在将一个Square对象传递给这样一个方法时产生了问题，显然是违背了LSP<br><br>9.Square和Rectangle类是相互一致和合法的。尽管程序员对基类作了合理的假设，但其所编写的方法仍然会导致设计模型的失败。<br><br>10.不能孤立地去看待解决方案，必须根据设计用户所做的合理假设来看待它们。</p>
        <br>
        <p>11. 一个数学意义上的正方形可能是一个四边形，但是一个Square对象不是一个Rectangle对象，因为一个Square对象的行为与一个Rectangle对象的行为是不一致的！<br><br>12.从行为上来说，一个Square不是一个Rectangle！一个Square对象与一个Rectangle对象之间不具有多态的特征。<br><br></p>
        <br></blockquote><br></blockquote><br>
        <ul><br>
            <li><br>
            <h3>总结</h3>
            <br>
            <blockquote><br>
            <p><br><br>1.Liskov替换法则（LSP）清楚地表明了ISA关系全部都是与行为有关的。<br><br>2.为了保持LSP（并与开放－封闭法则一起），所有子类必须符合使用基类的client所期望的行为。<br><br>3.一个子类型不得具有比基类型（base type）更多的限制，可能这对于基类型来说是合法的，但是可能会因为违背子类型的其中一个额外限制，从而违背了LSP！<br><br>4.LSP保证一个子类总是能够被用在其基类可以出现的地方！<br></p>
            </blockquote></li>
        </ul>
        </blockquote></li>
    </ul>
    </blockquote></blockquote></strong></blockquote></li>
</ul>
<img src ="http://www.blogjava.net/simie/aggbug/127527.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/simie/" target="_blank">和田雨</a> 2007-07-02 13:11 <a href="http://www.blogjava.net/simie/archive/2007/07/02/127527.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>