面向对象设计领域的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是面向对象设计的核心所在。遵循这个原则可带来面向对象技术所声称 的巨大好处(灵活性、可重用性以及可维护性)。然而,对于应用程序的每个部分都肆意地进行抽象并不是一个好主意。应该仅仅对程序中呈现出频繁变化的那部分 作出抽象。拒绝不成熟的抽象和抽象本身一样重要;
转载于:https://blog.51cto.com/samqiu2014/1533147
相关文章:

Python教学课程分享9-面向对象编程
面向对象程序设计的思想主要是针对大型软件设计而提出的,它的一个关键性观念是将数据以及对数据的操作封装在一起,组成一个相互依存、不可分割的整体,即不同对象之间通过消息机制来通信或者同步。对于相同类型对象进行分类、抽象后࿰…

UE capability与 双连接相关的参数。
UE capability 分为 Network capability 和 Radio capability, 即网络能力和无线能力。 Netowrk Capability UE 在做Attach Request 时会主动上报自己的网络能力;Radio Capability 网络侧下发Enquiry Capability来请求UE无线能力,UE 回复capability inf…

Linux下Tomcat的安装配置
Linux下Tomcat的安装配置 一.下载安装对应的jdk,并配置Java环境。 官网下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk-6u26-download-400750.html 下载将jdk加压后放到/usr/local目录下: [rootmaster ~]#chmod 755 jdk-6u5-li…

python登录代码思路_用python登录Dr.com思路以及代码分享
用python登录Dr.com思路以及代码分享发布于 2014-08-28 22:31:52 | 192 次阅读 | 评论: 0 | 来源: 网友投递Python编程语言Python 是一种面向对象、解释型计算机程序设计语言,由Guido van Rossum于1989年底发明,第一个公开发行版发行于1991年。Python语法…

postgresql开发中可能有用的知识
2019独角兽企业重金招聘Python工程师标准>>> postgresql手册 一、PostgreSQL中可以直接对时间进行加减运算: 查询系统当前时间: select now();或者select current_timestamp;SELECT now()::timestamp 1 year; --当前时间加1年SELECT now():…

css实现 textarea 高度自适应
此textarea非彼textarea ,有经验的老司机们应该知道html标签contenteditable这个属性。 利用此属性使当前的标签成为可以输入的状态,等同于输入框。 演示地址:https://xibushijie.github.io/static/textareaHeihgAuto.html <!DOCTYPE html…

LTE PUCCH Format1
PUCCH 格式 1/1a/1b 是向eNodeB传递1或2或4位数据。 这个过程相当复杂,我们用如下3个章节来描述: PUCCH Format 1,1a,1b 所在RB位置PUCCH F1信号的生成PUCCH 多UE 复用 PUCCH Format 1,1a,1b 所在RB位置 LTE中有很多课题(尤其是物理层),如…

innodb force recovery
innodb force recovery的6种设置: 1.innodb force recovery1,即使发现了损坏页面也继续让服务器继续运行,这个选项对于备份或者转存当前数据尤为有用2.innodb force recovery2,阻止恢复主线程的运行,如果清除操作会导致…

随机森林 java_机器学习weka,java api调用随机森林及保存模型
工作需要,了解了一下weka的java api,主要是随机森林这一块,刚开始学习,记录下。了解不多,直接上demo,里面有一些注释说明:package weka;import java.io.File;import weka.classifiers.Classifie…

[转载]64位linux安装WPS
2019独角兽企业重金招聘Python工程师标准>>> 网上下载了最新的WPS*.deb 安装后发现运行不了。(点Unity > WP搜出来的图标) 还以为安装有问题。于是重装了几次。还是不成功。 然后打开终端 wps 原来是程序出错了 提示找不到/opt…

mybatis报错There is no getter for property named '***' in 'class ***'
mybatis报错There is no getter for property named *** in class ***, 检查一看是xml中映射字段拼写错误,大小写。 有的时候用插件生成了原始的代码没问题,增加了一个字段在没有再自动生成的时候, 喜欢自己手动加一部分进去&…

LTE - PUCCH Format2
LTE中有很多课题(尤其是物理层),如果不仔细阅读规范中给出的每个参数和方程,是无法解释清楚的。物理资源分配就是其中之一。 PUCCH格式2/2a/2b的物理资源分配由以下过程确定。看到这些公式千万不要惊慌,方程本身就是高中数学的一部分…
数据绑定(Binding)
Windows Presentation Foundation (WPF) 中的数据绑定为应用程序提供了一种简单、一致的数据表示和交互方法。元素能够以公共语言运行时 (CLR) 对象和 XML 形式绑定到来自各种数据源的数据。 什么是数据绑定? 数据绑定是在应用程序 UI 与业务逻辑之间建立连接的过程…
java exception源码_Java异常之 Error 和 Exception
简单了解 Java 异常1、实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求;你的程序要打开某个文件,这个文件可能不存在或者文件格式不对;你要读取数据库的数据&am…

面向对象解决了全局变量问题?
2019独角兽企业重金招聘Python工程师标准>>> 全局变量的应用场景 程序中的某些资源之多能有一个,比如计数器、配置信息、程序运行状态等,而且许多地方需要访问他,那么这个资源就应该,也只能设置成全局变量。在稍微大点…
物理层UL基本流程
物理层发端的基本流程在36.211/36.212(NR:38.211/38.212)中有详细的描述,现在归纳如下。下面列出的每个步骤对于某些信道而言可能会增加其它步骤,也可能有些步骤不需要。 CRC 相关 信道编码(channel coding) LTE: NR: 加扰-Scrambling 加扰过程是da…

java 建树源码_Java实现的二叉树常用操作【前序建树,前中后递归非递归遍历及层序遍历】...
import java.util.ArrayDeque;import java.util.Queue;import java.util.Stack;//二叉树的建树,前中后 递归非递归遍历 层序遍历//Node节点class Node {int element;Node left;Node right;public Node() {}public Node(int element) {this.element element;}}// Bi…

html5小趣味知识点系列(一)autofocus
<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>autofocus</title> </head> <body><input type"text" autofocus value"页面中只能有一个哦"><!-- 如…

cisco aaa 授权后门测试
最近遇到一个客户aaa没有正确的配置,导致自己被关在设备外面的case;由于是生产环境的多交换机堆叠单元,重启忽略配置也是不允许的,且必须远程操作解决,无疑提升了解决问题的难度。多次尝试后发现通过cisco acs上的一些…

hive的基本命令
创建表 CREATE TABLE pokes (foo INT, bar STRING); 创建表并创建索引字段ds CREATE TABLE invites (foo INT, bar STRING) PARTITIONED BY (ds STRING); 显示所有表 SHOW TABLES; 按正条件(正则表达式)显示表, SHOW TABLES .*s; 表添加一列…
MMSE(Minimum Mean Square Error)
MMSE是一种最小化接收数据的MSE(均方误差)的模型。关于这句话,你的脑海里就会出现很多问题: 什么是均方误差? “最小化MSE”的物理意义是什么? 让我们从一个我们现在非常熟悉的信道模型开始. MMSE作为一种均衡器,是一种后处理算法,它帮助…

java控制台两个字符串_java控制台输入字符串
实验要求: 1/7 1.掌握 JDK 的安装及参数配置方法,能在控制台界面使用 Java 命令进行 Java 程序的编译及运行。 2.掌握 Eclipse 软件安装方法。3.掌握在 ......习题1. 数据类型转换应用【案例简介】下例说明了整型、浮点型、字符串型之间的相互转换。 【案例目的】掌握 Java 中两…

lua单链表实现
List {}--创建一个节点function List.new(val)return {pnext nil, value val}end--往一个节点后添加一个节点function List.addNode(nodeParent, nodeChild)nodeChild.pnext nodeParent.pnextnodeParent.pnext nodeChildreturn nodeChildend--输出链表function List.print…

Java语言的基础知识9
第十一章(线程)1、通过String nameThread.currentThread().getName();来获取当前线程的名称。2、多次启动一个线程或者启动一个已经运行的线程是非法的,会抛出IllegalThreadStateException异常对象。Thread.sleep((int)Math.random()*10000);3、java提供了Runnable接口使继承了…

Android Parcelable的介绍与使用
Parcelable使用的一个地方就是在进程间传递一个自定义的较为复杂的对象,对Parcelable学习了一下写下自己的观点。 将一个对象比如说一个名字为Cartoon的自定义类,由一个activity传递到另外一个activity去,这个时候就要用到Parcelable了。首先…

LTE PUCCH F2 TX/RX汇总
TX TX端的公式如下(下图来自sharetechnote): 发送端在36.212/36.211中有详细的描述,就是一系列的数学运算,过程概括如下: 编码、加扰、调制的过程暂不介绍,主要介绍下上图中乘以r_uv的过程,公式如下&#…

面试题:查询连续出现的数字
难度:中等 写一段SQL查询至少连续出现3次的数字。 --------- | Id | Num | --------- | 1 | 1 | | 2 | 1 | | 3 | 1 | | 4 | 2 | | 5 | 1 | | 6 | 2 | | 7 | 2 | --------- 例如:上图表 Logs, 1 是唯一一个连续出现3次的…

php的数组排序方法,PHP数组排序函数
在使用 PHP 进行编程时,有时需要对数组进行排序,通常我们使用的对数组进行排序的方法有冒泡排序、快速排序等等。我们除了可以自定义一些数组排序的函数外,PHP 还内置了多种对数组进行排序的函数,这些函数允许用户在数组内部对元素…

介绍并扩展Fitnesse的测试模块化机制:Scenario
2019独角兽企业重金招聘Python工程师标准>>> 首先普及一下概念,什么是Fitnesse,听一听.NET版Cucumber的创始人Aslak Hellesy谈Fitnesse与Cucumber对比: FIT/Fitnesse和Cucumber都执行高级语言编写的验收测试。FIT仅识别HTML&#…

cmake, This may result in binaries being created in the wrong place
现象: CMake Error: The current CMakeCache.txt directory /home/etouch/minigui-64/minigui/libmgeff-1.0.0/CMakeCache.txt is different than the directory /home/weiym/devel/minigui/rel-3-0/libmgeff-1.0 where CMakeCache.txt was created. This may resul…