设计模式学习--面向对象的5条设计原则之开放封闭原则--OCP

一、OCP简介(OCP--Open-Closed Principle):
Software entities(classes,modules,functions,etc.) should be open for extension, but closed for modification。
软件实体应当对扩展开放,对修改关闭,即软件实体应当在不修改(在.Net当中可能通过代理模式来达到这个目的)的前提下扩展。
Open for extension:当新需求出现的时候,可以通过扩展现有模型达到目的。
Close for modification:对已有的二进制代码,如dll,jar等,则不允许做任何修改。

二、OCP举例:
1、例子一
假如我们要写一个工资税类,工资税在不同国家有不同计算规则,如果我们不坚持OCP,直接写一个类封装工资税的算税方法,而每个国家对工资税的具体实现细节是不尽相同的!如果我们允许修改,即把现在系统需要的所有工资税(中国工资税、美国工资税等)都放在一个类里实现,谁也不能保证未来系统不会被卖到日本,一旦出现新的工资税,而在软件中必须要实现这种工资税,这个时候我们能做的只有找出这个类文件,在每个方法里加上日本税的实现细节并重新编译成DLL!虽然在.NET的运行环境中,我们只要将新的DLL覆盖到原有的DLL即可,并不影响现有程序的正常运行,但每次出现新情况都要找出类文件,添加新的实现细节,这个类文件不断扩大,以后维护起来就变的越来越困难,也并不满足我们以前说的单一职责原则(SRP),因为不同国家的工资税变化都会引起对这个类的改变动机!如果我们在设计这个类的时候坚持了OCP的话,把工资税的公共方法抽象出来做成一个接口,封闭修改,在客户端(使用该接口的类对象)只依赖这个接口来实现对自己所需要的工资税,以后如果系统需要增加新的工资税,只要扩展一个具体国家的工资税实现我们先前定义的接口,就可以正常使用,而不必重新修改原有类文件!

2、例子二
下面这个例子就是既不开放也不封闭的,因为Client和Server都是具体类,如果我要Client使用不同的一个Server类那就要修改Client类中所有使用Server类的地方为新的Server类。
class Client
{
Server server;
void GetMessage()
{
server.Message();
}
}

class Server
{
void Message();
}

下面为修改后符合OCP原则的实现,我们看到Server类是从ClientInterface继承的,不过ClientInterface却不叫ServerInterface,原因是我们希望对Client来说ClientInterface是固定下来的,变化的只是Server。这实际上就变成了一种策略模式(Gof Strategy)
interface ClientInterface
{
public void Message();
//Other functions
}

class Server:ClientInterface
{
public void Message();
}

class Client
{
ClientInterface ci;
public void GetMessage()
{
ci.Message();
}
public void Client(ClientInterface paramCi)
{
ci=paramCi;
}
}

//那么在主函数(或主控端)则
public static void Main()
{
ClientInterface ci = new Server();
//在上面如果有新的Server类只要替换Server()就行了.
Client client = new Client(ci);
client.GetMessage();
}

3、例子三
使用Template Method实现OCP:
public abstract class Policy
{
private int[] i ={ 1, 1234, 1234, 1234, 132 };
public bool Sort()
{
SortImp();
}
protected virtual bool SortImp()
{

}
}

class Bubbleimp : Policy
{
protected override bool SortImp()
{
//冒泡排序
}
}
class Bintreeimp : Policy
{
protected override bool SortImp()
{
//二分法排序
}
}

//主函数中实现
static void Main(string[] args)
{
//如果要使用冒泡排序,只要把下面的Bintreeimp改为Bubbleimp
Policy sort = new Bintreeimp();
sort.Sort();
}

三、OCP优点:
1、降低程序各部分之间的耦合性,使程序模块互换成为可能;
2、使软件各部分便于单元测试,通过编制与接口一致的模拟类(Mock),可以很容易地实现软件各部分的单元测试;
3、利于实现软件的模块的呼唤,软件升级时可以只部署发生变化的部分,而不会影响其它部分;

四、使用OCP注意点:
1、实现OCP原则的关键是抽象;
2、两种安全的实现开闭原则的设计模式是:Strategy pattern(策略模式),Template Methord(模版方法模式);
3、依据开闭原则,我们尽量不要修改类,只扩展类,但在有些情况下会出现一些比较怪异的状况,这时可以采用几个类进行组合来完成;
4、将可能发生变化的部分封装成一个对象,如: 状态, 消息,,算法,数据结构等等 , 封装变化是实现"开闭原则"的一个重要手段,如经常发生变化的状态值,如温度,气压,颜色,积分,排名等等,可以将这些作为独立的属性,如果参数之间有关系,有必要进行抽象。对于行为,如果是基本不变的,则可以直接作为对象的方法,否则考虑抽象或者封装这些行为;
5、在许多方面,OCP是面向对象设计的核心所在。遵循这个原则可带来面向对象技术所声称的巨大好处(灵活性、可重用性以及可维护性)。然而,对于应用程序的每个部分都肆意地进行抽象并不是一个好主意。应该仅仅对程序中呈现出频繁变化的那部分作出抽象。拒绝不成熟的抽象和抽象本身一样重要;

 

时间: 2024-10-22 05:11:45

设计模式学习--面向对象的5条设计原则之开放封闭原则--OCP的相关文章

设计模式学习--面向对象的5条设计原则(转)

这几天重新看了一遍<大话设计模式>,发现果然有不同的感悟,而且自己也上网找了<敏捷软件开发-原则.模式与实践>一书来看,那本书的序言中有一段话我觉得很有道理:"美的东西比丑的东西创建起来更廉价,也更快捷."设计一个软件不关要追求代码的优雅问题,更关乎生产成本等.技术大师们在对软件架构的研究中经历了很长时间的摸索,从面向过程到面向对象,从设计原则到设计模式,总结了许多设计上的经典法则,而我们就只是站在巨人的肩膀上眺望远方而已. 从<大话设计模式>中,大

设计模式学习--面向对象的5条设计原则之单一职责原则--SRP

  一.SRP简介(SRP--Single-Responsibility Principle): 就一个类而言,应该只专注于做一件事和仅有一个引起它变化的原因.   所谓职责,我们可以理解他为功能,就是设计的这个类功能应该只有一个,而不是两个或更多.也可以理解为引用变化的原因,当你发现有两个变化会要求我们修改这个类,那么你就要考虑撤分这个类了.因为职责是变化的一个轴线,当需求变化时,该变化会反映类的职责的变化. "就像一个人身兼数职,而这些事情相互关联不大,,甚至有冲突,那他就无法很好的解决这些

设计模式学习--面向对象的5条设计原则之接口隔离原则--ISP

一.ISP简介(ISP--Interface Segregation Principle): 使用多个专门的接口比使用单一的总接口要好.一个类对另外一个类的依赖性应当是建立在最小的接口上的.一个接口代表一个角色,不应当将不同的角色都交给一个接口.没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染.   "不应该强迫客户依赖于它们不用的方法.接口属于客户,不属于它所在的类层次结构."这个说得很明白了,再通俗点说,不要强迫客户使用它们不用的方法,如果强迫用户使用它们不使

设计模式六大原则——开放封闭原则(OCP)

      什么是开闭原则?       定义:是说软件实体(类.模块.函数等等)应该可以扩展,但是不可修改.       开闭原则主要体现在两个方面:       1.对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况.     2.对修改封闭,意味着类一旦设计完成,就可以独立其工作,而不要对类尽任何修改.         怎么使用开闭原则?     实现开放封闭的核心思想就是对抽象编程,而不对具体编程,因为抽象相对稳定.让类依赖于固定的抽象,所以对修改就是封闭的:而

《你必须知道的.net》读书笔记 007——2.3 开放封闭原则

       开放封闭原则,核心思想:软件实体应该是可扩展,而不可修改的.也就是说,对扩展是开放的,而对修改是封闭的.            体现在两个方面:      1.对扩展开放,意味着有新的需求和变化时,可以对现有代码进行扩展,以适应新的情况.      2.对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改.   ==        辛辛苦苦写好的代码,测试也通过了,就不要再改了嘛,一改动就可能发生错误,或者是不希望的修改,至少还需要在测试一遍吧.如果改一处

开放-封闭 原则

开放-封闭原则:软件实体(类,模块,函数等等)应该可以扩展,但是不可修改   为适应不断变更的新需求,就及早的想办法应对发生更大改变的可能.最初编写代码时,假设变化不会发生.当变化发生时,我们就创建抽象来隔离以后发生的同类变化.比如:之前的加法程序,很快在一个client类中就能完成(http://www.cnblogs.com/zhangdongsheng/archive/2012/03/25/2417224.html).此时变化还没有发生,如果我们再加一个减法功能,你发现,增加功能需要修改这

设计模式原则(单一、开放封闭、里氏代换、依赖倒转、迪米特法则五大原则)

原文:设计模式原则(单一.开放封闭.里氏代换.依赖倒转.迪米特法则五大原则) 单一职责原则 单一职责原则,就一个类而言,应该仅有一个引起它变化的原因.   如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力,当变化发生时,设计会遭受到意想不到的破坏.事实上,我们完全可以找出来进行分类,分离.   软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离.其实要去判断是否应该分离出类来,也不难,那就是如果你能够想到多余一个的动机去改变

设计模式学习总结

       之前一直是面向过程编程,前段时间因为某些原因需要更好的去理解一下面向对象思想精髓,在别人的推荐下看了<大话设计模式>这本书.通过对29个模式的学习,不仅仅了解了设计模式是个什么回事,也稍微加深了一点对面向对象(Object-oriented)技术.面向对象技术关注的是对象,对象的优点在于,可以定义自己负责的事物,作要求它自己的事情.对象应该自己负责自己,而且应该清楚地定义责任.它具有三大特征:封装.多态.继承.        封装(Encapsulation),也就是把客观事物封

iOS应用开发应遵循的10条设计原则

大家知道,苹果App Store的应用审查十分严格,可以说近乎吹毛求疵.如何才能确保自己的应用通过苹果的审查,顺利在App Store上架?以下是BI为广大开发者总结出来的10条设计原则: 1)操控便捷 iOS应用的控制设计应该具有圆润的轮廓和程式化的梯度,操作便捷. 2)结构清晰.导航方便 充分利用iOS导航栏.尽量将所有的导航都安排在一个分层格式中,方便显示应用内的当前位置. 3)微妙清晰的用户反馈 使用动画显示用户的操作结果.一个经典的例子是:当用户长按进入"重新排列模式"时,应