Skip to content

单一职责原则

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的方式