乐趣区

javascript设计模式学习之路

面向对象

概念

,具有相同或相似属性或方法的对象的抽象就是类。例如:人都有姓名、年龄,都会吃饭、说话,其中姓名、年龄就是人这个类的属性,吃饭、说话就是人这个类的方法。
对象,类的具体实现就是对象。例如,小明这个人就可以认为是人这个类的具体实现。

// 类
class Person {constructor(name, age) {
    this.name = name // 属性 姓名
    this.age = age // 属性 年龄
  }
  // 方法 吃饭
  eat() {alert(`${this.name} eat something.`)
  }
  // 方法 说话
  speak() {alert(`My name is ${this.name}, my age is ${this.age}.`)
  }
}

// 对象 Person 的具体实现
const xiaoming = new Person('xiaoming', 10)
xiaoming.eat()
xiaoming.speak()

三要素

继承,子类可以继承父类的属性和方法。例如,学生是人类的一种,具有人类的所有特性,也可以有自己的特性,可以认为学生继承了人这个父类。

class Person {constructor(name, age) {
    this.name = name
    this.age = age
  }
  eat() {alert(`${this.name} eat something.`)
  }
  speak() {alert(`My name is ${this.name}, my age is ${this.age}.`)
  }
}

// Student 继承了 Person,具有 Person 的所有属性,并且有自己的特有属性
class Student extends Person {constructor(name, age, no) {super(name, age)
    this.no = no // 学生可以有学号属性
  }
  // 学生可以学习
  study() {alert(`${this.name} study something.`)
  }
}

const xiaoming = new Student('xiaoming', 10, '10010')
xiaoming.study()

封装 ,类的属性具有访问权限。说到封装不得不说public、protected、private 三个关键字,其中 public 关键字修饰的属性表示公有的属性,可以随便访问,protected关键字修饰的属性表示子类内部可以访问,private关键字修饰的属性只能在类内部访问,外部无法访问(图中 + 表示共有属性、#表示子类可以访问、-表示私有属性,由于 javascript 不支持这三种修饰符,所以此处用 typescript 演示,了解即可)。

class Person {
  public name // 公有属性,可以随便访问
  public age
  protected weight // 子类内部可以访问,外部无法访问
  constructor(name, age) {
    this.name = name
    this.age = age
    this.weight = 120
  }
  eat() {console.log(`${this.name} eat something.`)
  }
  speak() {console.log(`My name is ${this.name}, age is ${this.age}.`)
  }
}

class Student extends Person {
  private grilfriend // 私有属性,只有在 Student 类内部才可以访问
  constructor(name, age) {super(name, age)
    this.grilfriend = 'xiaoli'
  }
  study() {alert(`${this.name} study.`)
  }
  getWeight() {alert(`weight ${this.weight}.`) // protected 修饰的属性子类内部可以访问
  }
}

let xiaoming = new Student('xiaoming', 10)
xiaoming.getWeight()
alert(xiaoming.name)
// alert(xiaoming.weight) // 报错
// alert(xiaoming.grilfriend) // 报错

多态,子类既可以继承父类的属性和方法,也可以有自己的特性。学生是人类的一种,除了具有人类的所有特性之外,还可以有自己独特的特性,例如学生可以进行学习这个动作。

class Person {constructor(name) {this.name = name}
  saySomething() {}
}

class A extends Person {constructor(name) {super(name)
  }
  saySomething() {alert('This is A.')
  }
}

class B extends Person {constructor(name) {super(name)
  }
  saySomething() {alert('This is B.')
  }
}

五大设计原则

单一职责原则 ,应该有且只有一个引起变更的原因,一个程序只做一件事情,如果功能过于复杂,就要拆开,每部分保持独立。
开放封闭原则 ,一个软件的实体,比如模块、类、对象应该对扩展开放,对修改封闭,增加新需求时要增加代码而不是修改代码。
里氏置换原则 现的地方,子类就可以出现,且替换成子类也不会产生任何错误或者异常。
接口独立原则 接口,不要建立臃肿庞大的接口。即接口尽量细化,同时接口中的方法尽量少。
依赖倒置原则 ,面向接口编程,模块间的依赖关系通过接口和抽象类产生,实体类之间不直接发生依赖关系。
最少知识原则 统提供一个简单的入口,访问者或者客户不用了解系统内部的实现细节,只要懂得如何调用就好。

工厂模式

定义一个创建对象的工厂,将创建者和构造函数分离,创建者不用关心具体构造函数的实现,符合开放封闭原则和最少知识原则。

class Product {constructor(name) {this.name = name}
  init() {console.log('init.')
  }
  fn() {console.log('fn.')
  }
}

class Creator {create(name) {return new Product(name)
  }
}

const creator = new Creator()
const obj = creator.create('obj')
obj.init()
obj.fn()

单例模式

系统中被唯一使用,一个类只有一个示例,例如:

  • 登录框
  • 购物车

class SingleObject {constructor() {}
  init() {console.log('init...')
  }
}

SingleObject.getInstance = (function() {
  let instance = null
  return function() {if (!instance) {instance = new SingleObject()
    }
    return instance
  }
})()

const obj1 = SingleObject.getInstance()
obj1.init()
const obj2 = SingleObject.getInstance()
obj2.init()
console.log(obj1 === obj2)

退出移动版