Appearance
单一职责原则
Single Responsibility Principle 简称SRP
一个类应该只负责一个功能任务,其内部不应该完成与该任务不相关的其他任务
typescript
// User 只负责用户登录
class User {
private capcha: Capcha
public login(code: string) {
if (this.capcha.verify(code)) {
}
}
}
// Capcha只负责验证码,两者都符合单一原则
class Capcha {
public verify() {
return '正确'
}
}
接口隔离原则
Interface Segregation Principle 简称ISP
不依赖不需要的接口,即要将接口拆分成更小、更具体的接口,避免创建过于庞大和复杂的接口
typescript
interface User {
checkAuth(uid: number): boolean
login(mobile: string, pwd: string): void
register(mobile: string, pwd: string): void
}
interface Admin {
checkAuth(uid: number, passKey: strgin): boolean
login(mobile: string, pwd: string): void
}
/**
* 虽然user和admin有共同特点,但是需要遵循接口隔离原则不去extend后拓展
* 比如说checkAuth方法,admin和user共用同一个变成如下
* checkAuth(uid: number, passKey?: strgin): boolean
* 这就不符合接口隔离原则,后面拓展user或者admin也会受阻
*/
class UserImp implements User {
checkAuth(uid: number): boolean {
throw new Error('Method not implemented.')
}
login(mobile: string, pwd: string): void {
throw new Error('Method not implemented.')
}
register(mobile: string, pwd: string): void {
throw new Error('Method not implemented.')
}
}
class AdminImp implements Admin {
checkAuth(uid: number, passKey: string): boolean {
throw new Error('Method not implemented.')
}
login(mobile: string, pwd: string): void {
throw new Error('Method not implemented.')
}
}
依赖倒转原则
Dependence Inversion Principle 简称DIP
功能的实现依赖抽象,程序设计中,应该想考虑抽象接口,在考虑实现接口中的任务
也就是说所有功能上的实现应该依赖抽象接口,有了接口以后才能去考虑接口的每一个任务怎么实现
typescript
/**
* 要从总体去看,规范你如何进行实行
* 而不是如何进行执行,从最顶层看
* 先有架子(细致的框架),在往里丢东西(在具体实现)
*/
interface Order {
// 生成订单
generateOrder(prdId: string, count: number): void
// 支付
payForOder(orderId: string): void
}
class OrderImp implements Order {
generateOrder(prdId: string, count: number): void {
throw new Error('Method not implemented.')
}
payForOder(orderId: string): void {
throw new Error('Method not implemented.')
}
}
里氏替换原则
Liskov Substitution Principle 简称LSP
在继承时,子类可以拓展父类功能,尽可能不要重新父类方法(vue的单项数据流)
typescript
class User {
public login(name: string, pwd: string) {
// ...
}
public register(name: string, pwd: string) {
// ...
}
}
class Customer extends User {
// 子方法也有自己的login,但是尽量不去重写父方法的login
public loginWithMobile(mobile: string, code: string) {}
}
开闭原则
Open Close Principle 简称COP
如果需求变化了,不是修改现有代码风格,而是在现有进行扩展
关闭修改原有代码,开放拓展源代码
typescript
class User {
public changeName(uid: number, newName: string) {
// ...
}
// 在原有的changeName进行拓展新的changeName
public changeNameWithCode(uid: number, code: string, newName: string) {
this.changeName(1, 'name')
// ...
}
}
迪米特法则
Law of Demeter 简称LOD
类与类之间尽量保持最少的依赖,访问其他类的最小单位应该是方法,而不是属性和内部逻辑【解耦】
ts
class A {
b: B
someMethod() {
// 符合迪米特法则
this.b.doSomething()
// 不符合
this.b.c.someMethod()
}
}
class B {
c: C
doSomething() {
this.c.someMethod()
}
}
class C {
someMethod() {}
}
合成复用原则
Composite Reuse Principle 简称CRP
类的继承是增加了类与类之前的耦合性,所有优先使用对象组合或聚合,而不是通过继承实现代码的复用
ts
class Controller {
private userService: Service
public register(name: string, pwd: string) {
this.userService.register(name, pwd)
}
}
class Service {
public register(name: string, pwd: string) {}
}
参考nest.js中controller调用service的方式