概念
迪米特法则
Don't talk to strangers. 不要和陌生人说话
迪米特法则又称为最小知识原则,他被描述为一种代码设计的基本原则.他要求一个对象对其他对象应该有最少的了解.这个法则认为,任意对象应当也只能调用如下对象:
- 对象本身
- 作为实参传入的对象
- 在方法内创建的对象
从业务理解的方向上来说,我们需要了解类与类之间的关系,哪些类之间是可以直接产生业务协作的,哪些类之间又是应该对彼此知之甚少的?这边给一个demo来帮助了解.
Demo
现在有业务场景如下:
病人需要支付看病费用,于是他走到了支付窗口拿出了钱包,准备开始付钱
// 病人
class Patient {
name: string
patientId: string | number
MineWallet: Wallet
constructor() {
this.name = ''
this.init()
}
/**
* 获取个人信息
*/
getUserInfo = async () => {
let res = await apiGetUserInfo()
this.patientId = res.patientId
this.name = res.name
}
/**
* 初始化钱包
*/
initWallet = async () => {
let mineWallet = new Wallet({ patientId: this.patientId })
mineWallet.init()
this.MineWallet = mineWallet
}
/**
* 初始化
*/
init = async() => {
await this.getUserInfo()
this.initWallet()
}
// 获取钱包
getWallet = () => {
return this.MineWallet
}
}
// 钱包
class Wallet extends Object{
money: number
patientId: number | string
constructor(params) {
super(params)
const { patientId } = params
this.money = 0
this.patientId = patientId
}
// 获取余额
getMoney = async () => {
let res = await apiGetMoney(this.patientId)
this.money = this.money
return this.money
}
setMoney = async (money: number) => {
let res = await apiSetMoney(this.patientId)
}
// 初始化钱包
init = async () => {
this.patientId ?
this.getMoney():
console.log('出问题')
}
}
// 支付窗口
class PayWindow {
pay = async(patient: Patient, money: number) => {
let thiswallet: Wallet
thiswallet = patient.getWallet()
let nowMoney = await thiswallet.getMoney()
if (nowMoney > money) {
thiswallet.setMoney(nowMoney - money)
} else {
console.log('出问题')
}
}
}
这样子的设计其实就违反了迪米特法则.我们不如将这一串代码语意化
病人: 嘿哥们 我要付钱!
收银台工作员: 好的老弟,我是不会告诉你要花多少钱的,你先把钱包拿出来给我,我来看看够不够!
病人: ??? (但还是交出了钱包)
收银台工作员: 很好,够了,看不出你还挺有钱,钱付好了你可以走了.
看出来了吗?问题就在于收银台工作员不应该直接和钱包发生交互,根据迪米特法则,payWindow和Wallet两个对象之间应该是无知的.
那么正确的流程是什么呢? 其实也很简单.将pay方法写在patient类中,payWindow只会去调用patient类中的pay方法.
// 病人
class Patient {
//.....
pay = async (money: number) => {
let nowMoney = await this.MineWallet.getMoney()
if (nowMoney > money) {
this.MineWallet.setMoney(nowMoney - money)
} else {
console.log('出问题')
}
}
}
class PayWindow {
pay = async(patient: Patient, money: number) => {
patient.pay(money)
}
}
再次语意化一下:
病人: 嘿哥们儿我要付钱!
收银台工作人员: 共计199元.
病人: 让我看看...钱够了,给你.
收银台工作人员: 好的.
中介者模式
中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
优点:
- 降低了类的复杂度,将一对多转化成了一对一。
- 各个类之间的解耦,减少对象之间的关联性,让每一个对象都能够独立
- 符合迪米特原则。
- 不会引入太多其他的系统
- 系统被依赖的程度降低
缺点:
- 中介类可能会因为功能量的增加而变得很大,需要配套使用其他的设计模式使用.
在上面的例子中.patient类就作为了payWindow和wallet的中介类.