博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《你必须知道的.NET》书中对OCP(开放封闭)原则的阐述
阅读量:5096 次
发布时间:2019-06-13

本文共 3036 字,大约阅读时间需要 10 分钟。

开放封闭原则(OCP,Open Closed Principle)是面向对象原则的核心。由于软件设计本身所追求的墓边就是封装变化,降低耦合,而开放封闭原则就是对这一目标的直接体现。( 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();       }}

如果有新的客户类型,那么就新增一个这样的类即可。完成!

 

转载于:https://www.cnblogs.com/Benjamin/p/3251987.html

你可能感兴趣的文章
android 通过AlarmManager实现守护进程
查看>>
Sql Server 中由数字转换为指定长度的字符串
查看>>
win7下把电脑设置成wlan热
查看>>
Java 多态 虚方法
查看>>
jquery.validate插件在booststarp中的运用
查看>>
java常用的包
查看>>
PHP批量覆盖文件并执行cmd命令脚本
查看>>
Unity之fragment shader中如何获得视口空间中的坐标
查看>>
支持向量机——内核
查看>>
MFC注册热键
查看>>
万能的SQLHelper帮助类
查看>>
三种方式创建Angular的自定义服务
查看>>
如何在 Terminal 内可以“用惯用的编辑器”快速打开“目前正在做”的专案(project)呢?...
查看>>
uboot分析:uboot的启动过程分析
查看>>
tmux的简单快捷键
查看>>
springboot笔记04——读取配置文件+使用slf4j日志
查看>>
[Swift]LeetCode653. 两数之和 IV - 输入 BST | Two Sum IV - Input is a BST
查看>>
[Swift]LeetCode922.按奇偶排序数组 II | Sort Array By Parity II
查看>>
微信小程序的wxml文件和wxss文件在webstrom的支持
查看>>
SaltStack快速部署及测试
查看>>