我是靠谱客的博主 踏实奇异果,这篇文章主要介绍适配器模式与外观模式,现在分享给大家,希望可以做个参考。

适配器GitHub代码
外观GitHub代码

适配器模式

场景描述:想象一下我们维护了一套老系统,并于一个厂商通过接口进行交互。但是最近厂商更新它们的代码,并变更了接口格式,我们如何在不修改老系统代码的基础上,优雅的过渡呢?

提出方案:我们可以想象一下我们平时使用的转换头,这就是一种适配器。我们可以通过这种方式来优雅的“将方形放入圆形中”。

我们尝试举一个例子,假设现在有一个鸭子接口

复制代码
1
2
3
4
5
public interface Duck { public void quack(); public void fly(); }

并作出一个实现

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
public class MallardDuck implements Duck { @Override public void quack() { System.out.println("Quack"); } @Override public void fly() { System.out.println("I'm flying"); } }

接着我们有另一个火鸡接口

复制代码
1
2
3
4
5
public interface Turkey { public void gobble(); public void fly(); }

以及一个实现

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
public class WildTurkey implements Turkey { @Override public void gobble() { System.out.println("Gobble gobble"); } @Override public void fly() { System.out.println("I'm flying a short distance"); } }

我们如何能够将火鸡作为鸭子呢?可以提供一个适配器来做接口的转换

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TurkeyAdapter implements Duck { Turkey turkey; public TurkeyAdapter(Turkey turkey){ this.turkey = turkey; } @Override public void quack() { turkey.gobble(); } @Override public void fly() { for (int i = 0; i < 5; i++){ turkey.fly(); } } }

然后我们测试一下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class DuckTestDrive { public static void main(String[] args) { MallardDuck duck = new MallardDuck(); WildTurkey turkey = new WildTurkey(); Duck turkeyAdapter = new TurkeyAdapter(turkey); System.out.println("The Turkey says..."); turkey.gobble(); turkey.fly(); System.out.println("nThe Duck says..."); testDuck(duck); System.out.println("nThe TurkeyAdapter says..."); testDuck(turkeyAdapter); } static void testDuck(Duck duck){ duck.quack(); duck.fly(); } }

可以通过结果看到我们现在将这个火鸡作为一只鸭子的实现了。
在这里插入图片描述

适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。

我们看一下它的类图
在这里插入图片描述
实现一个适配器所需要进行的工作,和目标接口的大小成正比。

由于Java不支持多继承,所以适配器又分为“对象”适配器(Java)和“类”适配器(支持多继承的其他语言)。

再看一下“类”适配器的类图
在这里插入图片描述

外观模式

场景描述:我们现在有一个家庭影院,其中包含了DVD,投影机,自动屏幕,立体环绕声等等,每当我们想要看电影的时候,都需要进行一系列操作;而看完电影时,又需要反向再操作一遍。

改进方案:我们尝试进行一种近似流水线的改造,通过将一系列操作变成一个更加高层的操作。

如下是我们的改进方案的代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class HomeTheaterFacade { Amplifier amp; Tuner tuner; DvdPlayer dvd; CdPlayer cd; Projector projector; TheaterLights lights; Screen screen; PopcornPopper popper; public HomeTheaterFacade(Amplifier amp, Tuner tuner, DvdPlayer dvd, CdPlayer cd, Projector projector, TheaterLights lights, Screen screen, PopcornPopper popper){ this.amp = amp; this.tuner = tuner; this.dvd = dvd; this.cd = cd; this.projector = projector; this.lights = lights; this.screen = screen; this.popper = popper; } public void watchMovie(String movie){ System.out.println("Get ready to watch a movie..."); popper.on(); popper.pop(); lights.dim(10); screen.down(); projector.on(); projector.wideScreenMode(); amp.on(); amp.setDvd(); amp.setSurroundSound(); amp.setVolume(5); dvd.on(); dvd.play(movie); } public void endMovie(){ System.out.println("Shutting movie theater down..."); popper.off(); lights.on(); screen.up(); projector.off(); amp.off(); dvd.stop(); dvd.eject(); dvd.off(); }

这样我们测试一下,只可以通过一步操作就完成之前的一系列操作

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class HomeTheaterTestDrive { public static void main(String[] args) { Amplifier amp = new Amplifier(); Tuner tuner = new Tuner(); DvdPlayer dvd = new DvdPlayer(); CdPlayer cd = new CdPlayer(); Projector projector = new Projector(); Screen screen = new Screen(); TheaterLights lights = new TheaterLights(); PopcornPopper popper = new PopcornPopper(); HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, tuner, dvd, cd, projector, lights, screen, popper); homeTheater.watchMovie("Raiders of the Lost Ark"); System.out.println("n-----------Watching Movies------------n"); homeTheater.endMovie(); } }

结果如下
在这里插入图片描述

外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。

外观模式有一个很好的特征:提供简化的接口的同时,依然将系统完整的功能暴露出来,以供需要的人使用。
以下是它的类图
在这里插入图片描述
适配器模式的意图是,“改变”接口符合客户的期望;而外观模式的意图是,提供子系统的一个简化接口。
我们将装饰者模式、适配器模式、外观模式一同比较,可以看出它们的意图分别为:

  • 装饰者模式,不改变接口,但加入职责
  • 适配器模式,将一个接口转成另一个接口
  • 外观模式,让接口更简单

设计原则:最少知识原则:只和你的密友谈话。

当你正在设计一个系统,不管是任何对象,你都要注意它所交互的类有哪些,并注意它和这些类是如何交互的。
这个原则又名墨忒耳法则,它希望我们在设计中,不要让太多的类耦合在一起,免得修改系统中一部分,会影响到其他部分。

这个原则提供了一些方针:就任何对象而言,在该对象的方法内,我们只应该调用属于以下范围的方法:

  • 该对象本身
  • 被当作方法的参数而传递进来的对象
  • 此方法所创建或实例化的任何对象
  • 对象的任何组件

如果调用从另一个调用中返回的对象的方法,会有什么害处呢?如果我们这样做,相当于向另一个对象的子部分发请求(而增加我们直接认识的对象数目)。
在这里插入图片描述
这个原则的缺点是,采用这个原则会导致更多的“包装”类被制造出来,以处理和其他组件的沟通,这可能会导致复杂度和开发时间的增加,并降低运行时的性能。

总结如下:当我们需要从一个接口“转变”为另一个接口时,可以尝试使用适配器;而当我们想要将子系统的一系列操作简化时,可以使用外观模式。

最后

以上就是踏实奇异果最近收集整理的关于适配器模式与外观模式的全部内容,更多相关适配器模式与外观模式内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(80)

评论列表共有 0 条评论

立即
投稿
返回
顶部