@@ -1043,8 +1043,144 @@ Bisection.algorithm
10431043每一个 `Algorithm ` 接口的实现,都实现了不同的 `algorithm()` 方法。在 `FindMinama ` 中,将会创建一个算法的列表(这就是所谓的“链”),而 `minima()` 方法只是遍历这个列表,然后找到能够成功执行的算法而已。
10441044
10451045< ! -- Changing the Interface -- >
1046- ## 接口改变
1046+ ## 改变接口
10471047
1048+ 有时候我们需要解决的问题很简单,仅仅是“我没有需要的接口”而已。有两种设计模式用来解决这个问题:* 适配器模式* 接受一种类型并且提供一个对其他类型的接口。* 外观模式* 为一组类创建了一个接口,这样做只是为了提供一种更方便的方法来处理库或资源。
1049+
1050+ ### 适配器模式(Adapter )
1051+
1052+ 当我们手头有某个类,而我们需要的却是另外一个类,我们就可以通过 * 适配器模式* 来解决问题。唯一需要做的就是产生出我们需要的那个类,有许多种方法可以完成这种适配。
1053+
1054+ ```java
1055+ // patterns/adapt/Adapter.java
1056+ // Variations on the Adapter pattern
1057+ // {java patterns.adapt.Adapter}
1058+ package patterns. adapt;
1059+
1060+ class WhatIHave {
1061+ public void g () {}
1062+ public void h () {}
1063+ }
1064+
1065+ interface WhatIWant {
1066+ void f ();
1067+ }
1068+
1069+ class ProxyAdapter implements WhatIWant {
1070+ WhatIHave whatIHave;
1071+ ProxyAdapter (WhatIHave wih ) {
1072+ whatIHave = wih;
1073+ }
1074+ @Override
1075+ public void f () {
1076+ // Implement behavior using
1077+ // methods in WhatIHave:
1078+ whatIHave. g();
1079+ whatIHave. h();
1080+ }
1081+ }
1082+
1083+ class WhatIUse {
1084+ public void op (WhatIWant wiw ) {
1085+ wiw. f();
1086+ }
1087+ }
1088+
1089+ // Approach 2: build adapter use into op():
1090+ class WhatIUse2 extends WhatIUse {
1091+ public void op (WhatIHave wih ) {
1092+ new ProxyAdapter (wih).f ();
1093+ }
1094+ }
1095+
1096+ // Approach 3: build adapter into WhatIHave:
1097+ class WhatIHave2 extends WhatIHave implements WhatIWant {
1098+ @Override
1099+ public void f () {
1100+ g();
1101+ h();
1102+ }
1103+ }
1104+
1105+ // Approach 4: use an inner class:
1106+ class WhatIHave3 extends WhatIHave {
1107+ private class InnerAdapter implements WhatIWant {
1108+ @Override
1109+ public void f () {
1110+ g();
1111+ h();
1112+ }
1113+ }
1114+ public WhatIWant whatIWant () {
1115+ return new InnerAdapter ();
1116+ }
1117+ }
1118+
1119+ public class Adapter {
1120+ public static void main (String [] args ) {
1121+ WhatIUse whatIUse = new WhatIUse ();
1122+ WhatIHave whatIHave = new WhatIHave ();
1123+ WhatIWant adapt= new ProxyAdapter (whatIHave);
1124+ whatIUse. op(adapt);
1125+ // Approach 2:
1126+ WhatIUse2 whatIUse2 = new WhatIUse2 ();
1127+ whatIUse2. op(whatIHave);
1128+ // Approach 3:
1129+ WhatIHave2 whatIHave2 = new WhatIHave2 ();
1130+ whatIUse. op(whatIHave2);
1131+ // Approach 4:
1132+ WhatIHave3 whatIHave3 = new WhatIHave3 ();
1133+ whatIUse. op(whatIHave3. whatIWant());
1134+ }
1135+ }
1136+ ```
1137+
1138+ 我想冒昧的借用一下术语“proxy”(代理),因为在 * 《设计模式》* 里,他们坚持认为一个代理(proxy)必须拥有和它所代理的对象一模一样的接口。但是,如果把这两个词一起使用,叫做“代理适配器(proxy adapter)”,似乎更合理一些。
1139+
1140+ ### 外观模式(Fa çade)
1141+
1142+ 当我想方设法试图将需求初步(first- cut)转化成对象的时候,通常我使用的原则是:
1143+
1144+ > “把所有丑陋的东西都隐藏到对象里去”。
1145+
1146+ 基本上说,* 外观模式* 干的就是这个事情。如果我们有一堆让人头晕的类以及交互(Interactions ),而它们又不是客户端程序员必须了解的,那我们就可以为客户端程序员创建一个接口只提供那些必要的功能。
1147+
1148+ 外观模式经常被实现为一个符合单例模式(Singleton )的抽象工厂(abstract factory)。当然,你可以通过创建包含 ** 静态** 工厂方法(static factory methods)的类来达到上述效果。
1149+
1150+ ```java
1151+ // patterns/Facade.java
1152+
1153+ class A { A (int x ) {} }
1154+
1155+ class B { B (long x ) {} }
1156+
1157+ class C { C (double x ) {} }
1158+
1159+ // Other classes that aren't exposed by the
1160+ // facade go here ...
1161+ public class Facade {
1162+ static A makeA (int x ) { return new A (x); }
1163+ static B makeB (long x ) { return new B (x); }
1164+ static C makeC (double x ) { return new C (x); }
1165+ public static void main (String [] args ) {
1166+ // The client programmer gets the objects
1167+ // by calling the static methods:
1168+ A a = Facade . makeA(1 );
1169+ B b = Facade . makeB(1 );
1170+ C c = Facade . makeC(1.0 );
1171+ }
1172+ }
1173+ ```
1174+
1175+ 《设计模式》给出的例子并不是真正的 * 外观模式* ,而仅仅是一个类使用了其他的类而已。
1176+
1177+ #### 包(Package )作为外观模式的变体
1178+
1179+ 我感觉,* 外观模式* 更倾向于“过程式的(procedural)”,也就是非面向对象的(non- object- oriented):我们是通过调用某些函数才得到对象。它和抽象工厂(Abstract factory)到底有多大差别呢?* 外观模式* 关键的一点是隐藏某个库的一部分类(以及它们的交互),使它们对于客户端程序员不可见,这样那些类的接口就更加简练和易于理解了。
1180+
1181+ 其实,这也正是 Java 的 packaging(包)的功能所完成的事情:在库以外,我们只能创建和使用被声明为公共(public )的那些类;所有非公共(non- public )的类只能被同一 package 的类使用。看起来,* 外观模式* 似乎是 Java 内嵌的一个功能。
1182+
1183+ 公平起见,* 《设计模式》* 主要是写给 C ++ 读者的。尽管 C ++ 有命名空间(namespaces)机制来防止全局变量和类名称之间的冲突,但它并没有提供类隐藏的机制,而在 Java 里我们可以通过声明 non- public 类来实现这一点。我认为,大多数情况下 Java 的 package 功能就足以解决针对 * 外观模式* 的问题了。
10481184
10491185< ! -- Interpreter : Run - Time Flexibility -- >
10501186## 解释器
0 commit comments