# JavaScript 中的设计模式
# 前言
设计模式,往往是软件设计中的最佳实践,是前人对问题的解决经验的总结。我认为学习并理解设计模式,对自己的程序设计,软件开发有很大帮助,同时也可以扩展自己开发设计的思维。我是后来才明白,所有编程语言,都有设计模式这一说法,读《JavaScript 中的设计模式》这本书,给了我很大启发。
# 关于 ES6 的继承:
子类必须在 constructor
方法中调用 super
方法,否则新建实例时会报错。这是因为子类没有自己的 this
对象,而是继承父类的 this
对象,然后对其进行加工。如果不调用 super
方法,子类就得不到 this
对象。
ES5 的继承,实质是先创造子类的实例对象 this
,然后再将父类的方法添加到 this
上面( Parent.apply(this)
)。
ES6 的继承机制完全不同,实质是先创造父类的实例对象 this
(所以必须先调用 super
方法),然后再用子类的构造函数修改 this
。
如果子类没有定义 constructor
方法,这个方法会被默认添加,代码如下。也就是说,不管有没有显式定义,任何一个子类都有 constructor
方法。
1 2 3 4 5 6 7 8 9
| class ColorPoint extends Point { }
class ColorPoint extends Point { constructor(...args) { super(...args); } }
|
# 设计模式的六大原则
- 单一职责原则(Single Responsibility Principle);
- 开闭原则(Open Closed Principle);
- 里氏替换原则(Liskov Substitution Principle);
- 迪米特法则(Law of Demeter),又叫 “最少知道法则”;
- 接口隔离原则(Interface Segregation Principle);
- 依赖倒置原则(Dependence Inversion Principle)。
# 创造型设计模式(5)
# 1. 工厂模式
工厂模式是比较常用的设计模式之一,那么什么叫模式呢?简单来说,就是你需要什么东西,不直接使用 new 的方法生成实例,而是通过工厂加工再生成实例。
比如我们现在需要生产三种形状,分别为:圆形,正方形,三角形。我们可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Circle { draw = () => { console.log("画了一个圆形"); }; } class Triangle { draw = () => { console.log("画了一个三角形"); }; } class Square { draw = () => { console.log("画了一个正方形"); }; } const myCircle = new Circle(); myCircle.draw();
|
但是这样的话,每次我需要一个圆形,都要自己 new 一个 Circle,如果需要其他形状,又要 new 一个其他的构造类,下面我们来建一个工厂,负责生产不同的形状。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class shapeFactory { getShape(shapeType) { switch (shapeType) { case "Circle": { return new Circle(); } case "Triangle": { return new Triangle(); } case "Square": { return new Square(); } } } } const shapefactory = new shapeFactory(); const myCircle = shapefactory.getShape("Circle"); const myTriangle = shapefactory.getShape("Triangle"); myCircle.draw() myTriangle.draw()
|
工厂模式的优势:使用工厂模式的好处也是显而易见的,比如实例的生产比较复杂,或者说生成实例后还需要额外加工,这个时候工厂给了我们一个统一的出入口,也方便了日后对这个实例的修改。比如你要修改产出是一个单例的时候,就不需要在所有类中修改,而只需要在工厂出口修改即可。
# 2. 抽象工厂模式
抽象工厂?这名字确实挺抽象,因为一般来讲一个工厂只负责加工一个组件,而你的产品需要很多组件合成组装,因此你需要很多生产不同组件的工厂,那么如何管理这些工厂呢,那就用生产工厂的工厂!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| class Circle { draw = () => { console.log("画了一个圆形"); }; } class Triangle { draw = () => { console.log("画了一个三角形"); }; } class Square { draw = () => { console.log("画了一个正方形"); }; } class Blue { fill = () => { console.log("填充蓝色") } } class Red { fill = () => { console.log("填充红色") } } class Yellow { fill = () => { console.log("填充黄色") } }
class ShapeFactory { getShape(shapeType) { switch (shapeType) { case "Circle": { return new Circle(); } case "Triangle": { return new Triangle(); } case "Square": { return new Square(); } } } }
class ColorFactory { getColor(colorType) { switch (colorType) { case 'Blue':{ return new Blue(); } case 'Green':{ return new Green(); } case 'Yellow':{ return new Yellow(); } } } } class FatherFactory { getFactory(choice) { switch (choice) { case 'Color':{ return new ColorFactory(); } case 'Shape':{ return new ShapeFactory(); } } } } const fatherfactory = new FatherFactory() const colorfactory = fatherfactory.getFactory('Color') const shapefactory = fatherfactory.getFactory('Shape')
const myCircle = shapefactory.getShape('Circle') myCircle.draw() const blue = colorfactory.getColor('Blue') blue.fill();
|
说说好处:和工厂模式类似,抽象工厂模式方便了对各种工厂的管理。
# 3. 单例模式
顾名思义,单例模式就是每个实例只生产一次。单例模式又分为两种,一种叫懒汉式,一种叫饿汉式。区别在于,懒汉式是使用的时候才初始化,饿汉式是先初始化,需要用的时候直接给。
值得注意的是懒汉式写法在 java 中可能会对线程安全有影响,但是 JS 是单线程的,不需要考虑线程安全哈哈哈,所以优先考虑懒汉式。
TODO…
# 结构型设计模式(8)
# 行为型设计模式(12)