封装变化的内容
深入理解软件设计原则 第 7 篇
什么是优秀的软件设计?
如何对其进行评估?
你需要遵循哪些实践方式才能实现这样的方式?
如何让你的架构灵活、 稳定且易于理解?
找到程序中的变化内容并将其与不变的内容区分开
该原则的主要目的是将变更造成的影响最小化。
假设你的程序是一艘船, 变更就是徘徊在水下的可怕水雷。如果船撞上水雷就会沉没。
了解到这些情况后, 你可将船体分隔为独立的隔间, 并对其进行安全的密封, 以使得任何损坏都会被限制在隔间范围内。现在, 即使船撞上水雷也不会沉没了。
你可用同样的方式将程序的变化部分放入独立的模块中, 保 护其他代码不受负面影响。最终, 你只需花较少时间就能让 程序恢复正常工作, 或是实现并测试修改的内容。你在修改 程序上所花的时间越少, 就会有更多时间来实现功能。
1.方法层面的封装
假如你正在开发一个电子商务网站。代码中某处有一个getOrderTotal 获取订单总额 方法, 用于计算订单的总价 (包括税金在内)。
我们预计在未来可能会修改与税金相关的代码。税率会根据 客户居住的国家/地区、 州/省甚至城市而有所不同; 而且一 段时间后, 实际的计算公式可能会由于新的法律或规定而修 改。因此,你将需要经常性地修改 getOrderTotal 方法。不 过仔细看看方法名称, 连它都在暗示其不关心税金是如何计 算出来的。
//伪代码
method getOrderTotal(order) is
total = 0
foreach item in order.lineItems
total += item.price * item.quantity
if (order.country == "US")
total += total * 0.07 // 美国营业税
else if (order.country == "EU"):
total += total * 0.20 // 欧洲增值税
return total
修改前:税率计算代码和方法的其他代码混杂在一起。
你可以将计算税金的逻辑抽取到一个单独的方法中, 并对原始方法隐藏该逻辑。
method getOrderTotal(order) is
total = 0
foreach item in order.lineItems
total += item.price * item.quantity
total += total * getTaxRate(order.country)
return total
method getTaxRate(country) is
if (country == "US")
return 0.07 // 美国营业税 else if (country == "EU") return 0.20 // 欧洲增值税
else return 0
这样税率相关的修改就被隔离在单个方法内了。此外, 如果 税率计算逻辑变得过于复杂, 你也能更方便地将其移动到独 立的类中。
2.类层面的封装
一段时间后, 你可能会在一个以前完成简单工作的方法中添 加越来越多的职责。新增行为通常还会带来助手成员变量和 方法, 最终使得包含接纳它们的类的主要职责变得模糊。将 所有这些内容抽取到一个新类中会让程序更加清晰和简洁。
修改前:在 订单 Order 类中计算税金。
订单类的对象将所有与税金相关的工作委派给一个专门负责
的特殊对象。
修改后:对订单类隐藏税金计算。
- “单播”、“组播”和“多播”
- flash player10.1 + FMS4中的p2p功能
- fms4 p2p:图片分享
- 老域名新用的优缺点分析
- 不用临时变量,交换二个整型变量的值
- monoTouch开发(1):win7 + vmware下安装mac os
- 数据结构C#版笔记--队列(Quene)
- 数据结构C#版笔记--堆栈(Stack)
- MySQL基础入门-第一课 新建数据库(linux版本)
- 2017年度最不安全密码报告,看看你的密码安全吗?
- 数据结构C#版笔记--顺序表(SeqList)
- 数据结构C#版笔记--单链表(LinkList)
- 操作系统 页式存储 页与块之间的关系详解
- 数据结构C#版笔记--双向链表(DbLinkList)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- NodeMCU连接wifi语句报错:“stdin:1: bad argument #1 to 'config' (config table not found!)”
- Angularjs动态加载ECharts(二)
- 【LeetCode】每日一题(8.3)
- LeetCode精选好题(四)
- 【Android 直播软件开发:音视频硬解码篇】
- 知更鸟主题修改CSS:让凌乱的标签变得整洁清爽
- 浅谈 Android Dex 文件
- Tcp连接建立与连接释放
- Python Django开发 异常及解决办法(三)
- 有赞零售小票打印跨平台解决方案
- Angular [(ngModel)]的ng-dirty设置时机
- 有赞订单导出的配置化实践
- k2路由器刷系统
- 使用Seq搭建免费的日志服务
- html可伸缩侧边栏