设计模式之适配器模式与外观模式
适配器模式适配器模式就是将一个接口转化成另一个接口。 一个常见的例子是插头转换器 我们知道英式插头长这样: 而国内的插头一般是这样的 这时候,你就需要一个转换插头了 而适配器的工作就像是一个转换插头。你不需要从新买一个电器,也不用换一个插孔,只需要一个转换器即可。 假设已有一个软件系统,你希望它能和新的厂商类库搭配使用,但是这个新厂商设计出来的接口,不同于旧厂商的接口。 你不想改变现有的代码,也不能改变厂商的代码,于是你可以写一个类,将新厂商接口转成你所希望的接口。 情景: 首先你有一个鸭子接口(这书有毒啊啊啊这都什么破例子) 有一个鸭子的子类
MallardDuck
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> quack() {
System.out.println(</span>"Quack"<span style="color: #000000;">);
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> fly() {
System.out.println(</span>"I'm flying"<span style="color: #000000;">);
}
} 然后现在有一只火鸡 <div class="cnblogs_code"> WildTurkey
} 因为你想要鸭子,鸭子不够用了,但是我们有火鸡,于是你决定为火鸡写一个配适器,偷偷地假装它们是鸭子。。。。 当需要鸭子叫的时候,就让火鸡叫,当需要鸭子飞的时候,就让火鸡飞。火鸡飞的距离短,所以还要多飞几次。 TurkeyAdapter
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> TurkeyAdapter(Turkey turkey) {
</span><span style="color: #0000ff;">this</span>.turkey =<span style="color: #000000;"> turkey;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> quack() {
turkey.gobble();
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> fly() {
</span><span style="color: #008000;">//</span><span style="color: #008000;"> 火鸡飞行距离短 要连续飞五次才能对应鸭子的飞行</span>
<span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 0; i < 5; ++<span style="color: #000000;">i) {
turkey.fly();
}
}
} 然后测试一下: =
WildTurkey turkey </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> WildTurkey();
Duck turkeyAdapter </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> TurkeyAdapter(turkey);
System.out.println(</span>"The turkey says..."<span style="color: #000000;">);
turkey.gobble();
turkey.fly();
System.out.println(</span>"nThe Duck says..."<span style="color: #000000;">);
testDuck(duck);
System.out.println(</span>"nThe TurkeyAdapter says..."<span style="color: #000000;">);
testDuck(turkeyAdapter);
}
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> testDuck(Duck duck) {
duck.quack();
duck.fly();
}
} 输出: 'm flying a short diatance
'm flying
'm flying a short diatance
I'm flying a short diatance
I'm flying a short diatance
I'm flying a short diatance
I'm flying a short diatance
我们就可以把火鸡当成鸭子了~(真·有毒。。。。
类图: 上面的类图表现的是“对象”适配器,还有一种适配器,被称作“类”适配器,需要多重继承才能实现,所以在Java中是不可能的。 现实世界一个简单的适配器。 在早期的集合实现如Vector,Stack,HashTable都实现了一个elements()的方法,该方法会返回一个Enumeration,这个接口可以逐一走过集合内的每一个元素。 而新的集合类,使用Iterator来遍历集合。 现在,将枚举适配到迭代器。 <span style="color: #0000ff;">public <span style="color: #0000ff;">class EnumerationIterator <span style="color: #0000ff;">implements<span style="color: #000000;"> Iterator {
} 反过来也可以将迭代器适配到枚举 <span style="color: #0000ff;">public <span style="color: #0000ff;">class IteratorEnumeration <span style="color: #0000ff;">implements<span style="color: #000000;"> Enumeration {
Iterator iterator;
} 测试一下: <span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> ArrayListEnumTest {
<span style="color: #0000ff;">public <span style="color: #0000ff;">static <span style="color: #0000ff;">void<span style="color: #000000;"> main(String[] args) { ArrayList list = <span style="color: #0000ff;">new<span style="color: #000000;"> ArrayList(); list.add("适"<span style="color: #000000;">); list.add("配"<span style="color: #000000;">); list.add("器"<span style="color: #000000;">); list.add("模"<span style="color: #000000;">); list.add("式"<span style="color: #000000;">); Iterator iterator =<span style="color: #000000;"> list.iterator(); Enumeration ei = <span style="color: #0000ff;">new<span style="color: #000000;"> IteratorEnumeration(iterator); showListByEnum(ei); }
} 外观模式情景:当你需要看一场电影的时候,你可能需要调灯光放屏幕打开投影机选择模式……每一次都是一样的步骤,等结束的时候,又是一系列繁琐的动作。 如果提供一个简单的类,能够一下就完成这一系列工作就好了。 这时就需要用外观模式,将一系列子类包装起来,提供一个简单的接口,来替代访问一系列子系统的接口。
原谅自己只能写一个拙劣的例子,折叠掉。。。 <span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> FacadeTest {
<span style="color: #0000ff;">public <span style="color: #0000ff;">static <span style="color: #0000ff;">void<span style="color: #000000;"> main(String[] args) { A a = <span style="color: #0000ff;">new<span style="color: #000000;"> A(); B b = <span style="color: #0000ff;">new<span style="color: #000000;"> B(); C c = <span style="color: #0000ff;">new<span style="color: #000000;"> C(); Facade facade = <span style="color: #0000ff;">new<span style="color: #000000;"> Facade(a,b,c); facade.ABC1(); System.out.println(); facade.ABC2(); } } <span style="color: #0000ff;">class<span style="color: #000000;"> A { <span style="color: #0000ff;">class<span style="color: #000000;"> B { <span style="color: #0000ff;">class<span style="color: #000000;"> C { <span style="color: #0000ff;">class<span style="color: #000000;"> Facade {
类图: 这个原则希望我们在设计中,不要让太多的类耦合在一起,免得修改系统中的一部分,会影响到其他部分。 怎么才能避免这样?这个原则提供了一些方针:就任何对象而言,在该对象的方法内,我们只应调用属于以下范围的方法:
举个栗子: 不使用这个原则: =
使用这个原则: 应用此原则时,在气象站中加一个方法,用来向温度计请求温度。这可以减少我们所依赖的类的数目。 综上: 当需要使用一个现有的类而其接口并不符合你的需求时,就使用适配器。 当需要简化并统一一个很大的接口或者一群复杂的接口时,使用外观。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |