设计原则

何为设计原则?
五大设计原则
从设计到模式
23中设计模式

何为设计?

  • 按照哪一种思路或者标准来实现功能
  • 功能相同,可以有不同的设计方案来实现
  • 随着需求增加,设计的作用才能体现出来

unix/linux设计哲学

  1. 小即是美
  2. 让每个程序只做好好一件事
  3. 快速建立原型
  4. 舍弃高效率而取可移植性
  5. 采用纯文本来存储数据
  6. 充分利用软件的杠杆效应(软件复用)
  7. 使用shell脚本来提高效应和可移植性
  8. 避免强制性的用户界面
  9. 让每个程序都称为过滤器(shell的管道操作)
  10. 允许用户定制环境
  11. 尽量使用操作系统内核小而轻量化
  12. 使用小写字母并尽量简短
  13. 沉默是金(在命令行的输出有体现)
  14. 各部分之和大于整体
  15. 寻求90%的解决方案

SOLID五大设计原则

S - 单一职责原则

  • 一个程序只做好一件事
  • 如果功能过于复杂就拆分开,每个部分保持独立

O - 开放封闭原则(important)

  • 对拓展开放,对修改封闭
  • 增加需求时,拓展新代码,而非修改已有代码
  • 这是软件设计的终极目标

L - 李氏置换原则

  • 子类能够覆盖父类
  • 父类能出现的地方子类就能出现
  • js中使用较少(弱类型&继承使用较少)

I - 接口独立原则

  • +保持接口的单一独立,避免出现“胖接口”
  • js中没有接口(typescript例外),使用较少
  • 类似于单一职责原则,这里更关注接口

D - 依赖导致原则

  • 面向接口编程,依赖于抽象而不依赖于具体
  • 使用方只关注接口而不关注具体类的实现
  • js使用较少(没有接口&弱类型)

在js中:

  • S O 体现较多,L I D 体现较少,但是可以了解其用意

例如:在promise中运用了S O:

  • 单一职责原则:每个then中的逻辑只做好一件事
  • 开放封闭原则: 如过增加新需求,拓展then
  • 对拓展开放,对修改封闭
function loadImg(src) {
    var promise = new Promise(function (reslove, reject)  {
        var img = document.creatElement('img')
        img.onload = function() {
            reslove(img)
        }
        img.src = src
    })
    return promise
}

var src = '.....'
var result = loadImg(src)

result.then(function (img) {
    console.log('img.width',img.width)
    return img
}).then(function (img) {
    console.log('img.height',img.height)
}).catch(function (ex) {
    console.log(ex)
})

从设计到模式

23种设计模式

组合型

  • 工厂模式(工厂方法模式,抽象工厂模式,创建者模式)
  • 单例模式
  • 原型模式

组合型

  • 适配器模式
  • 装饰器模式
  • 代理模式
  • 外观模式
  • 适配器模式
  • 装饰器模式
  • 代理模式
  • 外观模式
  • 桥连接模式
  • 组合模式
  • 享元模式

行为型

  • 策略模式
  • 模板方法模式
  • 观察者模式
  • 迭代器模式
  • 职责连模式
  • 命令模式
  • 备忘录模式
  • 状态模式
  • 访问者模式
  • 中介者模式
  • 解释器模式

例子

one

设计原则_设计原则

设计原则_设计原则_02

有继承有引用

class Car {
    constructor(number, name) {
        this.number = number
        this.name = name
    }
}
class Kuaiche extends Car {
    constructor(number, name) {
        super(number, name)
        this.price = 1
    }
}
class Zhuanche extends Car {
    constructor(number, name) {
        super(number, name)
        this.price = 2
    }
}

class Trip {
    constructor(car) {
        this.car = car
    }
    start() {
        console.log(`行程开始,名称: ${this.car.name}, 车牌号: ${this.car.price}`)
    }
    end() {
        console.log('行程结束,价格: ' + (this.car.price * 5))
    }
}

let car = new Kuaiche(100, '桑塔纳')
let trip = new Trip(car)
trip.start()
trip.end()

two

设计原则_设计原则_03

设计原则_设计原则_04

都为引用

// 车
class Car {
    constructor(num) {
        this.num = num
    }
}

// 入口摄像头
class Camera {
    shot(car) {
        return {
            num: car.num,
            inTime: Date.now()
        }
    }
}

// 出口显示器
class Screen {
    show(car, inTime) {
        console.log('车牌号', car.num)
        console.log('停车时间', Date.now() - inTime)
    }
}

// 停车场
class Park {
    constructor(floors) {
        this.floors = floors || []
        this.camera = new Camera()
        this.screen = new Screen()
        this.carList = {}
    }
    in(car) {
        // 获取摄像头的信息:号码 时间
        const info = this.camera.shot(car)
        // 停到某个车位
        const i = parseInt(Math.random() * 100 % 100)
        const place = this.floors[0].places[i]
        place.in()
        info.place = place
        // 记录信息
        this.carList[car.num] = info
    }
    out(car) {
        // 获取信息
        const info = this.carList[car.num]
        const place = info.place
        place.out()

        // 显示时间
        this.screen.show(car, info.inTime)

        // 删除信息存储
        delete this.carList[car.num]
    }
    emptyNum() {
        return this.floors.map(floor => {
            return `${floor.index} 层还有 ${floor.emptyPlaceNum()} 个车位`
        }).join('\n')
    }
}

// 层
class Floor {
    constructor(index, places) {
        this.index = index
        this.places = places || []
    }
    emptyPlaceNum() {
        let num = 0
        this.places.forEach(p => {
            if (p.empty) {
                num = num + 1
            }
        })
        return num
    }
}

// 车位
class Place {
    constructor() {
        this.empty = true
    }
    in() {
        this.empty = false
    }
    out() {
        this.empty = true
    }
}

// 测试代码------------------------------
// 初始化停车场
const floors = []
for (let i = 0; i < 3; i++) {
    const places = []
    for (let j = 0; j < 100; j++) {
        places[j] = new Place()
    }
    floors[i] = new Floor(i + 1, places)
}
const park = new Park(floors)

// 初始化车辆
const car1 = new Car('A1')
const car2 = new Car('A2')
const car3 = new Car('A3')

console.log('第一辆车进入')
console.log(park.emptyNum())
park.in(car1)
console.log('第二辆车进入')
console.log(park.emptyNum())
park.in(car2)
console.log('第一辆车离开')
park.out(car1)
console.log('第二辆车离开')
park.out(car2)

console.log('第三辆车进入')
console.log(park.emptyNum())
park.in(car3)
console.log('第三辆车离开')
park.out(car3)