漫谈面向对象基石之开闭原则(OCP)(转)
原帖地址: http://www.cnblogs.com/yukaizhao/archive/2010/06/29/ood-ocp.html
开闭原则的意思是软件实体应该对扩展开发,对修改关闭(Software entities should be open for extension,but closed for modification)。实现开闭原则的途径是抽象,将需要扩展的部分抽象出来,并留出扩展接口。打个比方,比如电脑机箱上有usb的插口,这些插口就是可扩展的部分,我们可以在这些usb插口上插上鼠标,键盘,U盘,还可以插上网银的U盾等等。电脑硬件上对于usb接口的这个设计就是一个符合开闭原则的设计。
为什么要遵循开闭原则呢?因为开闭原则可以使软件系统更容易复用,更容易维护,当某个软件实体,不适合了,我可以重新做另外一种实现,并将现有的实现替换掉。比如说统计个税的算法发生了一些变化,我可以在不改变原有代码的情况下,重新实现一个算法将原有的算法替换下来。比如说杀毒软件,在出现一种新的病毒时,开发出一个查杀这种病毒的新模块,可以只开发更新这个查杀模块,而不需要改变原有系统的内容。
开闭原则这么好,如何实现符合开闭原则的软件系统呢?答案是抽象,将可能发生变化的功能点进行抽象,并留出变化的接口。设计模式中很多模式都可以帮我们实现开闭原则,个人的理解设计模式是对抽象用法的一种总结。其实我们在项目已经为开闭原则做了一些工作了,比如说我们进行三层开发,将数据层抽象出来,并定义个数据处理的接口,我们可以通过新开发一个数据层把刚开始将数据存放到sql server中的实现,修改为将数据存放到my sql中的实现;我们将业务逻辑中的代码从UI代码中分离出来,这就为我们复用业务逻辑的代码提供了可能,我们可以开发一个专门为手机使用的UI层出来,当用户用手机访问我们的系统时,智能的切换到手机UI层的代码上去执行。
实现开闭原则的例子,其实我都不好意思自己举例子了,因为我正在使用office 2007写这篇博客,在Office2007的快捷工具栏中就有一项是加载项,就是说Office 2007能将插件加载进来使用,如下图所示:
Snagit在word中添加了一个插件,这种插件技术就是一种遵循OCP的实现;再说我们整天使用的Visual Studio 它的可扩展程度更高,可以开发很多类型的工具对他进行扩展。
为了本文的完整性,我还是厚着脸皮,用重构的方式举一个遵循开闭原则的微不足道的实现。
下面的举例实现的场景是个税的计算:我的第一个版本是这样子的
01
|
class Program
|
02
|
{
|
03
|
static void Main( string [] args)
|
04
|
{
|
05
|
float salary = 10000;
|
06
|
07
|
Console.WriteLine( "收入是{0}的人应缴个税是{1}," ,salary, GetTax(salary));
|
08
|
}
|
09
|
10
|
static float GetTax( float salary)
|
11
|
{
|
12
|
return ( float )(salary * 0.03);
|
13
|
}
|
14
|
}
|
这个版本中我未做任何抽象,直接调用静态方法算了,可是一不小心开两会了,个税要调整了,于是个税的算法要进行调整了,怎么办呢,因为要少缴税,我很高兴的就要来重构上面的代码了,既然个税的计算方法是一个变化的东西,我就把它抽象出来吧。
01
|
class Program
|
02
|
{
|
03
|
static void Main( string [] args)
|
04
|
{
|
05
|
float salary = 10000;
|
06
|
07
|
Console.WriteLine( "收入是{0}的人应缴个税是{1}," ,salary, GetTax(salary));
|
08
|
}
|
09
|
10
|
static float GetTax( float salary)
|
11
|
{
|
12
|
ITaxCalculateStrategy strategy = GetTaxCalculateStrategy();
|
13
|
return strategy.GetTax(salary);
|
14
|
}
|
15
|
16
|
/// <summary>
|
17
|
/// 获得应该使用的个税计算方法
|
18
|
/// </summary>
|
19
|
/// <returns>个税计算方法实现实例</returns>
|
20
|
static ITaxCalculateStrategy GetTaxCalculateStrategy() {
|
21
|
string typeName = ConfigurationManager.AppSettings[ "TaxCalculateStrategyType" ];
|
22
|
if ( string .IsNullOrEmpty(typeName))
|
23
|
throw new ConfigurationErrorsException( "请配置TaxCalculateStrategyType" );
|
24
|
25
|
Type type = Type.GetType(typeName);
|
26
|
if (type == null ) throw new ConfigurationErrorsException( "TaxCalculateStrategyType错误" );
|
27
|
28
|
return (ITaxCalculateStrategy)Activator.CreateInstance(type);
|
29
|
}
|
30
|
}
|
31
|
32
|
/// <summary>
|
33
|
/// 定义个税计算的接口
|
34
|
/// </summary>
|
35
|
public interface ITaxCalculateStrategy
|
36
|
{
|
37
|
float GetTax( float salary);
|
38
|
}
|
39
|
40
|
/// <summary>
|
41
|
/// 两会前个税计算办法的实现
|
42
|
/// </summary>
|
43
|
public class TaxCalculateBefore2Conference : ITaxCalculateStrategy
|
44
|
{
|
45
|
float ITaxCalculateStrategy.GetTax( float salary)
|
46
|
{
|
47
|
return ( float )(salary * 0.03);
|
48
|
}
|
49
|
}
|
50
|
51
|
/// <summary>
|
52
|
/// 两会后个税的计算方法
|
53
|
/// </summary>
|
54
|
public class TaxCalculateAfter2Conference:ITaxCalculateStrategy
|
55
|
{
|
56
|
float ITaxCalculateStrategy.GetTax( float salary)
|
57
|
{
|
58
|
return ( float )(salary * 0.020);
|
59
|
}
|
60
|
}
|
因为要少缴税,所以我很愉快的重构了之前的代码,可以转眼两会开完了,结果并非如我预期的个税变化,咋办呢?没关系我们重新开发一个个税计算方法,修改下配置就可以仍旧使用之前的个税计算办法了。
开闭原则实现的关键点在于抽象,也许我们刚开始不知道该把那部分抽象出来,但是这并不是问题,我们可以遵循简单设计的原则,当变化来了的时候,再重构代码,做到一种满足开闭原则的设计。
切忌到处都抽象,如果到处都抽象就会导致系统过度设计,过度复杂。这反而是不利于系统的维护。完全的开闭原则是不可能实现的,所以请保持简单设计,在需要的时候做符合开闭原则的设计。
漫谈面向对象基石之开闭原则(OCP)(转)相关推荐
- 设计原则:开闭原则(OCP)
1.什么是开闭原则 开闭原则的英文是Open Closed Principle,缩写就是OCP.其定义如下: 软件实体(模块.类.方法等)应该"对扩展开放.对修改关闭". 从定义上 ...
- 深入理解JavaScript系列(7):S.O.L.I.D五大原则之开闭原则OCP
前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第2篇,开闭原则OCP(The Open/Closed Principle ). 开闭原则的描述是: Software ...
- 设计一个扩展自抽象类geometricobject的新的triangle类_面向对象设计原则之开放封闭原则(开闭原则OCP)...
(1) 定义 一个软件实体(类.模块.函数等),对于扩展是开放的,对于更改是封闭的. 对于扩展是开放的:这意味着模块的行为是可以扩展的.当应用的需求发生改变时,我们可以对模块进行扩展,比如增加新的类或 ...
- 设计原则(一)开-闭原则(OCP)
经典力学的基石是牛顿三大定律.而面向对象的可复用设计的第一块基石,便是所谓的"开-闭"原则(Open-Closed Principle,常缩写为OCP). 一.什么是开闭原则 &q ...
- 设计模式-开闭原则(OCP)
开闭原则(open closed principle) 目标:已有的场景下,对于需要拓展的进行开放,拒绝直接的功能修改 需求: 吃鸡游戏要高亮 + LOL需要弹出折扣 // sprint1 - 青年节 ...
- JavaScript 开闭原则OCP
代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3. ...
- 面向对象设计原则——开闭原则
第一次听说开闭原则的时候,感觉很高大尚很深奥,真正了解之后,发现,原来是这个意思 开闭原则OCP(Open Closed Principle):对扩展开放,对修改关闭 开闭原则对软件测试来说,只需要测 ...
- [设计原则] 六大设计原则之“开闭原则”
[设计原则] 六大设计原则之"开闭原则" 目录 [设计原则] 六大设计原则之"开闭原则" 什么是开闭原则 为什么使用开闭原则 如何使用开闭原则 注意事项 总结 ...
- 面向对象设计原则:开闭原则(OCP)
最常见的解释:开闭原则中的"开",是指对于组件功能的扩展是开放的,是允许对其进行功能扩展的:开闭原则中的"闭",是指对于原有代码的修改是封闭的,即不应该修改原有 ...
最新文章
- 随机森林(Random Forest)和梯度提升树(GBDT)有什么区别?
- kafka0.9 java commit_0.9版本kafka优化及常见错误(转载)
- table row设置cell的html,css中display设置为table、table-row、table-cell后的作用及其注意点...
- PHPStrom的快捷键突然失效解决方案
- java B2B2C Springboot电子商城系统
- TypeScript里的Index signature
- css3 多列布局使用
- AnalyticDB for MySQL技术架构解析
- initPlayer初始化过程(一)
- 如何用结构型信号量实现互斥和同步
- 多态和C++多态的实现(汇总)
- Dokcer从理论到实践----------Docker原理
- 计算机web前端岗位职责,web前端开发工程师岗位的职责
- 有了5G手机和套餐,如何正确使用5G网络?
- Carsim安装中遇到的一些坑(invalid license key)
- WLC RTU license
- php中trim 的作用,PHP trim()函数的作用和使用方法
- 无线网能连接上但无法连接服务器是啥原因,腾达无线路由器能连接但是上不了网怎么办...
- maven项目查询jar依赖的网址
- html dom反选,Dom操作--全选反选
热门文章
- HAOI2014 走出金字塔
- 读书笔记:线上性能问题初步排查方法
- 还是来说class,什么鬼,类会生宝宝
- 调整linux的时钟
- 让ASP程序在服务器中自动运行
- pku 2954 Triangle pku 1265 Area Pick定理的应用 + 叉积求多边形面积
- 【ASP.NET Core】处理异常(上篇)
- xhtmlrenderer 将html转换成pdf,完美css,带图片,手动分页,解决内容断开的问题
- org.mybatis.spring.MyBatisSystemException异常及处理
- 如何获取Node.js目录中存在的所有文件的名称列表?