何为设计原则?
五大设计原则
从设计到模式
23中设计模式
何为设计?
- 按照哪一种思路或者标准来实现功能
- 功能相同,可以有不同的设计方案来实现
- 随着需求增加,设计的作用才能体现出来
unix/linux设计哲学
- 小即是美
- 让每个程序只做好好一件事
- 快速建立原型
- 舍弃高效率而取可移植性
- 采用纯文本来存储数据
- 充分利用软件的杠杆效应(软件复用)
- 使用shell脚本来提高效应和可移植性
- 避免强制性的用户界面
- 让每个程序都称为过滤器(shell的管道操作)
- 允许用户定制环境
- 尽量使用操作系统内核小而轻量化
- 使用小写字母并尽量简短
- 沉默是金(在命令行的输出有体现)
- 各部分之和大于整体
- 寻求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
有继承有引用
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
都为引用
// 车 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)