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

适配器模式有两种,对象适配器和类的适配器。先看一下对象适配器。

还是看最开始鸭子的例子,如果此时鸭子不够了,需要一个火鸡来充当一个鸭子。

对象适配器

interface Duck {
public void quack(); public void fly();
} interface Turkey {
public void gobble(); public void fly();
} class WildTurkey implements Turkey {
@Override
public void gobble() {
System.out.println("Gobble gobble");
} @Override
public void fly() {
System.out.println("i am flying a short distance");
}
} class TurkeyAdaper implements Duck {
Turkey turkey; public TurkeyAdaper(Turkey turkey) {
this.turkey = turkey;
} @Override
public void quack() {
turkey.gobble();
} @Override
public void fly() {
for (int i = ; i < ; i++) {
turkey.fly();
}
}
} public class Test {
public static void main(String[] args) {
Turkey turkey = new WildTurkey();
Duck turkeyAdaper = new TurkeyAdaper(turkey);
turkey.gobble();
turkey.fly(); testDuck(turkeyAdaper);
} static void testDuck(Duck duck) {
duck.quack();
duck.fly();
}
}

类图:

适配器的需要进行的工作和目标接口的大小成正比。如果一个目标接口很大,不用适配器的话,就要改写原来的代码来调用这个接口,这也会很耗费力气,相比之下,还是将所有的变化封装进一个适配类中比较好。

假如上面还有还有一个鹅(Goose)也不够用了,还需要用火鸡来充当鹅,只需要将这个适配器在实现Goose的接口,这样这个适配器技能适配成Duck还能适配成Goose。

然后看一下类的适配器

interface Duck {
public void quack(); public void fly();
} interface Turkey {
public void gobble(); public void fly();
} class WildTurkey implements Turkey {
@Override
public void gobble() {
System.out.println("Gobble gobble");
} @Override
public void fly() {
System.out.println("i am flying a short distance");
}
} class AnotherTurkeyAdaper extends WildTurkey implements Duck {
@Override
public void quack() { }
}

类图:

类的适配器继承原有类(WildTurkey),实现目标类(Duck)。这样适配器中可以具有目标类的方法,如果要扩招原有的类也可以覆盖重写原有类的方法。(自己感觉:这种模式的原有类的基类最好是一个抽象类,这样可以继承基类获取方法,而不是去实现基类的子类)

就代码而言,两种模式的区别是对象适配器中需要持有原对象,而类的适配器是同时扩展两个类(实际上应该是同时继承两个类,但是java不允许多继承,只好实现目标接口),不需要在适配器持有原对象,如果需要可以重写原对象的方法。无论怎么做一定要扩展目标类(Duck),因为你就是想让不是目标类(Duck)的类型可以伪装成一个目标类(Duck)。

对象适配器利用组合,可以扩展这个类的子类。类适配器利用继承,不需要重新实现整个被适配者,必要的时候,可以重写。对象适配器是利用组合,需要持有被适配者,这样可以将工作委托给适配者进行,更有弹性,同时也用到了组合优于继承。但是这是有代价的,需要在代码中在创建一个被适配者,代码量增加,而类适配器只需要这个适配器就可以,效率高。

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

利用了新的原则:最少知识原则(迪米特法则,不要和陌生人说话),定义类和类之间的松耦合

首先先理解一下这个原则。(下面代码copy自 http://www.cnblogs.com/yucongblog/p/4620607.html   )
下面这段代码严重违反迪米特法则:

public class Teacher {
public void commond(GroupLeader groupLeader) {
List<Girl> listGirls = new ArrayList<Girl>();
for (int i = ; i < ; i++) {
listGirls.add(new Girl());
}
groupLeader.countGirls(listGirls);
}
}

我们在代码中这么写可能很常见,以后应该在写代码的时候应该想想这方面的问题。
为什么违反了迪米特法则,在commend方法中,用到了Girl类,而Teacher类的行为commend在运行前Teacher类居然不知道还依赖了这个类。
正确的做法:

public class Teacher {
public void commond(GroupLeader groupLeader) {
groupLeader.countGirls();
}
}
public class GroupLeader {
private List<Girl> listGirls; public GroupLeader(List<Girl> _listGirls) {
this.listGirls = _listGirls;
}
public void countGirls() {
System.out.println("女生数量是:" + listGirls.size());
}
}

迪米特法则希望,类中public尽量少,尽量多的private,protected,final。一定要减少类之间的耦合

这个原则提供了一些方针:在对象的方法内,我们只能调用一下范围的方法
1、该对想本身
2、被当做方法的参数传进来的对象
3、此方法所创建或实例化的任何对象  (前三点隐藏着一个注意的地方:如果某对象是调用其他方法的返回结果,不要调用改对象的方法)
4、对象的组件

外观模式代码:

public class Test2Facade {
public static void main(String[] args) {
Facade facade = new Facade(new FacedeA(), new FacedeB(), new FacedeC());
facade.method();
}
} class FacedeA {
public void facadeA() { }
} class FacedeB {
public void facadeB() { }
} class FacedeC {
public void facadeC() { }
} class Facade {
private FacedeA facedeA;
private FacedeB facedeB;
private FacedeC facedeC; public Facade(FacedeA facedeA, FacedeB facedeB, FacedeC facedeC) {
this.facedeA = facedeA;
this.facedeB = facedeB;
this.facedeC = facedeC;
} public void method() {
facedeA.facadeA();
facedeB.facadeB();
facedeC.facadeC();
}
}

就是将一个大方法组成了一个小方法供client去调用。类图也不用了,基本上写代码的时候都是这么写的。要注意的就是尽量使用迪米特法则来设计外观模式。

Head First 设计模式 --7 适配器模式 外观模式的更多相关文章

  1. Java设计模式之《外观模式》及应用场景

    原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6484128.html 1.外观模式简介 外观模式,一般用在子系统与访问之间,用于对访问屏蔽复 ...

  2. 《Head First 设计模式》学习笔记——适配器模式 + 外观模式

    在ADO.NET中.对于我们从数据库中取出的数据都要放到一个DataSet中,无论你是Access的数据库,还是SQL的数据库,或者是Oracle的数据库都要放到DataSet中..NET中并没有提供 ...

  3. c#设计模式之:外观模式(Facade)

    一.引言 在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化,然而为了将复杂系统的内部子系统与客户端之间的依赖解耦,从而就有了外观模式,也称作 ...

  4. Head First设计模式——适配器和外观模式

    前言:为什么要一次讲解这两个模式,说点骚话:因为比较简单(*^_^*),其实是他们两个有相似和有时候我们容易搞混概念. 讲到这两个设计模式与另外一个“装饰者模式”也有相似,他们三个按照结构模式分类都属 ...

  5. PHP设计模式之:外观模式

    外观模式: 外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用: 外观模式又称为门面模 ...

  6. C#设计模式之十一外观模式(Facade)【结构型】

    一.引言 快12点半了,要开始今天的写作了.很快,转眼设计模式已经写了十个了,今天我们要讲[结构型]设计模式的第五个模式,该模式是[外观模式],英文名称是:Facade Pattern.我们先从名字上 ...

  7. 设计模式学习心得<外观模式 Facade>

    外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. 这种模式涉及 ...

  8. C#设计模式之十外观模式(Facade Pattern)【结构型】

    一.引言 快12点半了,要开始今天的写作了.很快,转眼设计模式已经写了十个了,今天我们要讲[结构型]设计模式的第五个模式,该模式是[外观模式],英文名称是:Facade Pattern.我们先从名字上 ...

  9. 设计模式のFacadePattern(外观模式)----结构模式

    一.产生背景 外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. ...

随机推荐

  1. Microsoft ACE OLEDB 12.0概念及用法

    首先需要清楚几个概念: Database engine(数据引擎):一些预先存储于数据库中的组件: Microsoft JET (Joint Engine Technology):Microsoft ...

  2. jdk环境变量

    exportJAVA_HOME=/opt/jdk1.8.0_92 exportJRE_HOME=${JAVA_HOME}/jre   exportCLASSPATH=.:${JAVA_HOME}/li ...

  3. django静态文件数据库设置

    STATIC_URL = '/static/'STATICFILES_DIRS = (        os.path.join(BASE_DIR,'static')) DATABASES = {    ...

  4. Eclipse设置自动换行

    Eclipse 使用系统内置的“ Text Editor ”做为文本编辑器,这个文本编辑器有一个问题,就是文本无法换行.这个问题在显示上给人们带来不少麻烦. 终于有人忍不住开发了一个扩展插件 Word ...

  5. 如何在断开ssh连接后仍然保持服务器正常运行程序

    问题描述:当SSH远程连接到服务器上,然后运行一个Python程序(bpr.py),然后把终端开闭(切断SSH连接)之后,发现该程序执行中断. 解决方法:使用nohup命令让程序在关闭窗口(切换SSH ...

  6. 向ES6看齐,用更好的JavaScript(三)

    本文是ES6系列的第三篇,主要介绍ES6新增的数据类型.数据结构,先上传送门: 1 变量部分 2 现有对象拓展 3 新增数据类型/数据结构 4 新的异步编程模式 5 类和模块 1 第七种数据类型Sym ...

  7. spring1冲刺感想与总结

    感想与体会: 通过团队合作的第一个sprint,我们知道如何在团队合作中做好自己,还有与队友不合时,如何和平处理问题.产品负责人是一个重要的的角色,他负责任务的安排,处理合作中意见不统一的问题.通过这 ...

  8. 【NFC】Android NFC API Reference中英文

    0 Near Field Communication Near Field Communication (NFC) is a set of   short-range wireless technol ...

  9. 夺命雷公狗-----React---4--props变量的传递

    提示:props的值是不可以改变的... <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  10. AJAX-----14HTML5中新增的API---files

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...