Head First设计模式之适配器模式与外观模式

前言:

之前讲过装饰者模式,将对象包装起来并赋予新的职责,这一章我们也会将对象进行包装,只不过是让它们看起来不像自己而像是别的东西。这样就可以在设计中将类的接口转化为想要的接口,以实现同的接口,此外还将讲述另一个模式,将对象包装起来以简化接口。

1.   适配器简介

1.1 面向对象的适配器

真实世界的适配器比如位于美式插头和欧式插座之间的交流电适配器。面向对象的适配器是什么呢?

面向对象的适配器是将一个接口转化成另一个接口,以符合客户的期望。

例如已有的一个软件系统,希望它能和一个新的厂商类库搭配使用,但是这个厂商设计出来的接口不同于旧的接口,而你又不想改变现有的代码,所以这个时候就需要一个适配器来完成现有系统和新的厂商类库的对接。

1.2 使用中的适配器

我们在策略模式里举例讲的鸭子。看一个简化版的示例。

1.2.1 鸭子接口
  1. publicinterface Duck
  2. {
  3. void Quack();//鸭子叫
  4. void Fly();//鸭子飞
  5. }
1.2.2 鸭子子类(绿头鸭)实现
  1. publicclass MallardDuck:Duck
  2. {
  3. public void Quack()
  4. {
  5. Console.WriteLine(" Quack");
  6. }
  7. public void Fly()
  8. {
  9. Console.WriteLine(" Fly");
  10. }
  11. }
1.2.3 新的禽类接口以及具体实现
  1. publicinterface Turkey
  2. {
  3. void Gobble();//咯咯叫
  4. void Fly();//飞
  5. }
  6. publicclass WildTurkey : Turkey
  7. {
  8. public void Gobble()
  9. {
  10. Console.WriteLine(" GobbleGobble");
  11. }
  12. public void Fly()
  13. {
  14. Console.WriteLine(" I'm flyinga short distance ");
  15. }
  16. }
1.2.4 适配器
  1. publicclass TurkeyAdapter:Duck//实现想转换成的类型接口
  2. {
  3. Turkey turkey;
  4. public TurkeyAdapter(Turkey turkey)//取得适配器的对象引用,并利用构造得到这个引用
  5. {
  6. this.turkey = turkey;
  7. }
  8.  
  9. public void Quack()//实现接口中的所有方法
  10. {
  11. turkey.Gobble();
  12. }
  13.  
  14. public void Fly()
  15. {
  16. for(var i=0;i<5;i++)
  17. turkey.Fly();
  18. }
  19. }
1.2.5 测试
  1. MallardDuckduck = new MallardDuck();
  2. WildTurkey turkey = newWildTurkey();
  3. Duck turkeyAdapter = newTurkeyAdapter(turkey);
  4.  
  5. Console.WriteLine(" The turkeysyas ...");
  6. turkey.Gobble();
  7. turkey.Fly();
  8.  
  9. Console.WriteLine(" The Ducksays ...");
  10. turkeyAdapter.Quack();
  11. turkeyAdapter.Fly();
  12.  
  13. Console.Read();

结果如下:

1.3 适配器模式解析

客户使用适配器的过程如下:

l  客户通过目标接口调用适配器的方法对适配器发出请求。

l  适配器使用被适配者接口把请求转化成被适配者的一个或多个调用接口。

l  客户接收到调用的结果。

2.   定义适配器模式

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

该模式可以通过创建适配器进行接口转换,让不兼容的接口变得兼容,让客户从实现的接口解耦。其类图如下:

该适配器充满了OO设计的原则:使用对象组合,以修改的接口包装被适配者。被是陪者的任何子类都可以搭配着适配器使用。该模式是把客户和接口绑定起来的,而非和实现绑定。

实际上有两种适配器:对象适配器和类适配器。类适配器通过多重继承来实现,而对象适配器利用组合的方式将请求传递给被适配者。

类适配器图:

3.   定义外观模式

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

外观模式允许我们让客户和子系统之间避免紧耦合。类图如下:

4.   最少知识原则

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

最少知识原则告诉我们要减少对象之间的交互。该原则希望在设计时,不要让太多的类耦合在一起,免得修改系统中的一部分,会影响到其他部分。

怎样避免让太多的类耦合在一起呢?主要有以下的方针:

就对象而言,在该对象的方法内,我们只应该调用属于以下范围的方法:

l  该对象本身

l  被当做方法的参数而传递进来的对象

l  此方法所创建或实例化的任何对象

l  对象的任何组件

如下示例:

(不要采用这个原则)从气象站取得了温度计对象,然后再从温度计对象取得问题

  1. Publicfloat GetTemp()
  2. {
  3. Thermometerthermometer=station.GetThermometer();
  4. return thermometer.GetTemperature();
  5. }

(采用这个原则)我们在气象站中加进一个方法,用来向温度计请求温度。可以减少我们所依赖的类的数据。

  1. Publicfloat GetTemp()
  2. {
  3. Return station.GetTemperature();
  4. }

5.   总结

l  当需要使用一个现有的类而其接口并不符合你的需要时,就需要使用适配器。

l  当需要简化并统一一个很大的接口或者一群负责的接口时,使用外观。

l  适配器改变接口以符合客户的期望。

l  外观将客户从一个复杂的子系统中解耦。

l  实现一个适配器的难易视目标接口的大小与复杂而定。

l  实现一个外观,需要将子系统组合进外观中,然后将工作委托给子系统执行。

l  适配器分为对象适配器和类适配器,类适配器需要多重继承。

l  可以为一个子系统实现一个以上的外观。

l  适配器将一个对象包装起来以改变其接口;装饰者将一个对象包装起来以增加新的行为和责任;而外观将一群对象“包装”起来以简化其接口。

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

  1. 适配器模式和外观模式(head first设计模式——6)

    为什么要把适配器模式和外观模式放在同一篇文章中,主要是其相对前面的几个模式来讲会简单些并且具有相似之处.下面就分别通过例子来看理解一下两种模式,然后再进行对其进行比较. 一.适配器模式 1.1适配器模 ...

  2. 设计模式(九)外观模式Facade(结构型)

    设计模式(九)外观模式Facade(结构型) 1. 概述 外观模式,我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性. ...

  3. Java设计模式(11)外观模式(Facade模式)

    外观模式(Facade)的定义:为子系统中的一组接口提供一个一致的界面. Facade一个典型应用就是数据库JDBC的应用,如下例对数据库的操作: public class DBCompare { C ...

  4. 设计模式(二)-- 外观模式(Facade)

    设计模式(二) 外观模式(Facade) 为了解决子系统外部的客户端在使用子系统的时候,既能简单地使用这些子系统内部的模块功能,而又不用客户端去与子系统内部的多个模块交互的问题. 为子系统中的一组接口 ...

  5. headfirst设计模式(8)—适配器模式与外观模式

    前言 这一章主要讲2个模式,一个是,适配器模式(负责将一个类的接口适配成用户所期待的),另外一个是外观模式(为子系统提供一个共同的对外接口),看完的第一反应是,为什么要把它们两放在同一章,难道它们有什 ...

  6. 【HeadFirst设计模式】7.适配器模式与外观模式

    今晚学习完第七章,顺便做一下知识备忘. 适配器模模式: 定义:将一个类的接口,转换成客户期望的另一个接口.适配器让原本接口不兼容的类可以合作无间. 对象适配器: 类适配器: 外观模式: 提供了一个统一 ...

  7. 《Head First 设计模式》之适配器模式与外观模式

    适配器模式(Adapter) 适配器(adapter-pattern):将一个类的接口,转换成客户期望的另一个接口.适配器让原来接口不兼容的类可以合作无间.两种形式: 对象适配器(组合) 类适配器(多 ...

  8. 设计模式(十一)外观模式(Facade Pattern)

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

  9. 【转】设计模式(九)外观模式Facade(结构型)

    设计模式--外观模式Facade(结构型): 1. 概述 外观模式,我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性. ...

随机推荐

  1. Spring中配置文件中引用外部文件

    src\dayday\conn.java package dayday;import java.sql.Connection;import java.sql.DriverManager;import ...

  2. position属性的四个value

    As we all know, position属性有四个值,分别为 relative,fixed,absolute, static. 1,relative相对定位 (不会脱离文档流) 在一个相对定位 ...

  3. 更新UI界面的四种方法

    一.runOnUiThread(new Runnable()): 二.Handler的sendMessage()系列: 三.Handler的post(): 四.View的post():

  4. java开发环境

    java开发环境搭建   文中主要内容来自:http://blog.csdn.net/cxwen78/article/details/6400798 .文章对原文有所改动. 1. 开发工具获取 开发工 ...

  5. Java的多态

    多态的定义: 同一种行为,在不同对象上有不同的表现形式 实现多态的条件: 要有继承 要有方法的重写 要有父类的引用指向子类的对象 代码如下: public class Animal { String ...

  6. calender 软文

    http://www.cnblogs.com/cloudgamer/archive/2008/08/23/1274459.html

  7. tabhost使用

    Tabhost用法 使用方法一:使用同一个布局文件 在xml中如此定义tabhost: <RelativeLayout xmlns:android="http://schemas.an ...

  8. Uncaught ReferenceError: WebForm_DoPostBackWithOptions is not defined

    环境:Asp.Net网站,Framework版本4.0,IIS版本7.0问题:按钮失效,下面是按钮代码: <a id="dnn_ctr1161_Login_Login_DNN_cmdL ...

  9. java 对象 :创建

    灵感来自effective java 关于对象,是java的核心,如何有效的创建其实是一个值得关注的地方. 1.静态工厂:这是一个值得关注的,并且应该时刻考虑的方法. 优点:1.他是有名字的,这个是如 ...

  10. Android---闪频页和倒计时

    android闪频的实现非常简单,使用Handler对象的postDelayed()方法就可以实现.在这个方法里传递一个Runnable对象和一个延迟的时间.该方法实现了一个延迟执行的效果,延迟的时间 ...