微信

使用微信服务,更方便

职友集>程序员面试题 > 什么是开闭原则?如何实现开闭原则

什么是开闭原则?如何实现开闭原则

2015-04-13 06:30:01 阅读( 137 )

2181人 收藏本页

标签:程序员面试题

开闭原则的解释就是:软件实体应当对扩展开放,对修改关闭,也就是:软件系统中包含的各种组件,例如模块(Modules)、类(Classes)以及功能(Functions)等等,应该在不修改现有代码的基础上,引入新功能。开闭原则中“开”,是指对于组件功能的扩展是开放的,是允许对其进行功能扩展的;开闭原则中“闭”,是指对于原有代码的修改是封闭的,即不应该修改原有的代码。

开闭原则是说我们应该努力设计不需要修改的模块。在扩展系统的行为时,我们只需要添加新的代码,而不需要修改已有的代码。一般可以通过添加新的子类和重写父类的方法来实现。

满足开闭原则的模块需要符合如面两个标准:

对扩展开放 ——- 模块的行为可以被扩展从而满足新的需求。
对修改关闭 ——- 不需要修改模块的源代码。(或者尽量使修改最小化)
怎样实现开闭原则

抽象
多态
继承
接口
要想使一个软件系统的所有模块都满足开闭原则是不太现实的,不过我们应该努力使大部分模块满足开闭原则。开闭原则是面向对象设计的核心,满足该原则可以达到最大限度的复用和可维护性。

实例

考虑下面某个类的方法:

Java代码

public double totalPrice(Part[] parts) {
double total = 0.0;
for (int i=0; i<parts.length; i++) {
total += parts.getPrice();
}
return total;
}
上面函数的功能是计算给定的零件数组中所有零件价格的总和,如果Part是一个基类或者接口,那我们就可以利用多态的特性,当有新的零件被添加进来时不需要修改该函数的代码。这样它就可以满足开闭原则。

但是如果我们的会计部门规定当计算主板和内存的价格时,需要添加一些额外的费用,请看下面的代码:

Java代码

public double totalPrice(Part[] parts) {
double total = 0.0;
for (int i=0; i<parts.length; i++) {
if (parts instanceof Motherboard)
total += (1.45 * parts.getPrice());
else if (parts instanceof Memory)
total += (1.27 * parts.getPrice());
else
total += parts.getPrice();
}
return total;
}
现在它还符合开闭原则吗?不!每次会计部门发布一个新的价格政策时,我们都需要修改totalPrice()方法!它对修改不是关闭的,显然,价格政策的改变意味着我们必须修改某处的代码,那么我们应该怎么做呢?为了使用我们第一个版本的totalPrice()方法,我们需要把Part的 getPrice()方法的价格政策包含进来。

下面是Part和ConcretePrat类:

Java代码

// Class Part is the superclass for all parts.
public class Part {
private double price;
public Part(double price) (this.price = price;}
public void setPrice(double price) {this.price = price;}
public double getPrice() {return price;}
}
// Class ConcretePart implements a part for sale.
// Pricing policy explicit here!
public class ConcretePart extends Part {
public double getPrice() {
// return (1.45 * price); //Premium
return (0.90 * price); //Labor Day Sale
}
}
但是,现在如果价格政策改变,我们必须修改Part的子类,一个更好的方法是建立一个PricePolicy类,它可以为我们提供不同的价格政策:

Java代码

/**
* Class PricePolicy implements a given price policy.
*/
public class PricePolicy {
private double factor;
public PricePolicy (double factor) {
this.factor = factor;
}
public double getPrice(double price) {return price * factor;}
}
使用这种方法,我们可以在运行时动态的设置Part对象所引用的PricePoilcy对象,在实际的程序中,零件的价格和相关的PricePolicy可以从数据库中获取。

总结

像许多其他原则一样,开闭原则只是面向对象设计的一个原则,实现一个灵活的设计需要额外的时间和努力,引入新的抽象层会增加代码的复杂性。因此,该原则适用于那些需求会经常发生变化的系统。有许多设计模式可以帮助我们扩展功能而不需要修改代码。例如,装饰模式等。


来自IT公司面试手册

下一篇:程序员面试题整理 欢迎指导

上一篇:美国英网软件公司题目

亲~ 如果您有更好的答案 可在评论区发表您独到的见解。

您想查看更多的信息: 面试题