软件设计应遵循的原则
作者:网络转载 发布时间:[ 2013/5/27 13:39:02 ] 推荐标签:
但是现在每当计价策略发生改变,我们必须修改Part 的每个子类!
一个更好的思路是采用一个PricePolicy类,通过对其进行继承以提供不同的计价策略,那麽这里是在运用设计模式里面的策略模式了,解决起来算是很完美了:
public class Part {
private PricePolicy pricePolicy;
public void setPricePolicy(PricePolicy policy) {
pricePolicy = policy;
}
public void setPrice(double price) {
pricePolicy.setPrice(price);
}
public double getPrice() {
return pricePolicy.getPrice();
}
}
public class PricePolicy {
private double basePrice;
public void setPrice(double price) {
basePrice = price;
}
public double getPrice() {
return basePrice;
}
}
public class SalePrice extends PricePolicy {
private double discount;
public void setDiscount(double discount) {
this.discount = discount;
}
public double getPrice() {
return basePrice*discount;
}
}
看起来我们所做的是将问题推迟到另一个类中,将“变化”封装在PricePolicy类里面。但是使用该解决方案,我们可通过改变Part对象,在运行期间动态地来设定计价的策略。另一个解决方案是使每个ConcretePart从数据库或属性文件中获取其当前的价格,这样相当于把“变化”封装在了属性文件里面了。
三、里氏代换原则(LSP)
(1) 由Barbar Liskov(芭芭拉.里氏)提出,是继承复用的基石。
(2) 严格表达:如果每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都代换称o2时,程序P的行为没有变化,那么类型T2是类型T1的子类型.
换言之,一个软件实体如果使用的是一个基类的话,那么一定适用于其子类,而且它根本不能察觉出基类对象和子类对象的区别.只有衍生类可以替换基类,软件单位的功能才能不受影响,基类才能真正被复用,而衍生类也能够在基类的基础上增加新功能。
(3) 反过来的代换不成立
(4) <墨子.小取>中说:"白马,马也; 乘白马,乘马也.骊马(黑马),马也;乘骊马,乘马也."
(5) 该类西方的例程为:正方形是否是长方形的子类(答案是"否")。类似的还有椭圆和圆的关系。
(6) 应当尽量从抽象类继承,而不从具体类继承,一般而言,如果有两个具体类A,B有继承关系,那么一个简单的修改方案是建立一个抽象类C,然后让类A和B成为抽象类C的子类.即如果有一个由继承关系形成的登记结构的话,那么在等级结构的树形图上面所有的树叶节点都应当是具体类;而所有的树枝节点都应当是抽象类或者接口.
(7) "基于契约设计(Design By Constract),简称DBC"这项技术对LISKOV代换原则提供了支持.该项技术Bertrand Meyer伯特兰做过详细的介绍:
使用DBC,类的编写者显式地规定针对该类的契约.客户代码的编写者可以通过该契约获悉可以依赖的行为方式.契约是通过每个方法声明的前置条件(preconditions)和后置条件(postconditions)来指定的.要使一个方法得以执行,前置条件必须为真.执行完毕后,该方法要保证后置条件为真.是说,在重新声明派生类中的例程(routine)时,只能使用相等或者更弱的前置条件来替换原始的前置条件,只能使用相等或者更强的后置条件来替换原始的后置条件.
一个软件实体如果使用的是一个基类的话那么一定适用于其子类,而且它察觉不出基类对象和子类对象的区别。也是说,在软件里面,把基类都替换成它的子类,程序的行为没有变化。
LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。
下面,我们从代码重构的角度来对LSP进行理解。LSP讲的是基类和子类的关系。只有当这种关系存在时,里氏代换关系才存在。如果两个具体的类A,B之间的关系违反了LSP的设计,(假设是从B到A的继承关系)那么根据具体的情况可以在下面的两种重构方案中选择一种。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11