Head First 设计模式 --7 适配器模式 外观模式
适配器模式:将一个类东街口转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
适配器模式有两种,对象适配器和类的适配器。先看一下对象适配器。
还是看最开始鸭子的例子,如果此时鸭子不够了,需要一个火鸡来充当一个鸭子。
对象适配器
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 适配器模式 外观模式的更多相关文章
- Java设计模式之《外观模式》及应用场景
原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6484128.html 1.外观模式简介 外观模式,一般用在子系统与访问之间,用于对访问屏蔽复 ...
- 《Head First 设计模式》学习笔记——适配器模式 + 外观模式
在ADO.NET中.对于我们从数据库中取出的数据都要放到一个DataSet中,无论你是Access的数据库,还是SQL的数据库,或者是Oracle的数据库都要放到DataSet中..NET中并没有提供 ...
- c#设计模式之:外观模式(Facade)
一.引言 在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化,然而为了将复杂系统的内部子系统与客户端之间的依赖解耦,从而就有了外观模式,也称作 ...
- Head First设计模式——适配器和外观模式
前言:为什么要一次讲解这两个模式,说点骚话:因为比较简单(*^_^*),其实是他们两个有相似和有时候我们容易搞混概念. 讲到这两个设计模式与另外一个“装饰者模式”也有相似,他们三个按照结构模式分类都属 ...
- PHP设计模式之:外观模式
外观模式: 外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用: 外观模式又称为门面模 ...
- C#设计模式之十一外观模式(Facade)【结构型】
一.引言 快12点半了,要开始今天的写作了.很快,转眼设计模式已经写了十个了,今天我们要讲[结构型]设计模式的第五个模式,该模式是[外观模式],英文名称是:Facade Pattern.我们先从名字上 ...
- 设计模式学习心得<外观模式 Facade>
外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. 这种模式涉及 ...
- C#设计模式之十外观模式(Facade Pattern)【结构型】
一.引言 快12点半了,要开始今天的写作了.很快,转眼设计模式已经写了十个了,今天我们要讲[结构型]设计模式的第五个模式,该模式是[外观模式],英文名称是:Facade Pattern.我们先从名字上 ...
- 设计模式のFacadePattern(外观模式)----结构模式
一.产生背景 外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. ...
随机推荐
- zepto源码--核心方法(类数组相关)--学习笔记
从这篇起,在没有介绍到各类插件之前,后面将陆续介绍zepto对外暴露的核心方法.即$.fn={}里面的所有方法的介绍.会配合zepto的API进行介绍. 其实前面已经介绍了几个,如width,heig ...
- StringBuffer与StringBuilder有什么区别
package String比较; /* * StringBuffer与StringBuilder有什么区别 * StringBuilder是JDK5增加的一个新类,功能几乎与StringBuffer ...
- NET 框架基本原理透析⑵
生成.打包.部署及管理应用程序与类型 要生成就离不开程,序集,程序集是包含一个或多个类型定义文件和资源文件的集合.在程序集包含的所有文件中,有一个文件用于保存清单.清单是另外一组元数据表的集合,其中主 ...
- __weak
需要使用弱引用的 三种情况: 1. 如果这个block不被持有,那么你完全没有必要使用__weak 2. 如果被持有了,那么__weak是必然的 3. 如果在多线程并发的情况下,不仅要使用__weak ...
- 捕获Insert触发器失败记录
1.背景 环境:发布服务器A Windows2008+SQL2008,分发服务器B Windows2008+SQL2008,订阅服务器C Windows2008+SQL2012发布服务器A上的用户信息 ...
- 安装django
我已经有Python3.5的环境了.我们去下载Django.https://github.com/django/django.git 直接下载为zip解压即可. 然后在命令提示符下安装 1. 切换 ...
- Python 面向对象编程进阶
静态方法 只是名义上归类管理,实际上在静态方法里访问不了类或实例中的任何属性 通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在 ...
- 【转】lonekight@xmu·ACM/ICPC 回忆录
转自:http://hi.baidu.com/ordeder/item/2a342a7fe7cb9e336dc37c89 2009年09月06日 星期日 21:55 初识ACM最早听说ACM/ICPC ...
- Java关于md5加密
package com.mi.util; /** * md5+salt 长度为32的加密 * @author admin * */ public class MD5 { public static v ...
- opencv的学习笔记1
想在周末去游泳,找了些游泳的注意事项什么的,想想还没干正事,就来继续看看opencv的使用吧,晚上看了opencv的一些基本入门的东西,打算下面主要总结CSDN上一个大牛的博文,链接如下:http:/ ...