Skip to content

Commit 782e546

Browse files
m.lm.l
m.l
authored and
m.l
committed
适配器模式大部分段落更新
1 parent 36c2ba6 commit 782e546

File tree

1 file changed

+54
-8
lines changed

1 file changed

+54
-8
lines changed

第四章-适配器模式.md

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Python的包Traits也为了把一个对象进行转换,而又不为这个对
4141
The Adapter pattern is used for making things work after they have been implemented [j.mp/adapterpat]. Usually one of the two incompatible interfaces is either foreign or old/legacy. If the interface is foreign, it means that we have no access to the source code. If it is old it is usually impractical to refactor it. We can take it even further and argue that altering the implementation of a legacy component to meet our needs is not only impractical, but it also violates the open/close principle [j.mp/adaptsimp]. The open/close principle is one of the fundamental principles of Object-Oriented design (the O of SOLID). It states that a software entity should
4242
be open for extension, but closed for modi cation. That basically means that we should be able to extend the behavior of an entity without making source code modi cations. Adapter respects the open/closed principle [j.mp/openclosedp].
4343

44-
适配器模式
44+
适配器模式在实现之后用来让事务工作起来。通常两个不兼容的接口中的其中一个不是外部的,就是老旧的。如果接口是外部的,这意味着我们不能访问源代码。如果是旧的话,一般不实际的做法是重构它。我们进一步来探讨改变旧代码组建的实现来实现我们的需求不仅仅是不切实际的,而且这还违反了开发/关闭原则。开发/关闭原则是面向对象设计的一个基础原则。它声明了,软件对象应该为扩展而开发,且对修改进行关闭。这基本就是说,我们应该能够扩展一个对象的行为,而不用对源代码进行修改。适配器同样遵守开发/关闭原则。
4545

4646
Therefore, using an Adapter for making things work after they have been implemented is a better approach because it:
4747

@@ -56,11 +56,11 @@ Therefore, using an Adapter for making things work after they have been implemen
5656
## Implementation 实现
5757
There are many ways of implementing the Adapter design pattern in Python [Eckel08, page 207]. All the techniques demonstrated by Bruce Eckel use inheritance, but Python provides an alternative, and in my opinion, a more idiomatic way of implementing an Adapter. The alternative technique should be familiar to you, since it uses the internal dictionary of a class, and we have seen how to do that in Chapter 3, The Prototype Pattern.
5858

59-
在Python中有很多实现适配器模式的方法。所有的技术都由布鲁斯-埃寇使用继承来阐明,但是Python提供了一个选择,在我看来是一种更为理想的实现适配器的办法。
59+
在Python中有很多实现适配器模式的方法。所有的技术都由布鲁斯-埃寇使用继承来阐明,但是Python提供了一个选择,在我看来是一种更为理想的实现适配器的办法。另外一种技术你应该是熟悉的,因此它使用的是类的内部字典,而且在第三章-原型模式中,我们已经见过如何具体操作了。
6060

6161
Let's begin with the what we have part. Our application has a Computer class that shows basic information about a computer. All the classes of this example, including the Computer class are very primitive, because we want to focus on the Adapter pattern and not on how to make a class as complete as possible.
6262

63-
我们从自己所实现的部分开始。我们的应用拥有一个展示电脑基本信息的Computer类。该例子的所有类,
63+
我们从自己所实现的部分开始。我们的应用拥有一个展示电脑基本信息的Computer类。该例子的所有类,包括Computer类在内都非常的简陋,因为我们想关注在适配模式上,而不是如何将一个类尽可能的编写完整。
6464

6565
```python
6666
class Computer:
@@ -78,38 +78,49 @@ In this case, the execute() method is the main action that the computer can perf
7878

7979
Now we move to the what we want part. We decide to enrich our application with more functionality, and luckily, we nd two interesting classes implemented in two different libraries that are unrelated with our application: Synthesizer and Human. In the Synthesizer class, the main action is performed by the play() method. In the Human class, it is performed by the speak() method. To indicate that the two classes are external, we place them in a separate module, as shown:
8080

81-
现在,进入我们我们想要使用的代码。我们决定使用更多的功能扩展我们的应用,幸运的是,我们
81+
现在,进入我们我们想要使用的代码。我们决定使用更多的功能扩展我们的应用,幸运的是,我们找到了两个有趣的使用不同和我们的应用无关的库实现的类:Synthesizer 和 Human。在Synthesizer,主要的行为是由play()方法执行的。在Human类中,主要是由speak()执行的。为了表明这两个类是来自外部的,我们把它放到一个独立的模块中,一如下所示:
8282

8383
```python
8484
class Synthesizer:
8585
def __init__(self, name):
8686
self.name = name
87+
8788
def __str__(self):
8889
return 'the {} synthesizer'.format(self.name)
90+
8991
def play(self):
9092
return 'is playing an electronic song'
93+
94+
9195
class Human:
9296
def __init__(self, name):
9397
self.name = name
98+
9499
def __str__(self):
95100
return '{} the human'.format(self.name)
101+
96102
def speak(self):
97103
return 'says hello'
98104
```
99105

100-
So far so good. But, we have a problem. The client only knows how to call the execute() method, and it has no idea about play() or speak(). How can we make the code work without changing the Synthesizer and Human classes? Adapters to the rescue! We create a generic Adapter class that allows us to adapt a number of objects with different interfaces, into one uni ed interface. The obj argument of the __init__() method is the object that we want to adapt, and adapted_methods is a dictionary containing key/value pairs of method the client calls/method that should be called.
106+
So far so good. But, we have a problem. The client only knows how to call the execute() method, and it has no idea about play() or speak(). How can we make the code work without changing the Synthesizer and Human classes? Adapters to the rescue! We create a generic Adapter class that allows us to adapt a number of objects with different interfaces, into one uni ed interface. The obj argument of the `__init__()` method is the object that we want to adapt, and adapted_methods is a dictionary containing key/value pairs of method the client calls/method that should be called.
107+
108+
到目前为止还好。但是,我们有一个问题。用户仅知道如何调用execute()方法,而不知道如何使用play()或者speak()。我们如何让代码工作而又不改变类Synthesizer和Human?适配器就是拯救这个问题的!我们创建一个允许我们让不同的接口的多个对象适配到一个统一的接口的通用适配器类。`__init__()`的obj参数是我们想要去适配的对象,而adapted_methods则是一个包含
101109

102110
```python
103111
class Adapter:
104112
def __init__(self, obj, adapted_methods):
105113
self.obj = obj
106114
self.__dict__.update(adapted_methods)
115+
107116
def __str__(self):
108117
return str(self.obj)
109118
```
110119

111120
Let's see how we can use the Adapter pattern. An objects list holds all the objects. The compatible objects that belong to the Computer class need no adaptation. We can add them directly to the list. The incompatible objects are not added directly. They are adapted using the Adapter class. The result is that the client code can continue using the known execute() method on all objects without the need to be aware of any interface differences between the used classes.
112121

122+
让我们来看看如何使用适配器模式。一个对象列表拥有多个对象。属于Computer类的合适对象不需要去适配。我们直接把它们加入到列表。不合适的对象不会直接添加。它们要使用Adapter类进行适配。其结果是客户端代码可以继续在所有对象上使用 execute() 方法,而不需要关心所使用类之间任何接口上的不同。
123+
113124
```python
114125
def main():
115126
objects = [Computer('Asus')]
@@ -121,38 +132,56 @@ Let's see how we can use the Adapter pattern. An objects list holds all the obje
121132
print('{} {}'.format(str(i), i.execute()))
122133
```
123134

124-
Let's see the complete code of the Adapter pattern example ( les external.py and adapter.py) as follows:
135+
Let's see the complete code of the Adapter pattern example (files external.py and adapter.py) as follows:
136+
137+
如下,让我们看看适配器模式例子的完整代码文件(文件external.py和adapter.py):
125138

126139
```python
127140
class Synthesizer:
128141
def __init__(self, name):
129142
self.name = name
143+
130144
def __str__(self):
131145
return 'the {} synthesizer'.format(self.name)
146+
132147
def play(self):
133148
return 'is playing an electronic song'
149+
150+
134151
class Human:
135152
def __init__(self, name):
136153
self.name = name
154+
137155
def __str__(self):
138156
return '{} the human'.format(self.name)
157+
139158
def speak(self):
140159
return 'says hello'
160+
161+
141162
from external import Synthesizer, Human
163+
164+
142165
class Computer:
143166
def __init__(self, name):
144-
self.name = name
167+
self.name = name
145168

146169
def __str__(self):
147170
return 'the {} computer'.format(self.name)
171+
148172
def execute(self):
149173
return 'executes a program'
174+
175+
150176
class Adapter:
151177
def __init__(self, obj, adapted_methods):
152178
self.obj = obj
153179
self.__dict__.update(adapted_methods)
180+
154181
def __str__(self):
155182
return str(self.obj)
183+
184+
156185
def main():
157186
objects = [Computer('Asus')]
158187
synth = Synthesizer('moog')
@@ -161,12 +190,16 @@ Let's see the complete code of the Adapter pattern example ( les external.py and
161190
objects.append(Adapter(human, dict(execute=human.speak)))
162191
for i in objects:
163192
print('{} {}'.format(str(i), i.execute()))
193+
194+
164195
if __name__ == "__main__":
165196
main()
166197
```
167198

168199
The output when executing the example is:
169200

201+
执行这个例子输出结果是:
202+
170203
```shell
171204
>>> python3 adapter.py
172205
the Asus computer executes a program
@@ -177,24 +210,37 @@ Bob the human says hello
177210
We managed to make the Human and Synthesizer classes compatible with the interface expected by the client, without changing their source code. This is nice.
178211
Here's a challenging exercise for you. There is a problem with this implementation. While all classes have a name attribute, the following code fails:
179212

213+
我们希望由用户来管理
214+
180215
```python
181216
for i in objects:
182217
print(i.name)
183218
```
184219

185220
First of all, why does this code fail? Although this makes sense from a coding point of view, it does not make sense at all for the client code which should not be aware of details such as what is adapted and what is not adapted. We just want to provide a uniform interface. How can we make this code work?
186221

222+
首先要说的是,这个代码为何会运行失败呢?
223+
187224
>### Tip
188225
>Hint: Think of how you can delegate the non-adapted parts to the object contained in the Adapter class.
189226
227+
>### 提示
228+
>想一想你该如何对包含在Adapter类中对象分配不适配的部分。
229+
190230
## Summary 总结
191231
This chapter covered the Adapter design pattern. We use the Adapter pattern for making two (or more) incompatible interfaces compatible. As a motivation, an e-commerce system that should support multiple currencies was mentioned.
192232
We use adapters every day for interconnecting devices, charging them, and so on.
193233

234+
本章讨论了适配器设计模式。我们使用适配器让两个(或者更多个)不兼容的接口变得兼容。从出发动机而言,一个电商系统应该支持早前提到的多种货币。我们每天都在使用适配器,比如为相互连接的设备进行充电,等等。
235+
194236
Adapter makes things work after they have been implemented. The Grok Python framework and the Traits package use the Adapter pattern for achieving API conformance and interface compatibility, respectively. The open/close principle is strongly connected with these aspects.
195237

238+
适配器在被实现后才可以让事务工作起来。Python框架Grok,和Traits包分别利用适配器模式实现API一致,和接口上的兼容性。
239+
196240
In the implementation section, we saw how to achieve interface conformance using the Adapter pattern without modifying the source code of the incompatible model. This is achieved through a generic Adapter class that does the work for us. Although we could use sub-classing (inheritance) to implement the Adapter pattern in the traditional way in Python, this technique is a great alternative.
197241

198-
In the next chapter, we will see how we can use the Decorator pattern to extend the behavior of an object without using sub-classing.
242+
在实现部分,我们见到了如何使用适配器模式实现接口一致,而不修改不兼容模型的源码。
199243

244+
In the next chapter, we will see how we can use the Decorator pattern to extend the behavior of an object without using sub-classing.
200245

246+
在下面的章节中,我们会看到如何使用装饰器模式扩展一个对象的行为,而不使用子类化。

0 commit comments

Comments
 (0)