`
阅读更多
1.什么时候使用适配器模式
   适配器模式俗称变压器模式,指将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

   从功能上讲这些接口不兼容的类一般具有相同或相似的功能。通常我们通过修改该类的接口来解决这种接口不兼容的情形,但是如果我们不愿意为了一个应用而修改各原有的接口,或者我们压根就没有原有对象的源代码那该怎么办呢? 此时Adapter模式就会派上大用场了。

   使用适配器模式不仅保证没有修改原有的系统,更主要的是还能保证对现有类的重用。若不进行这样的转化,客户类就不能利用现有类所提供的功能。

2.适配器模式的几个要素

    适配器模式所涉及的角色包括:1.源;2.目标;3.适配器;4.客户。

1.源(Adaptee)

    已经存在的、需要适配的类。

2.目标(Target)

    客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。

3.适配器(Adapter)

    适配器模式的核心类。有两种方式实现Adapter,对象适配器(Object Adapter)和类适配器(Class Adapter)。

4.客户(Client):

下图是Adapter设计模式中的几个对象:




3.类适配器




客户调用Target接口的request方法,实际就是调用其父类Adaptee的specialRequest方法。

代码示例如下:

//Adaptee.java
public class Adaptee{
     public void specialRequest(){
         System.out.println("Called SpecificRequest() in Adaptee ");
     }       
}

//Client.java
public class Client {
    public static void main(String[] args){
        Target t = new Adapter() ;
        t.request();
    }
}

//Target.java
public interface Target{
     public void request();
}

//Adapter.java
public class Adapter extends Adaptee implements Target{
     public void request(){
           this.specialRequest();
     }
}


4.对象适配器




  对象适配器将Adaptee对象做为一个Adapter适配器对象的一个属性,再进行调用。

示例代码:


//Adaptee.java
public class Adaptee{
     public void specialRequest(){
         System.out.println("Called SpecificRequest() in Adaptee ");
     }       
}

//Client.java
public class Client {
    public static void main(String[] args){
        Target t = new Adapter() ;
        t.request();
    }
}

//Target.java
public interface Target{
    public void request();
}

//Adapter.java
public class Adapter implements Target{
     Adaptee adaptee = new Adaptee();
     public void request(){
            adaptee.specialRequest();
     }
}


5.适配器模式的变体

    上面谈到的所有适配器都是通过重用Adaptee类从而实现Target接口中的方法。这只是具体层次的重用。是否还存在更高层次的适配器呢!?答案是肯定的!我们不仅可以适配具体的类还可以适配抽象类,甚至适配接口!下面是这种适配的简图:




   从上图可以看出:Adapter将Adaptee接口适配为客户Client需要的接口Target,这样在整个系统中所有实现Adaptee接口的类都可以通过Adapter适配为Target对象,从而避免为每一个类都写一个适配器。

6.IO库中的适配器模式

6.1 FileInputStream适配器类

   在FileInputStream继承了InputStrem类型,同时持有一个对FileDiscriptor的引用。这是将一个FileDiscriptor对象适配成InputStrem类型的对象形式的适配器模式,如下图所示:




查看JDK1.4的源代码我们可以看到:

Public class FileInputStream extends InputStream{
   private FileDescriptor fd;
   public FileInputStream(FileDescriptor fdObj) {
      SecurityManager security = System.getSecurityManager();
      if (fdObj == null) {
         throw new NullPointerException();
      }
      if (security != null) {
      security.checkRead(fdObj);
       }
      fd = fdObj;
  }

  public FileInputStream(File file) throws FileNotFoundException {
  String name = file.getPath();
  SecurityManager security = System.getSecurityManager();
  if (security != null) {
  security.checkRead(name);
  }
  fd = new FileDescriptor();  //对象适配器
  open(name);
  }
  //其它代码

  }

  
6.2 从byte流到char流的适配

   在Java I/O库中,使用比较频繁的要数InputStreamReader,OutputStreamWriter这两种类了,

  InputStreamReader是从byte输入流到char输入流的一个适配器。下图所示就是 InputStreamReader与Reader和InputStream等类的结构图:




  当把InputStreamReader与任何InputStream的具体子类链接的时候,可以从InputStream的输出读入byte类型的数据,将之转换成为char类型的数据,如下图所示:




查看JDK1.4的InputStreamReader源代码:

public class InputStreamReader extends Reader {
  private final StreamDecoder sd;//Adaptee对象
  public InputStreamReader(InputStream in) {
  super(in);
  try {
  sd = StreamDecoder.forInputStreamReader(in, this, (String)null); 
  } catch (UnsupportedEncodingException e) {
  // The default encoding should always be available
  throw new Error(e);
  }
  //其它代码
  }




  • 大小: 15.3 KB
  • 大小: 15.7 KB
  • 大小: 15.9 KB
  • 大小: 21 KB
  • 大小: 38.9 KB
  • 大小: 42.2 KB
  • 大小: 19.1 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics