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

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

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

对象适配器

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. Java基础之扩展GUI——使用对话框创建文本元素(Sketcher 4 creating text elements)

    控制台程序. 为了与Sketcher中的其他元素类型保持一致,需要为Elements菜单添加Text菜单项和工具栏按钮.还需要定义用来表示文本元素的类Element.Text. 1.修改Sketche ...

  2. Spring MVC 入门示例讲解

    在本例中,我们将使用Spring MVC框架构建一个入门级web应用程序.Spring MVC 是Spring框架最重要的的模块之一.它以强大的Spring IoC容器为基础,并充分利用容器的特性来简 ...

  3. 使用 Google Guava 美化你的 Java 代码

    文章转载自:http://my.oschina.net/leejun2005/blog/172328 目录:[ - ] 1-使用 GOOGLE COLLECTIONS,GUAVA,STATIC IMP ...

  4. 关于Web项目里的给表单验证控件添加结束时间不得小于开始时间的验证方法,日期转换和前台显示格式之间,还有JSON取日期数据格式转换成标准日期格式的问题

    项目里有些不同页面间的日期显示格式是不同的, 第一个问题: 比如我用日期控件WdatePicker.js导包后只需在input标签里加上onClick="WdatePicker()" ...

  5. mfc ui库

    引用:http://blog.csdn.net/weiqubo/article/details/6783717 Xtrme toolkit,BCGControlBar,SkinMagic,AppFac ...

  6. jenkins解决jenkins内存溢出问题

    在jenkins master-slave配置中,总是出现内存溢出问题,更换了机器设备仍然跑不起来: 问题如下: Status Code: 500 Exception: org.apache.comm ...

  7. datatable-提示

    `默认columns配置问题: 记住是columnDefs不是columnsDefs `Cannot read property 'sWidth' of undefined: columns的数量和t ...

  8. springmvc 组合注解

    组合注解的意思就是一个注解中包含多个注解.在springmvc 的@RestController中,你就可发现. @Target(ElementType.TYPE) @Retention(Retent ...

  9. Deferred解决JS同步问题

    测试脚本: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...

  10. 如何通过CRM评估客户价值和提高客户忠诚度?

    随着市场经济的日益繁荣,同行业之间企业的竞争越来越激烈,企业纷纷各出奇招吸引和挖掘客户,力求让自己的品牌成为更多客户的第一选择.那么,我们可以用什么方法来评估客户价值,提高客户忠诚度呢? 在互联网时代 ...