开放封闭原则(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(开放封闭)原则的阐述的更多相关文章

  1. 必须知道的Spring Boot中的一些Controller注解

    这篇文章是抄其他人的,原址:https://cloud.tencent.com/developer/article/1082720 本文旨在向你介绍在Spring Boot中controller中最基 ...

  2. [你必须知道的.NET]第二十六回:认识元数据和IL(下)

    发布日期:2009.03.04 作者:Anytao © 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. 说在,开篇之前 书接上回: 第二十四回:认识元数据和IL(上), ...

  3. MVC中你必须知道的13个扩展点

    MVC中你必须知道的13个扩展点 pasting 转:http://www.cnblogs.com/kirinboy/archive/2009/06/01/13-asp-net-mvc-extensi ...

  4. 解惑《你必须知道的.net》——C#继承关系中【方发表】的创建和调用

    前言: 现在正在读<你必须知道的.net>(第二版)一书,看到IL语言那一章,将call.callvirt和calli时候,书中举了一个例子,是一个三层继承的例子,我一开始看的时候就有点懵 ...

  5. [你必须知道的.NET]第二十五回:认识元数据和IL(中)

    发布日期:2009.02.25 作者:Anytao © 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. 说在,开篇之前 书接上回[第二十四回:认识元数据和IL(上)], ...

  6. 每个项目中,你必须知道的11个Java第三方类库。

    Java第三方library ecosystem是一个很广阔的范畴.不久前有人撰文:每个项目中,你必须知道的11个Java第三方类库. 单元测试 1.DBUnit DBunit是一个基于junit扩展 ...

  7. [你必须知道的.NET]第三十回:.NET十年(下)

    发布日期:2009.05.11 作者:Anytao © 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. /// <summary> /// 本文部分内容,已 ...

  8. [你必须知道的.NET]第二十九回:.NET十年(上)

    发布日期:2009.05.08 作者:Anytao © 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. /// <summary> /// 本文部分内容,已 ...

  9. 从零开始学习jQuery(剧场版) 你必须知道的javascript

    原文:从零开始学习jQuery(剧场版) 你必须知道的javascript 一.摘要 本文是jQuery系列教程的剧场版, 即和jQuery这条主线无关, 主要介绍大家平时会忽略的一些javascri ...

随机推荐

  1. MVC中Form表单的提交

    概述 Web页面进行Form表单提交是数据提交的一种,在MVC中Form表单提交到服务器.服务端接受Form表单的方式有多种,如果一个Form有2个submit按钮,那后台如何判断是哪个按钮提交的数据 ...

  2. 【PHP Cookie&&Session】

    大部分的人都知道Cookie,但是可能不了解Session,现在对这两者进行解释. 问题的提出: 有些网站会提示用户在一定的时间之内免登陆,这是用的什么技术?答案是Cookie技术. 有些购物网站会提 ...

  3. php正则获取网页标题、关键字、网页描述代码

    php正则获取网页关键字,代码如下: function get_keywords($html) { $html=strtolower($html); preg_match("@<hea ...

  4. 在ASP.NET Core 1.0中如何发送邮件

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:目前.NET Core 1.0中并没有提供SMTP相关的类库,那么要如何从ASP.NE ...

  5. C中的野指针—如何避免

    转自:http://www.cnblogs.com/viviwind/archive/2012/08/14/2638810.html 先看一个例子: struct student{ char* nam ...

  6. Create a Qt Widget Based Application—Windows

    This turtorial describes how to use Qt Creator to create a small Qt application, Text Finder. It is ...

  7. Android系统介绍与框架(转)

    一.Andriod是什么? Android系统是Google开发的一款开源移动OS,Android中文名被国内用户俗称“安卓”.Android操作系统基于Linux内核设计,使用了Google公司自己 ...

  8. 在Salesforce中可以对某一个Object的Standard Button或Link进行重写

    在Salesforce中可以对某一个Object的Standard Button或Link进行重写,来实现我们特定的逻辑过程,比如:在删除某个Object之前要判断该Object的某个Field的状态 ...

  9. POJ 1741 Tree 树分治

    Tree     Description Give a tree with n vertices,each edge has a length(positive integer less than 1 ...

  10. SpringMyBatis解析1-使用示例

    MyBatis使用介绍 MyBatis的详细使用介绍  http://www.cnblogs.com/xrq730/category/796495.html 建立PO public class Per ...