设计原则与设计模式

发布于 / 学习

设计原则

什么是设计

描述

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

UNIX/LINUX设计哲学

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

SOLID 五大设计原则

  • S-单一职责原则
  • O-开放封闭原则(拓展开放,修改封闭)
  • L-李氏置换原则
  • I-接口独立原则
  • D-依赖导致原则(依赖抽象而不是依赖实现)

单一职责原则

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

开放封闭原则

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

李氏置换原则

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

接口独立原则

  • 八婆吃接口的单一独立,避免出现‘胖接口’
  • js中没有接口(ts除外),使用较少
  • 类似于单一职责原则,这里更关注与接口

依赖倒置原则

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

设计原则总结

  • SO体现较多,详细介绍
  • LID体现较少,但是要了解其中的意思
    //用promise说明SO
   function loadImg(src) {
        var promise = new Promise(function (resolve, reject) {
            var img = document.createElement('img')
            img.onload = function () {
                resolve(img)
            }
            img.onerror = function () {
                reject('图片加载失败')
            }
            img.src = src
        })
        return promise
    }

    var imgSrc = 'https://static.ahwgs.cn/wp-content/uploads/2018/12/XQXT_RUDC1YB0FUW.png';
    var result = loadImg(imgSrc)

    result
        .then(function (img) {
            console.log('img width',img.width)
            return img
        })
        .then(function (img) {
            console.log('img height',img.height)
        })
        .catch(function (err) {
            console.log(err);
        })
  • 坚持单一职责原则,每一个then只做一件事
  • 开放封闭原则,如果有新功能,增加then即可。

设计模式

  • 创建型
  • 组合型
  • 行为型

创建型

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

结构型

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

行为型

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

关于设计模式的面试题

  • 题1:打车时,可以打专车或者快车。任何车都有车牌号和名称。不同的车价格不同,快车每公里1元,专车每公里2元。行程开始时显示车辆信息,行程结束时,显示打车金额(5)公里。要求画出UML类图与用es6语法表示出来。

image

    //Car 父类
    class Car {
        constructor(number, name) {
            this.name = name;  //车信息
            this.number = number;  //车牌号
        }
    }

    //专车类
    class Zhuanche extends Car {
        constructor(number, name) {
            super(number, name);
            this.price = 2
        }
    }

    //快车类
    class Kuaiche extends Car {
        constructor(number, name) {
            super(number, name);
            this.price = 1
        }
    }

    //行程类
    class Trip {
        constructor(car){
            this.car = car
        }
        //显示车牌信息
        start(){
            console.log('行程开始.名称:'+this.car.name+',车牌号:'+this.car.number)
        }
        end(){
            console.log('行程结束.总计:'+this.car.price * 5)
        }
    }

    var car = new Kuaiche('皖A000001','大奔')
    var trip = new Trip(car);

    trip.start()
    trip.end()
  • 题2:某停车场,分3层,每层100车位,每个车位都能监控到车辆的驶入和离开。车辆进入前,显示每层的空余车位数量,车辆进入时摄像头可识别车牌号和时间。车辆出来时,出口显示器显示车牌号和停车时长。

image

// 车
    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)

代码:https://github.com/ahwgs/design-pattern-learning/tree/master/2.%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99

本文采用 CC BY-NC-SA 3.0 Unported 协议进行许可
本文链接: https://www.ahwgs.cn/shejiyuanzeyushejimoshi.html