Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7710067

Browse filesBrowse files
装饰器模式
1 parent 0b40ce8 commit 7710067
Copy full SHA for 7710067

18 files changed

+310-256Lines changed: 310 additions & 256 deletions
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎06-设计模式/0 我的总结.md‎

Copy file name to clipboardExpand all lines: 06-设计模式/0 我的总结.md
+16-1Lines changed: 16 additions & 1 deletion
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,19 @@
55

66
职责链模式 vs 模板方法模式
77
职责链目的在于找到合适的处理方法
8-
模板方法模式在于执行一系列方法
8+
模板方法模式在于执行一系列方法
9+
10+
11+
装饰者模式和代理模式的结构看起来非常相像,两种模式都描述了怎样为对象提供一定程度上的间接引用,它们的实现部分都保留了对另外一个对象的引用,并且向那个对象发送请求。
12+
目的不同:
13+
1. 代理模式的目的是,当直接访问本体不方便或者不符合需要时,为这个本体提供一个替代者。
14+
本体定义了关键功能,而代理提供或拒绝对它的访问,或者在访问本体之前做一些额外的事情。
15+
2. 装饰者模式的作用就是为对象动态加入行为。
16+
换句话说,代理模式强调一种关系(Proxy 与它的实体之间的关系),这种关系可以静态的表达,也就是说,这种关系在一开始就可以被确定。
17+
而装饰者模式用于一开始不能确定对象的全部功能时。
18+
代理模式通常只有一层 代理 - 本体 的引用,而装饰者模式经常会形成一条长长的装饰链。
19+
20+
在虚拟代理实现图片预加载的例子中,本体负责设置 img 节点的 src,代理则提供了预加载
21+
的功能,这看起来也是“加入行为”的一种方式,但这种加入行为的方式和装饰者模式的偏重点
22+
是不一样的。装饰者模式是实实在在的为对象增加新的职责和行为,而代理做的事情还是跟本体
23+
一样,最终都是设置 src。但代理可以加入一些“聪明”的功能,比如在图片真正加载好之前,先使用一张占位的 loadin 图片反馈给
Collapse file
+46Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
在传统的面向对象语言中,给对象添加功能常常使用继承的方式,但是继承的方式并不灵活,还会带来许多问题:
2+
1. 一方面会导致超类和子类之间存在强耦合性,当超类改变时,子类也会随之改变;
3+
2. 另一方面,继承这种功能复用方式通常被称为“白箱复用”,“白箱”是相对可见性而言的,在继承方式中,超类的内部细节是对子类可见的,继承常常被认为破坏了封装性。
4+
3. 使用继承还会带来另外一个问题,在完成一些功能复用的同时,有可能创建出大量的子类,使子类的数量呈爆炸性增长。比如现在有 4 种型号的自行车,我们为每种自行车都定义了一个单独的类。
5+
现在要给每种自行车都装上前灯、尾灯和铃铛这 3 种配件。如果使用继承的方式来给每种自行车创建子类,则需要 4×3 = 12 个子类。
6+
但是如果把前灯、尾灯、铃铛这些对象动态组合到自行车上面,则只需要额外增加 3 个子类。
7+
8+
这种给对象动态地增加职责的方式称为装饰者(decorator)模式。
9+
装饰者模式能够在不改变对象自身的基础上,在程序运行期间给对象动态地添加职责。
10+
跟继承相比,装饰者是一种更轻便灵活的做法,这是一种“即用即付”的方式。
11+
12+
装饰者对象和它所装饰的对象拥有一致的接口,所以它们对使用该对象的客户来说是透明的,
13+
被装饰的对象也并不需要了解它曾经被装饰过,这种透明性使得我们可以递归地嵌套任意多个装饰者对象
14+
15+
从功能上而言,decorator 能很好地描述这个模式,但从结构上看,wrapper 的说法更加贴切。
16+
装饰者模式将一个对象嵌入另一个对象之中,实际上相当于这个对象被另一个对象包装起来,形成一条包装链。
17+
请求随着这条链依次传递到所有的对象,每个对象都有处理这条请求的机会,
18+
<script>
19+
// plane
20+
var Plane = function(){}
21+
Plane.prototype.fire = function(){
22+
console.log( '发射普通子弹' );
23+
}
24+
// 增加装饰类: 导弹
25+
var MissileDecorator = function( plane ){
26+
this.plane = plane;
27+
}
28+
MissileDecorator.prototype.fire = function(){
29+
this.plane.fire();
30+
console.log( '发射导弹' );
31+
}
32+
// 增加装饰类: 原子弹
33+
var AtomDecorator = function( plane ){
34+
this.plane = plane;
35+
}
36+
AtomDecorator.prototype.fire = function(){
37+
this.plane.fire();
38+
console.log( '发射原子弹' );
39+
}
40+
41+
var plane = new Plane();
42+
plane = new MissileDecorator( plane );
43+
plane = new AtomDecorator( plane );
44+
plane.fire();
45+
// 分别输出: 发射普通子弹、发射导弹、发射原子弹
46+
</script>
Collapse file
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
要想为函数添加一些功能,最简单粗暴的方式就是直接改写该函数
2+
但这是最差的办法,直接违反了开放封闭原则
3+
<script>
4+
// plane
5+
var plane = {
6+
fire: function(){
7+
console.log( '发射普通子弹' );
8+
}
9+
}
10+
// 待装饰的方法函数
11+
var missileDecorator = function(){
12+
console.log( '发射导弹' );
13+
}
14+
var atomDecorator = function(){
15+
console.log( '发射原子弹' );
16+
}
17+
// (装饰1)取得备份原来的待装饰方法并改写
18+
var fire1 = plane.fire;
19+
plane.fire = function(){ // 改写
20+
fire1();
21+
missileDecorator();
22+
}
23+
// (装饰2)取得备份原来的待装饰方法并改写
24+
var fire2 = plane.fire;
25+
plane.fire = function(){ // 改写
26+
fire2();
27+
atomDecorator();
28+
}
29+
30+
// 分别输出: 发射普通子弹、发射导弹、发射原子弹
31+
plane.fire();
32+
</script>

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.