js设计模式—面向对象和设计原则

322 阅读3分钟

一、面向对象

1. 概念

  • 把客观对象抽象成属性数据和对数据的相关操作,把内部细节和不相关的信息隐藏起来
  • 把同一个类型的客观对象的属性数据和操作绑定在一起,封装成类
  • 并且允许分成不同层次进行抽象,通过继承实现属性和操作的共享
    • 面向对象的分析 OOA(object oriented analyzing)
    • 面向对象的设计 OOD(object oriented designing)
    • 面向对象的变成 OOP(object oriented programing)

2.1 继承

// 父类是公共的
// 把属性和方法,封装在类中
class Animal {
    constructor(name){
        this.name = name
    }
    eat(food) {
        console.log(`${this.name}${food}`)
    }
}

// 继承父类
class Dog extends Animal {
    constructor() {
        super('狗')
    }
    speak() {
        console.log('汪汪汪')
    }
}

// 继承父类
class Cat extends Animal {
    constructor() {
        super('猫')
    }
    speak() {
        console.log('喵喵喵')
    }
}
const dog = new Dog()
dog.eat('肉')
dog.speak()
const cat = new Cat()
cat.eat('鱼')

2.2 封装

把数据封装起来

  • 减少耦合,不该外部访问的不让外部访问,私有的
  • 利于数据的接口权限管理
  • 利于数据的接口权限管理
  • es6目前不支持,一般认为_开头的都是私有的,不要使用
  • 实现
    • public:共有修饰符,可以在类内或内外使用public修饰的属性或行为,默认修饰符
    • protected:受保护的修饰符,可以本类和子类中使用protected修饰的属性和行为
    • private:私有修饰符,只可以在类内使用private修饰的属性和行为
class Person {
    public name: string; // 共有属性,都可以访问
    protected age: number; // 受保护的属性,自己 自己的子类可以访问,其他类不能访问
    private money: number; // 私有的,自己能访问,自己的子类和其他类都不能访问
    constructor(name, age, money) {
        this.name = name;
        this.age = age;
        this.money  money;
    }
}

class Student extends Person {
    public num: number; // 学号
    constructor(name, age, money) {
        super(name, age, money);
        this.num = num;
    }
    getName() {
        // 子类中可以访问父类的共有属性
        console.log(`我的名字叫 ${this.name}`)
    }
    getAge() {
        // 子类可以访问父类的受保护属性
        console.log(`我的年龄是 ${this.age}`)
    }
    getMoney() {
        // 子类不能访问父类的私有属性
        console.log(`我的余额是 ${this.money}`)
    }
}

const s1 = new Student('张三', 10, 100, 1)
// 其他类中可以访问父类的共有属性
console.log(s1.name)
// 其他类不能访问父类的受保护属性
console.log(s1.age)
// 其他类不能访问父类的私有属性
console.log(s1.money)

2.3 多态

  • 同一个接口可以不同实现
  • 保持子类的开放性和灵活性
  • 面向接口编程
class Animal {
    constructor(name){
        this.name = name
    }
    // 接口
    eat(food){
        consloe.log(`吃${food}`)
    }
}

class Dog extends Animal {
    eat(food) {
        console.log(`狗吃${food}`)
    } 
}

class Person extends Animal {
    eat(food) {
        console.log(`人吃${food}`)
    } 
}

const d = new Dog('狗')
d.eat('肉') // 多态
const p = new Person('人')
p.eat('包子') // 多态

二、设计原则

  • 按哪种思路或者标准来实现
  • 功能相同,可以有不同的设计方式
  • 需求如果不断变化,设计的作用才能体现出来

1. SOLID五大设计原则

1.1 单一职责原则

S:Single Responsibility Principle

单一功能原则认为对象应该仅具有一种单一功能的概念(一个程序只做好一件事,如果功能复杂就进行拆分)。

1.2 开放封闭原则

O: Open Closed Principle

开闭原则认为软件体应该是对于扩展开放的,对于修改封闭的概念(增加需求时,扩展新代码而不是修改已有代码)。

1.3 里氏替换原则

L:Liskov Substitution Principle

里氏替换原则认为程序中的对象应该是可以在不改变程序正确性的前提下被它的子类所替换的概念(子类能覆盖父类,父类能出现的地方子类就能出现)

1.4 接口隔离原则

I:Interface Segregation Principle

接口隔离原则认为多个特定客户端接口要好于一个宽泛用途的接口的概念(保持接口的单一独立避免出现胖接口,类似于单一职责原则但更关注接口)。

1.5 依赖反转原则

D:Dependence Inversion Principle

依赖反转原则认为一个方法应该遵从依赖于抽象而不是一个实例的概念。依赖的注入是该原则的一种实现方式(面向接口编程,依赖于抽象而不是具体实现,使用方只关注接口而不关注具体类的实现)。