48
48
> 近来,你发现人们对面向对象语言的继承进行批判。继承是有问题的 -- 在代码基中没有比基类与子类之间更深的耦合了 -- 但是我发现宽的继承树比深的要表现的更好。
49
49
50
50
# (沙盒)模式
51
- 一个__ 基类__ 定义了一个抽象的__ 沙盒方法__ 和一些__ 提供的操作__ 。通过设置他们为保护状态能够明确他们是被子类使用。每个继承的 __ 沙盒子类 __ 通过提供的操作来实现沙盒函数 。
51
+ 一个__ 基类__ 定义了一个抽象的__ 沙盒方法__ 和一些__ 提供的操作__ 。通过设置他们为保护状态来保证它们仅供子类使用。每个继承的 __ 沙盒子类 __ 针对父类提供的操作来实现沙盒函数 。
52
52
53
53
# 使用情境
54
- 沙盒模式是一种运用在大量代码基里甚至游戏之外的非常简单通用的模式 。如果你有一个非虚拟的保护函数,那么你很有可能正在使用类似该模式的东西 。沙盒模式在以下情况比较适用:
54
+ 沙盒模式是运用在多数代码库里甚至游戏之外的一种非常简单通用的模式 。如果你有一个非虚拟的保护函数,那么你很有可能正在使用与之相类似的模式 。沙盒模式在以下情况比较适用:
55
55
56
56
- 你有一个带有大量子类的基类。
57
57
58
- - 基类能够提供一个子类需要执行的所有操作 。
58
+ - 基类能够提供所有子类可能需要执行的操作集合 。
59
59
60
- - 在子类之间有重叠的代码,你想让他们之间更容易地分享代码 。
60
+ - 在子类之间有重叠的代码,你想让它们之间更容易地共享代码 。
61
61
62
62
- 你想使这些继承类与程序的其他代码之间的耦合最小化。
63
63
64
64
#使用须知
65
- “继承”一词最近在一些程序圈子里被视为诟病 ,其中一个原因是基类会滋生越来越多的代码。这个模式尤其受这个因素的影响。
65
+ “继承”一词在近代的一些程序圈子里被诟病 ,其中一个原因是基类会滋生越来越多的代码。这个模式尤其受这个因素的影响。
66
66
67
- 由于子类是通过它们的基类来实现剩下的游戏,基类最终会与所有子类需要交互的系统产生耦合 。当然,这些子类也与他们的基类绑定。这个蜘蛛网式的耦合使得在不破坏什么的情况下改变基类是很困难的 -- 你遇到了[ 脆弱的基类问题] ( http://en.wikipedia.org/wiki/Fragile_base_class ) 。
67
+ 由于子类是通过它们的基类来实现剩下的游戏,基类最终会与那些需要与其子类交互的系统产生耦合 。当然,这些子类也与他们的基类绑定。这个蜘蛛网式的耦合使得无损地改变基类是很困难的 -- 你遇到了[ 脆弱的基类问题] ( http://en.wikipedia.org/wiki/Fragile_base_class ) 。
68
68
69
- 从另一个角度来说你所有的耦合都被聚集到了基类, 子类现在明显地与其他世界更加独立了。理想状态下,你的绝大部分操作都在子类中。这意味着你的大量的代码基是独立的 ,并且更易于维护。
69
+ 而从好的角度来说,你所有的耦合都被聚集到了基类, 子类现在明显地与其他世界更加独立了。理想状态下,你的绝大部分操作都在子类中。这意味着你的大量的代码库是独立的 ,并且更易于维护。
70
70
71
- 如果你仍然发现这个模式正把你的基类推向一碗巨大的代码汤里的话 ,请考虑把一些提供的操作提取到一个基类能够管理的独立的类中。这里[ 组件模式] ( ./05.1-Component.md ) 能够有所帮助。
71
+ 如果你仍然发现这个模式正把你的基类浸入一大锅代码种时 ,请考虑把一些提供的操作提取到一个基类能够管理的独立的类中。这里[ 组件模式] ( ./05.1-Component.md ) 能够有所帮助。
72
72
73
73
#示例
74
- 由于这是一个如此简单的设计模式,并没有多少的示例代码。这不意味着这没有用 -- 这个模式的实现关乎的是其意义而不是其复杂度。
74
+ 由于这是一个如此简单的设计模式,并没有多少的示例代码。这不意味着它没有用 -- 这个模式的实现关乎的是其意义而不是其复杂度。
75
75
76
- 我们将从我们得Superpower基类开始 :
76
+ 我们将从我们的 ` Superpower ` 基类开始 :
77
77
``` c++
78
78
class Superpower
79
79
{
@@ -99,13 +99,13 @@ protected:
99
99
}
100
100
};
101
101
```
102
- 函数activate() 就是沙盒函数。由于它是虚拟和抽象的,子类必须要覆盖它。这对于需要创建一个力量子类而使工作正常进行的人们来说是清晰地 。
102
+ 函数 ` activate() ` 就是沙盒函数。由于它是虚拟和抽象的,子类必须要覆盖它。这是为了让子类使用者能够明确他们该对自己的特殊力量子类做些什么 。
103
103
104
- 另外的保护函数move(), playSound()和spawnParticles() 都是提供的操作。这些就是子类需要在activate() 函数实现时将调用的函数。
104
+ 另外的保护函数 ` move() ` , ` playSound() ` 和 ` spawnParticles() ` 都是提供的操作。这些就是子类需要在 ` activate() ` 函数实现时将调用的函数。
105
105
106
- 我们没有在这个示例中实现提供的操作,但是一个实际的游戏需要有真实的代码在那儿。这个函数是Superpower在游戏中与其他系统耦合的函数 -- move()函数也许会调用物理引擎代码,playSound()将与音效引擎通讯等等。由于所有的这些都是在基类的实现中,这就使得所有的耦合都封装在Superpower自己中 。
106
+ 我们没有在这个示例中实现提供的操作,但是一个实际的游戏需要有真实的代码在那儿。这个函数是 ` Superpower ` 在游戏中与其他系统耦合的地方 -- ` move() ` 函数也许会调用物理引擎代码,` playSound() ` 将与音效引擎通讯等等。由于所有的这些都是在基类的实现中,这就使得所有的耦合都封装在 ` Superpower ` 自己中 。
107
107
108
- 好啦,现在让我们放出我们的放射性蜘蛛并创建一个力量 。这就有一个:
108
+ 好啦,现在让我们放出放射性蜘蛛并创建一个力量 。这就有一个:
109
109
``` c++
110
110
class SkyLaunch : public Superpower
111
111
{
@@ -121,9 +121,9 @@ protected:
121
121
```
122
122
> 注解
123
123
124
- > 好啦,也许能够跳跃并不是力量的所有,但是这里我尝试保持事情简单 。
124
+ > 好啦,也许能够跳跃并不足以算是超能力,但是这里我尝试保持事情基础化 。
125
125
126
- 这个力量把超级英雄弹向空中,播放一段恰当的音效并踢开一缕拂尘。如果所有的超级力量都如此简单 -- 仅仅是音效,粒子效果和动作的组合,那么我们就不再需要这个模式了。反而,Superpower可以有一个activate()的烘烤的实现,这个activate() 是访问音效ID,粒子类型和移动的部分。但是这个在仅当所有的力量基本上以同样的方式来工作仅仅在数据上有一些差异的地方才有效。让我们更详细的看一下:
126
+ 这个力量把超级英雄弹向空中,播放一段恰当的音效并踢开一缕拂尘。如果所有的超级力量都如此简单 -- 仅仅是音效,粒子效果和动作的组合,那么我们就不再需要这个模式了。反而,` Superpower ` 可以自带一个 ` activate() ` 的实现,这个 ` activate() ` 是访问音效ID,粒子类型和移动的部分。但是这个在仅当所有的力量基本上以同样的方式来工作仅仅在数据上有一些差异的地方才有效。让我们更详细的看一下:
127
127
``` c++
128
128
class Superpower
129
129
{
@@ -146,7 +146,7 @@ protected:
146
146
// Existing stuff...
147
147
};
148
148
```
149
- 这里我们添加了一个方法用于获取英雄的位置。我们的SkyLaunch子类现在可以使用这些 :
149
+ 这里我们添加了一个方法用于获取英雄的位置。我们的 ` SkyLaunch ` 子类现在可以使用这些 :
150
150
``` c++
151
151
class SkyLaunch : public Superpower
152
152
{
@@ -176,7 +176,7 @@ protected:
176
176
}
177
177
};
178
178
```
179
- 由于我们可以使用一些状态,现在我们的沙盒函数可以做一些实际的有趣的控制流。这里仍然仅仅是一些简单的if语句,但是你可以做任何你想做的事情。通过使沙盒函数成为一个包含任意代码的切实丰富的函数,天空将无极限 。
179
+ 由于我们可以使用一些状态,现在我们的沙盒函数可以做一些实际的有趣的控制流。这里仍然仅仅是一些简单的if语句,但是你可以做任何你想做的事情。通过使沙盒函数成为一个包含任意代码的切实丰富的函数,将具备无限的潜力 。
180
180
181
181
> 注解
182
182
0 commit comments