JavaScript设计模式笔记(零)设计模式的原则

设计模式是设计于解决某些特定情况,但解决这些特定情况的设计,也需要遵循一定的原则

单一职责原则(SRP)


基本定义

单一职责原则体现在一个对象/方法只有一个职责,即只完成一件事,当我们要修改这个对象/方法时,只能是我们要对这件事的“做法”进行修改,而如果一个对象/方法有两个职责,那我们可能就有两个理由去修改这个对象/方法了。

目的

单一职责原则的目的在于减少耦合,方便我们对代码的修改,假设多个职责耦合在一个对象/方法内,当我们要修改一个职责时,很可能会影响到其他职责的正常实现。

设计模式中的单一职责原则

1.代理模式

代理模式将原对象要完成的另一件事委托给代理类完成,这样代理类和原对象可以保持只有一个职责,如果还有新的事件,也可以代理给新的对象。

2.装饰者模式

装饰者模式和代理模式类似,我们可以通过装饰链来将多个职责放在新添加的装饰对象上,这样也能保持每个对象只有一个职责。

单一职责的“单一”

单一职责的“单一”指的也不一定是非要只有一个职责,当我们确定两个职责是关联的时候,我们可以将这两个职责放在同一个对象/方法中,这样也可以减少对象的创建。

开放-封闭原则


基本定义

当需要改变一个程序的功能或者给这个程序增加新的功能的时候,可以使用增加代码的方式,但是不允许改动程序的源代码。

-----曾探的《JavaScript设计模式与开发实践》

消除条件分支语句

条件分支语句是违背开放-封闭原则的一个常见原因,诸如if-else,switch-case,当我们要增加新的条件时,总是会被迫去修改原函数,条件分支的违反情况如下代码(源自《JavaScript设计模式与开发实践》)

var makeSound = function(animal) {
    if (animal instanceof Duck) {
        console.log('嘎');
    } else if (animal instanceof Chicken) {
        console.log('咯');
    }
}

var Duck = function() {}
var Chicken = function() {}

makeSound(new Duck()); // 嘎
makeSound(new Chicken()); // 咯


// 添加狗的叫声,需要修改原来的代码
var makeSound = function(animal) {
    if (animal instanceof Duck) {
        console.log('嘎');
    } else if (animal instanceof Chicken) {
        console.log('咯');
    } else if (animal instanceof Dog) {
        console.log('汪');
    }
}

var Dog = function() {}

makeSound(new Dog()); // 汪

这里当我们添加一个Dog的叫声后,必须进入原来的函数中修改if-else语句才能达到我们要的结果,这显然违背了开放-封闭原则。

在这个例子中,我们要实现开放-封闭原则,首先要明确哪些是可变哪些是不可变的,将可变的部分作为参数传入,而不可变的部分封装在函数内部,这样当我们修改可变部分时就可以不修改函数内部的功能实现代码。

这里可变的是动物的种类,而且判断的种类也是可变的,因此此时我们传入的是一个对象,可以将功能放在对象的原型上,在方法内部调用传入对象的固定某个方法,而每个对象的方法又不一,这样就可以实现在不违法开放-封闭原则情况下增加功能。这正是对象的多态思想。

var Duck = function() {}
var Chicken = function() {}

Duck.prototype.makeSound = function() {
    console.log('嘎');
}

Chicken.prototype.makeSound = function() {
    console.log('咯');
}

var makeSound = function(animal) {
    animal.makeSound();
}

makeSound(new Duck()); // 嘎
makeSound(new Chicken()); // 咯

var Dog = function() {}

Dog.prototype.makeSound = function() {
    console.log('汪');
}

makeSound(new Dog()); // 汪

可以看到这里虽然添加了狗的叫声,但是我们对方法内部的代码没有进行任何修改。

总结上面的内容,我们可以看到,开放-封闭原则其实就是将可变的部分放在方法外修改,而将不可变的部分封装起来。

设计模式中的开放-封闭原则

事实上,几乎所有的设计模式都遵循开放-封闭原则,所以这里我们来提提这个原则在几个模式中的特别体现

1.发布-订阅模式

在发布-订阅模式中,订阅方向发布方发起订阅,当有新的订阅方订阅发布方时,此时不需要修改发布方也不需要修改之前的订阅方。

2.策略模式

在策略模式中每种策略都是独立的,新增一个策略不用修改之前的策略。

3.代理模式

通过代理将职责交给代理方完成,原对象的内容不用做修改。

4.职责链模式

职责链上每个节点的功能是独立的,即使往其上添加新的职责链节点,也不会修改之前的节点内容。

5.装饰者模式

装饰者模式在原对象的功能上新增新的对象而不修改原对象的内容,正好符合开放-封闭原则

相对的开放-封闭

正如《JavaScript设计模式与开发实践》里面所写的,

让程序保持完全封闭是不容易做到的,即使技术上做得到,也需要花费太多的时间和精力。

上面提到的符合开放-封闭原则的设计模式,也只是在其中的一部分符合开放-封闭原则,就如策略模式虽然新增一个策略不会修改之前的策略,但是策略方这个对象已经被修改是不争的事实,我们应该在可以不花过多时间和精力的条件下实现开放-封闭原则。

最少知识原则


基本定义

最少只是原则强调减少对象间的联系,所谓的知识,指的就是对其他对象的了解,而我们要尝试减少一个对象对其他对象的了解。

目的

最少知识原则的设置目的在于,当对象间的联系变多的话,我们修改其中一个对象,很可能会引起多个对象的变化,而这显然会引起我们维护的困难,我们无法轻易地修改其中一个对象,即使我们只是往对象中添加一行代码都可能会影响到其他多个对象。

模式中的最少知识原则

1.中介者模式

中介者模式可能是最能体现最少知识原则的一个模式了,中介者模式将多个对象和一个中介者进行联系,我们所需要维护的知识一个中介者和多个对象的关系,而多个对象之间的关系由中介者来管理,我们在修改其中某个对象时不用担心会影响到其他对象。

封装体现的最少知识原则

封装通过将部分内容隐藏起来,而只暴露一个接口与外界交流来实现,这样使得对象之间的联系得以缩小,体现了最少知识原则。

最少知识原则带来的弊端

事实上,没有哪个原则在每个设计中都能很好地体现,往往原则和设计模式都是在特定情况下实现的,而我们要自行判断在什么情况下使用什么设计模式和是否遵循原则,像上面的中介者模式,虽然减少了连接在中介者身上的对象之间的联系,但是我们需要对联系多个对象的中介者进行维护,当连接的对象多的时候,这就不是一个简单的工作了。


参考自曾探的《JavaScript设计模式与开发实践》

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值