《你必须知道的.NET》书中对OCP(开放封闭)原则的阐述
开放封闭原则(OCP,Open Closed Principle)是面向对象原则的核心。由于软件设计本身所追求的墓边就是封装变化,降低耦合,而开放封闭原则就是对这一目标的直接体现。(你必须知道的.NET p48页)
以下用例子说明,同样来自该书。
假设在一个柜台业务处理系统,首先有客户:
public class Client
{
public string Name{get;set;}
private string ClientType { get; set; }
}
ClientType表示客户的类型,如"存款用户","转账用户","取款用户"
public class BusyBankStaff
{
private readonly BankProcess bankProcess = new BankProcess();
public void HandleProcess(Client client)
{
switch (client.ClientType)
{
case "存款用户":
bankProcess.Deposit();
break;
case "转账用户":
bankProcess.Transfer();
break;
case "取款用户":
bankProcess.DrawMoney();
break;
}
}
}
业务处理类
public class BankProcess
{
public void Deposit() { }
public void Transfer() { }
public void DrawMoney() { }
}
问题是,如果银行多了一种业务类型,比如代购公积金,那么,必然地,BankProcess要修改为
public class BankProcess
{
public void Deposit() { }
public void Transfer() { }
public void DrawMoney() { }
public void BuyFund(){}
}
,并且BusyBankStaff中坏味道的switch语句又要增加一个条件。
其实,这样类的设计违反了开放封闭原则。
所谓开放封闭,是指,对修改封闭——一个类一旦写好,就不能再修改;对扩展开放——如果有新的需求,可以在不修改原系统的基础上方便增加。
怎么改?抽象!对可能或经常变化的部分使用接口将其封装。在此例中,BusyBankStaff依赖于BankProcess类,将其改为依赖于一个IBankProcess接口
public interface IBankProcess
{
void Process();
}
然后,不同的业务类型都实现该接口
public class DepositProcess:IBankProcess
{
public void Process(){}
}
public class TransferProcess:IBankProcess
{
public void Process(){}
}
等等。
此时BusyBankStaff可以摇身一变,变成EasyBankStaff
public class EasyBankStaff
{
private readonly IBankProcess bankProcess = new BankProcess();
public void HandleProcess(Client client)
{
bankProcess=client.CreateProcess();
bankProcess.Process();
}
}
注意到,业务的分配由银行的业务员转为客户,让客户自己依据自己的类型创建相应的bankProcess对象——这就是现实中客户依据业务类型的不同在排队取号机前取不同的业务号码。
现在,若新增一个业务,只要增加一个实现IBankProcess接口的类即可。
如
public class BuyFund:IBankProcess
{
public void Process(){}
}
大功告成了吗?不!
若观察系统,我们会发现客户类此时已经转变为
public class Client
{
public string Name{get;set;}
private string ClientType { get; set; } public IBankProcess CreateProcess()
{
switch(clientType)
{
case"存款用户":
return new DepositProcess();
case "转账用户":
return new TransferProcess(); }
}
}
又是一个违反OCP的类,又是switch的坏味道。
怎么办?同样是抽象!
将client类抽象为接口
public interface IClient
{
IBankProcess CreateProcess();
}
然后不同类型的客户都实现这一接口
public class DepositClient:Client
{
IBankProcess CreateProcess
{
return new DepositProcess();
} }
public class TransferClient:Client
{
IBankProcess CreateProcess
{
return new TransferProcess();
} }
如果有新的客户类型,那么就新增一个这样的类即可。完成!
《你必须知道的.NET》书中对OCP(开放封闭)原则的阐述的更多相关文章
- 必须知道的Spring Boot中的一些Controller注解
这篇文章是抄其他人的,原址:https://cloud.tencent.com/developer/article/1082720 本文旨在向你介绍在Spring Boot中controller中最基 ...
- [你必须知道的.NET]第二十六回:认识元数据和IL(下)
发布日期:2009.03.04 作者:Anytao © 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. 说在,开篇之前 书接上回: 第二十四回:认识元数据和IL(上), ...
- MVC中你必须知道的13个扩展点
MVC中你必须知道的13个扩展点 pasting 转:http://www.cnblogs.com/kirinboy/archive/2009/06/01/13-asp-net-mvc-extensi ...
- 解惑《你必须知道的.net》——C#继承关系中【方发表】的创建和调用
前言: 现在正在读<你必须知道的.net>(第二版)一书,看到IL语言那一章,将call.callvirt和calli时候,书中举了一个例子,是一个三层继承的例子,我一开始看的时候就有点懵 ...
- [你必须知道的.NET]第二十五回:认识元数据和IL(中)
发布日期:2009.02.25 作者:Anytao © 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. 说在,开篇之前 书接上回[第二十四回:认识元数据和IL(上)], ...
- 每个项目中,你必须知道的11个Java第三方类库。
Java第三方library ecosystem是一个很广阔的范畴.不久前有人撰文:每个项目中,你必须知道的11个Java第三方类库. 单元测试 1.DBUnit DBunit是一个基于junit扩展 ...
- [你必须知道的.NET]第三十回:.NET十年(下)
发布日期:2009.05.11 作者:Anytao © 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. /// <summary> /// 本文部分内容,已 ...
- [你必须知道的.NET]第二十九回:.NET十年(上)
发布日期:2009.05.08 作者:Anytao © 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. /// <summary> /// 本文部分内容,已 ...
- 从零开始学习jQuery(剧场版) 你必须知道的javascript
原文:从零开始学习jQuery(剧场版) 你必须知道的javascript 一.摘要 本文是jQuery系列教程的剧场版, 即和jQuery这条主线无关, 主要介绍大家平时会忽略的一些javascri ...
随机推荐
- Python无类再理解--metaclass,type
上次理解过一次,时间久了,就忘了.. 再学习一次.. http://blog.jobbole.com/21351/ ======================= 但是,Python中的类还远不止如此 ...
- 如何观察JS的事件队列的执行划分
也就是说,不同的操作函数,操作符,JS将其放入事件队列是不一样的... 比如: 外部函数和内部函数,就是分两次放入事件循环的尾端的. 比如,多个操作符组成的链式操作,也有可能是放不同的操作批次进入事件 ...
- 【POJ水题完成表】
题目 完成情况 poj1000:A+B problem 完成 poj1002:电话上按键对应着数字.现在给n个电话,求排序.相同的归一类 完成 poj1003:求最小的n让1+1/2+1/3+...+ ...
- Javascript事件冒泡机制
1. 事件 在浏览器客户端应用平台,基本生都是以事件驱动的,即某个事件发生,然后做出相应的动作. 浏览器的事件表示的是某些事情发生的信号.事件的阐述不是本文的重点,尚未了解的朋友,可以访问W3scho ...
- JS判断输入值是否为正整数
JS中的test是原来是JS中检测字符串中是否存在的一种模式,JS输入值是否为判断正整数代码: <script type=”text/javascript”> function test( ...
- 建造者模式与原型模式/builder模式与prototype模式/创建型模式
建造者模式 定义 用于简化复杂对象的创建 JDK中的建造者模式 java.lang.StringBuilder中的append()方法,每次调用后返回修改后的对象本身. public StringBu ...
- 在Salesforce中将 Decimal 数据转换成美元格式
闲言少叙,直接上代码(Apex Class 中的方法): private string ConvertToMoneyFormat(decimal price){ if (price == null | ...
- HDU 5919 Sequence II 主席树
Sequence II Problem Description Mr. Frog has an integer sequence of length n, which can be denoted ...
- 智能车学习(十)——MMA8451加速度计的使用
一.驱动说明: 就是使用I2C的通信方式驱动这款加速度计就行了,代码的话选择使用51单片机的代码进行移植. 二.代码分享: 1.头文件: #ifndef MMA8451_H #define MMA84 ...
- hdu1059 多重背包(转换为01背包二进制优化)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1059 之前写过一个多重背包二进制优化的博客,不懂请参考:http://www.cnblog ...