五大设计原则
单一职责原则
通过解耦,让每个模块的职责更加独立
依赖倒置原则
上层模块不应该依赖底层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。核心思想是:要面向接口编程,不要面向实现编程。
/**
* 首先实现应用商店的分享功能,后来又增加了评分功能
*/
// 底层模块, 应用商店部分
class Store {
constructor(){
for(let module of Store.modules.values()){
module.init(this)
}
}
static modules = new Map()
static inject(module){
Store.modules.set(module.constructor.name, module)
}
}
// 实现分享功能
class Share{
init(store){
store.share = this
}
shareTo(){
console.log('分享了功能')
}
}
// 新加评分功能
class Rate{
init(store){
store.rate = this
}
rate(){
console.log('评分了')
}
}
// 先注册这两个功能
const share = new Share()
const rate = new Rate()
Store.inject(share)
Store.inject(rate)
const store = new Store()
// 调用功能
store.share.shareTo()
store.rate.rate()
开放-封闭原则
对上层功能扩展的开放,对底层代码修改的封闭
/**
* 实现一个每种动物叫的功能
*/
// 第一种
// 底层代码部分
class MakeSound {
constructor(animal){
animal.sound()
}
}
// 功能拓展部分
class Duck {
sound(){
console.log('嘎嘎嘎')
}
}
const duck = new Duck()
new MakeSound(duck)
// 新加动物的时候,只需要增加拓展部分,不需要对基础代码做变动
class Chicken {
sound(){
console.log('咯咯咯')
}
}
const chicken = new Chicken()
new MakeSound(chicken)
// 第二种
// 底层代码部分
class Animal2 {
sound(){
console.log('')
}
}
// 功能拓展部分
class Duck2 extends Animal2{
sound(){
console.log('嘎嘎嘎')
}
}
const duck2 = new Duck2()
duck2.sound()
接口隔离原则
接口应该尽可能精简
// 有一个动物大类,新建海洋动物类和陆地动物类
class Animal{
talk(){}
run(){}
swim(){}
}
class Sea extends Animal{}
class Land extends Animal{}
// 修改一下
class Animal{
talk(){}
}
class Sea extends Animal{
swim(){}
}
class Land extends Animal{
run(){}
}
里氏替换原则
子类可以拓展接口,不能改变接口,不要破坏继承体系
常用设计模式
创建型
工厂模式
生产同类型产品
class Animal{
constructor(name){
this.animal = name
}
}
const duck = new Animal('duck')
const pig = new Animal('pig')
建造者模式
将一个负责对象的构建层与其表示层互相分离
// 实现一个优惠套餐单元, 皮肤+商品套餐打折售卖
class Product{
constructor(name){
this.name = name
}
init(){
console.log('product init')
}
}
class Skin{
constructor(name){
this.name = name
}
init(){
console.log('skin init')
}
}
class Shop {
constructor(){
this.package = ''
}
create(name){
this.package = new PackageBuilder(name)
}
get(){
return this.package.getPackage()
}
}
class PackageBuilder{
constructor(name){
this.game = new Product(name)
this.skin = new Skin(name)
}
getPackage(){
return this.game.init() + this.skin.init()
}
}
单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点
// 页面需要一个弹框
class Dialogue{
open(){}
}
class Load(){
constructor(){
this.dialogue = ''
}
createdialogue(){
if(this.dialogue){
return this.dialogue.open()
} else {
this.dialogue = new Dialogue
return this.dialogue.open()
}
}
}
const load = new Load()
load.createdialogue()
// 也可以用闭包
function Dialogue(){
this.open = () => { console.log('open dialogue')}
}
function Load(){
this.createdialogue = () => {
let dialogue = null
return () => {
if(dialogue){
return dialogue.open()
} else {
dialogue = new Dialogue
return dialogue.open()
}
}
}
}
let load = new Load()
let dialogue = load.createdialogue()
dialogue()
结构型
适配器模式
适配已有方案
适配器一般在开发中,用作数据格式的适配比较多,本来定义的数组类型的,现在返回的是一个大对象,这时候就可以不改变原有代码,而是在外面加一个适配器,将对象转为数组结构
装饰器模式
增强已有方案
// 先有一个人,然后我们不断的给这个人加buff
class Person{
constructor(name){
this.name = name
}
}
class Buff{
constructor(person){
this.person = person
}
fly(){
console.log('会飞')
}
}
const lisi = new Person('lisi')
let bufflist = new Buff(lisi)
bufflist.fly()
代理模式
为访问对象提供一个代理,控制对它的访问
// 进入一款游戏之前,需要对玩家的年龄进行验证
class Game{
play(){}
}
class Player{
constructor(age){
this.age = age
}
}
class GameProxy{
constructor(player){
this.player = plauer
}
play(){
if(this.player.age >= 18){
return new Game().play()
}
}
}
let player = new Player(19)
new GameProxy(player)
行为型
命令模式
包裹传递命令
class Receiver{
excute(){
console.log('跑')
}
}
class Operator{
constructor(command){
this.command = command
}
run(){
this.command.excute()
}
}
class Command{
constructor(receiver){
this.receiver = receiver
}
execute(){
console.log('执行命令')
this.receiver.excute()
}
}
const solider = new Receiver()
const order = new Command(solider)
const player = new Operator(order)
player.run()
模板模式
封装好固定的流程
// 把东西放进冰箱的步骤
class Process{
constructor(name){
this.name = name
}
openDoor(){}
put(){
console.log('put' + this.name)
}
closeDoor(){}
init(){
this.openDoor()
this.put()
this.closeDoor()
}
}
观察者模式
模块间的互通
// 顾客们在销售那里留下信息,有房源的时候,销售第一时间通知他们
class Seller {
constructor(){
this.observer = new Set()
}
subscribe(customer){
this.observer.add(customer)
}
notify(){
this.observer.forEach(customer => {
customer.receive()
})
}
}
class Customer {
constructor(name){
this.name = name
}
receive(){
console.log(this.name + '收到')
}
}
let seller = new Seller()
let lisi = new Customer('lisi')
seller.subscribe(lisi)
let zhangsan = new Customer('zhangsan')
seller.subscribe(zhangsan)
seller.notify()
职责链模式
多个对象都有机会处理请求,避免请求处理处理模块的耦合, 将这些对象连成一条链,沿着这条链传递请求,直到4有个对象能处理它
// 根据一个变量的值来确定执行
// 普通写法
function excute(x) {
if(x === 1 ){
console.log('这是1')
} else if(x === 2){
console.log('这是2')
} else if(x === 3){
console.log('这是3')
}
}
// 职责链模式
function excute(x){
excute1(x)
}
function excute1(x){
if(x === 1){
console.log('这是1')
} else{
excute2(x)
}
}
function excute2(x){
if(x === 2){
console.log('这是2')
} else{
excute3(x)
}
}
function excute3(x){
if(x === 3){
console.log('这是3')
} else{
console.log('啥也不是')
}
}