自己写文件系统的lsp可以替代系统的吗

OCP中,继承支持了抽象和多态特性.
LSP:子类必须能够替换掉其基类.
反例:使用if/else判断类型,以便选择针对特定类型的正确行为.
有效性并非本质属性
模型的有效性,只能通过它的客户程序来表现.
在考虑一个特定设计是否合理时,必须要根据该设计的使用者所作出的合理假设来审视它.
这些合理的假设常常就是单元测试中的assert.
不要试图做所有的假设,而只是优先预测那些明显的对于LSP原则的违反情况,而在相关的脆弱性臭味出现时,才做其他的预测.
IS-A是关于行为方式的.
对象的行为方式才是软件所关注的.
行为方式是可以进行合理假设的,是客户程序所依赖的.
DBC:基于契约(Contract)设计.
Class的编写者显示地规定针对该类的契约,Client代码的编写者通过契约获取可以依赖的行为方式.
契约通过为方法声明precondition和postcondition来指定.
弱:如果X没有遵守Y的所有约束,那么X就比Y弱.而无视X所遵守的新约束的数目.
断言重新声明规则:在派生类的重载中,只能使用相等或更弱的precondition来替代原始的,同时只能使用相等或者更前的postcondition来替换原始的.
在单元测试中指定契约.
提取公共部分的方法替代继承
对应于情况1,接受一个多态行为中的微妙错误和试着修改设计来完全符合LSP,两者谁更加有利是一个需要权衡(接受缺陷放弃完美)的问题.
总是保证子类可以替代它的基类是一个有效的管理复杂性的方法,一旦放弃了LSP,就必须要单独考虑每个子类.
提取公共部分,最后在代码不是很多的时候应用.如果类Line已经有很多的客户,那么提取出LinearObject是不容易的.
如果一组类都支持一个公共的职责,那么它们应该从一个公共的超类继承该职责.
启发式规则和习惯用法
在派生类中存在退化函数,预示着可能违反了LSP原则.
去除功能的派生类,完成的功能少于其基类的派生类是不能替换其基类的.
在派生类中添加了基类不会抛出的异常.基类的使用者是不会期望这些异常的.
结论. LSP原则中的子类型的可替换性(隐式可以依赖的)能够使得基类型的模块在无需修改时可以进行扩展.
子类型:可替换性的.
使用显示或者隐式的契约来定义可替换性.
[Agile Software Development(Principles,Patterns,and Pracitices)]
阅读(...) 评论()系统架构与软件设计(8)
“一个软件实体如果使用的是一个基类的话,一定适用于其子类,而且根本不能觉察出基类对象和子类对象的区别。”
子类型(Subtype)必须能够替换他们的基类型(Basetype)
Barbara Liskov对原则的陈述:
若对每个类型S的对象o1,都存在一个类型T的对象o2,使得在所有针对T编写的程序P中,用o1替换o2后,程序P的行为功能不变,则S是T的子类型。
通俗地讲,就是子类型能够完全替换父类型,而不会让调用父类型的客户程序从行为上有任何改变。
我们在客户程序在调用某一个类时,实际上是对该类的整个继承体系设定了一套约束,继承体系中的所有类必须遵循这一约束,即前置条件和后置条件必须保持一致。这为对象继承加上了一把严格的枷锁。显然,LSP原则对于约束继承的泛滥具有重要意义。
违反这个职责将导致程序的脆弱性和对OCP的违反
例如:基类Base,派生类Derived,派生类实例d,函数f(Base* p);
f(&d) 会导致错误
&& & & & & & & & &显然D对于f是脆弱的。
如果我们试图编写一些测试,以保证把d传给f时可以使f具有正确的行为。那么这个测试违反了OCP——因为f无法对Base的所有派生类都是封闭的。
经典例子:长方形与正方形驳论
&/pre&&pre&class=&cpp&&name=&code&&class&Rectangle&&{&&private:&&&&&&&long&&&&&&&&long&&&public:&&&&&&void&setWidth(long&width)&&&&&&{&&&&&&&&&&this-&width&=&&&&&&&}&&&&&&long&getWidth()&&&&&&{&&&&&&&&&&return&this-&&&&&&&}&&&&&&void&setHeight(long&height)&&&&&&{&&&&&&&&&&this-&height&=&&&&&&&}&&&&&&long&getHeight()&&&&&&{&&&&&&&&&&return&this-&&&&&&&}&&};&&&&&&class&Square&&{&&private:&&&span&style=&white-space:&&&&&&/span&long&&&&&&&&&public:&&&span&style=&white-space:&&&&&&/span&void&setSide(long&side)&&&&&&{&&&&&&&&&&this-&side&=&&&&&&&}&&&&&&long&getSide()&&&&&&{&&&&&&&&&&return&&&&&&&}&&};&&
&/pre&&pre class=&cpp& name=&code&&class Rectangle
&& &void setWidth(long width)
&& & & &this-&width =
&& &long getWidth()
&& & & &return this-&
&& &void setHeight(long height)
&& & & &this-&height =
&& &long getHeight()
&& & & &return this-&
//正方形类
class Square
&span style=&white-space: && &/span&
&span style=&white-space: && &/span&void setSide(long side)
&& & & &this-&side =
&& &long getSide()
class&Square&:&public&Rectangle&&
{&& private:&& &span&style=&white-space:pre&&&&&&&/span&long&&&
public:&& &span&style=&white-space:pre&&&&&&&/span&void&setWidth(long&width)&&
&&&&{&& &&&&&&&&setSide(width);&& &&&&}&& &&&&long&getWidth()&&
&&&&{&& &&&&&&&&return&getSide();&&
&&&&}&& &&&&void&setHeight(long&height)&&
&&&&{&& &&&&&&&&setSide(height);&& &&&&}&& &&&&long&getHeight()&&
&&&&{&& &&&&&&&&return&getSide();&&
&&&&}&& &&&&long&getSide()&&
&&&&{&& &&&&&&&&return&&&
&&&&}&& &&&&void&setSide(long&side)&&
&&&&{&& &&&&&&&&this-&side&=&&&
&&&&}&& };&&
//正方形类(如果继承自长方形类):
class Square : public Rectangle
&span style=&white-space:pre&& &/span&
&span style=&white-space:pre&& &/span&void setWidth(long width)
&& & & &setSide(width);
&& &long getWidth()
&& & & &return getSide();
&& &void setHeight(long height)
&& & & &setSide(height);
&& &long getHeight()
&& & & &return getSide();
&& &long getSide()
&& &void setSide(long side)
&& & & &this-&side =
class&SmartTest&&
{&& public:&& &&&&void&resize(Rectangle&r)&&
&&&&{&& &&&&while&(r.getHeight()&&=&r.getWidth()&)&&
&&&&&&&&{&& &&&&&&&&r.setWidth(r.getWidth()&+&1);&& &&&&&&&&}&& &&&&}&& };&&
class SmartTest
void resize(Rectangle r)
while (r.getHeight() &= r.getWidth() )
r.setWidth(r.getWidth() + 1);
从上面小函数可见,只想改变长方形的宽时,如果把正方形看成一种长方形的话,则正方形的长和宽都被改变了。LSP原则被破坏了,Square不应成为Rectangle的子类。
里氏代换与通常的数学法则和生活常识有不可混淆的区别。
考虑一个设计是否恰当时,不能孤立的看待并判断,应该从此设计的使用者所作出的假设来审视它!
这个看似明显正确的模型怎么会出错呢?
“正方形是一种长方形”
对不是SmartTest函数的编写者而言,正方形可以是长方形,但是对SmartTest函数的编写者而言,Square绝对不是Rectangle!!
OOD中对象之间是否存在IS-A关系,应该从行为的角度来看待。
-&而行为可以依赖客户程序做出合理的假设。
引入一个Quadrangle(四边形)类,并将Rectangle 与Square变成它的具体子类,解决了Rectangle 与Square的关系不符合里氏替换原则的问题。
class&Quadrangle&&
{&& public:&& &&&&virtual&long&getWidth()&=&0;&&&&&&
&&&&virtual&long&getHeight()&=&0;&&
class Quadrangle
virtual long getWidth() = 0;
virtual long getHeight() = 0;
};&Quadrangle类只声明两个取值方法,不声明任何的赋值方法。
//长方形类:
class&Rectangle&:&public&Quadrangle&&&
{&& private:&&
&&&&long&&& &&&&long&&&
&&&&&& public:&& &&&&void&setWidth(long&width)&&
&&&&{&& &&&&&&&&this-&width&=&&&
&&&&}&& &&&&long&getWidth()&&
&&&&{&& &&&&&&&&return&this-&&&
&&&&}&& &&&&void&setHeight(long&height)&&
&&&&{&& &&&&&&&&this-&height&=&&&
&&&&}&& &&&&long&getHeight()&&
&&&&{&& &&&&&&&&return&this-&&&
&&&&}&& };&&
class Rectangle : public Quadrangle
void setWidth(long width)
this-&width =
long getWidth()
return this-&
void setHeight(long height)
this-&height =
long getHeight()
return this-&
//正方形类:
class&Square&:&public&Quadrangle&&&
{&& private:&&
&&&&long&&& &&&&&& public:&& &&&&void&setSide(long&side)&&
&&&&{&& &&&&&&&&this-&side&=&&&
&&&&}&& &&&&&& &&&&long&getSide()&&
&&&&{&& &&&&&&&&return&&&
&&&&}&& &&&&&& &&&&long&getWidth()&&
&&&&{&& &&&&&&&&return&getSide();&&
&&&&}&& &&&&&& &&&&long&getHeight()&&
&&&&{&& &&&&&&&&return&getSide();&&
&&&&}&& };&&
class Square : public Quadrangle
void setSide(long side)
this-&side =
long getSide()
long getWidth()
return getSide();
long getHeight()
return getSide();
问题如何得以避免?
基类Quadrangle类没有赋值方法,因此类似于 SmartTest的resize()方法不可能适用于Quadrangle类型,而只能适用于不同的具体子类Rectangle 和Square,因此里氏替换原则不可能被破坏。
尽量从抽象类继承,而不从具体类继承。 如果有两个具体类A和B有继承关系,那么一个最简单的修改方案应当是建立一个抽象类C,让类A和B成为抽象类C的子类。 更进一步:&&如果有一个由继承关系形成的等级结构的话,那么在等级结构的树图上面所有的树叶节点都应该是具体类,而所有的树枝节点都应该是抽象类或接口。
相应设计模式:
Strategy Composite Proxy&
参考资源:
《设计模式:可复用面向对象软件的基础》,ERICH
GAMMA RICHARD HELM RALPH JOHNSON JOHN VLISSIDES著作,李英军 马晓星 蔡敏 刘建中译,机械工业出版社,2005.6
《敏捷软件开发:原则、模式与实践》,Robert C. Martin著,邓辉译,清华大学出版社,2003.9
《设计模式解析》,Alan Shalloway等著(徐言声译),人民邮电出版社,2006.10
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:242680次
积分:2795
积分:2795
排名:第13033名
原创:22篇
转载:182篇
评论:13条
(1)(2)(4)(2)(1)(3)(4)(2)(12)(6)(2)(1)(1)(3)(10)(2)(1)(9)(2)(2)(1)(4)(1)(4)(2)(6)(6)(3)(4)(3)(2)(7)(3)(4)(2)(22)(17)(14)(16)(13)}

我要回帖

更多关于 cad lsp怎么写 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信