详解 JAVA 适配模式和 接口适配器

 JAVA适配模式

意图
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。(GoF)

场景
相信很多人都知道什么是显卡,也有很多人知道显卡的本名——图形适配器。恩,是的,正好这回说说Apater模式,就拿显卡来例子来分析一下Adapter模式。

我们知道显示器(Client)是用来显示图形的,它是不能显示数据,它只能够接受来自图形发送设备Target的信号。可是我们手头上只有CPU(Adaptee)这个产生各种描述图形的数据的数据发送器。我们需要将这些数据让显示器进行显示,可是这两个部件却是不兼容的。于是我们需要一个中间设备,它能够将CPU“适配”于显示器,这便是我们的显卡——图形适配器(Adapter)。

java 代码

// 图形发送设备 
public class Target { 
    
    publicString request() { 
       return "Graphic sender"; 
   } 

    //显示器 
    public classClient { 
     
       public static void main(String[] args) { 
           Target target = new Targete(); 
           System.out.println(target.request()); 
       } 
   } 

可是我们的CPU(Adaptee)只能输出0/1数据,他是个计算器,而不是图形发送设备(Target)。

java 代码

    //CPU 
    public classAdaptee { 
        
       public String getData() { 
           return "CPU data"; 
       } 
   } 

这个时候我们的显卡(Adapter)的作用便体现出来了,它负责对CPU进行适配,通过将CPU传过来的数据转换成图形信号,从而将CPU伪装成一个图形发送设备。

java 代码

    //显卡,即我们的适配器 
    public classAdapter extends Target { 
     
       // 被代理的设备 
       private Adaptee apt = null; 
     
        
       public Adapter(Adaptee apt) { 
           this.apt = apt; 
       } 
     
        
       public String request() { 
           return apt.getData(); 
       } 
   } 

这样,我们的电脑的显示流程就变成CPU-显卡-显示器:

java 代码

    public class Client { 
     
       public static void main(String[] args) { 
           // CPU经过显卡的适配后“变”成了图形发送装置了 
           Target target = new Adapter(new Adaptee()); 
           System.out.println(target.request()); 
       } 
         
   } 

上面的这种依赖于对象组合的Adapter模式叫做对象适配器(ObjectAdapter)。它的特征是继承/实现某一方的类(Target),如这里的图形发送器,同时内部包含一个被适配的类(Adaptee),如这里的CPU。通过重写其父类的方法来进行适配。

另一种的Adapter实现
对于Adapter模式,还有另外一种实现方式,这种适配方式叫做类适配器(ClassAdapter)。它与Object Adapter的不同之处在于它继承被适配的对象。

java 代码

    public classAdapter extends Targer, Adaptee { 
       ...... 
   } 

这样的代码在C++中是合法的,但是在Java中规定最多只能继承一个父类,而可以实现多个接口。所以我们需要建立一个IAdaptee的接口,然后将我们的Adapter继承Target同时实现IAdaptee。

java 代码
 

    //IAdaptee接口 
    publicinterface IAdaptee{   
       String getData(); 
   }  

java 代码
 

    // Adaptee实现IAdaptee
    public classAdaptee implements IAdaptee { 
     ...... 
   }   

java 代码
 

    public classAdapter extends Target implements IAdaptee{ 
     
       private IAdaptee apt = null; 
     
       public Adapter(IAdaptee apt) { 
           this.apt = apt; 
       } 
     
       public String request() { 
           return apt.getData(); 
       } 
     
       public String getData() { 
           return apt.getData(); 
       } 
   } 

对于我们的显示器(Client)方面,Class Adapter跟Object Adapter一样,所以不需要进行修改。

对于ClassAdapter,大家也看见了,在Adapter中因为是实现了IAdaptee接口,因此需要实现getData()的接口。一旦Target和IAdaptee拥有相同的方法时,会出现麻烦的。所以尽量优先使用ObjectAdapter的模式。

接口适配器

java中适配器的作用实际上是实现了接口的类,但是适配器所实现的只是空方法。因为如果我们不用适配器,直接去实现接口,也要逐个实现里面的方法,并且大多情况下我们也会像jdk里适配器所做的:仅仅以空方法去实现,只实现对我们有用的方法。 

几乎所有申明了很多方法 的接口,都会有它自己的 适配器类。 

本身adapter没有什么作用,只是帮助程序员专注 所实现的功能,使代码简洁罢了

举第一个例子:

为一个接口提供缺省实现,这样子类可以从这个缺省实现进行扩展.而不必从原有接口进行扩展.作为适配器模式的一个特例,缺省适配模式在java语言中有着特殊的应用.(引用java模式书)

adapter是一个非常常用的设计模式.
像windows的每个窗口,事件很多个.关闭,移动,最大化,最小化,
java代码设计如下:
interface 窗口{
public void 关闭();
public void 移动();
public ovid 最大化();
...
...
}
如果客户点击了关闭按钮,java类实现如下:
Frame implements 窗口{
public void 关闭(){
System.out.println("关闭窗口");
}

public void 移动()[
}
public ovid 最大化(){
}
...
...
}
这里面我们可以看出,我们关注的只有关闭按钮触发的事件,其它的我们不用管.但是在java类中,我们必须把接口的所有方法都给实现.这样我们连一些没有用的方法也得给实现.那怕是空实现.

下面我们来建一个抽象类来实现这个接口.
public abstract Frame implements 窗口{
public void 关闭(){

}

public void 移动(){
}
public ovid 最大化(){
}
...
...
}
这里我们可以看出,抽象类给每个接口一个空的实现,那我们都可以在抽象类的基础上进行扩展。关闭功能实现如下:
public CloseFrame extends Frame{
public void 关闭(){
System.out.println("关闭窗口");

}
}

像在java中的事件处理都是用适配器模式来实现的。接口,抽象类都是已经写好的。我们只需要实现具体功能的类就可以了。

再举个简单的例子:
假如存在如下接口:
interface TestInterface{
void test1();
void test2();
void test3();
}
如果我们只关注test1接口应该怎样写呢。
abstract class TestAbstract implements Test{
public void test1(){
}
public void test2(){
}
public void test3(){
}
}
class TestTest1 extends TestAbstract{
public void test1(){
System.out.println("方法1实现");
}
}
那么在什么情况下用相信大家已经能看得出来了吧。假如你不准备实现接口的所有方法。就可以建一个抽象类来实现这个接口的所有方法,当然这里全都是空的实现.然后再写一个类继承这个抽象类就可以得到你想要的结果了.

一个更简单的例子

一般都是抽象类,API中很多都是这样的.比如在API中有
java.awt.event.WindowListener接口这样定义的:(接口声明了很多对窗口的事件)
public interface WindowListener{
public void windowActivated(WindowEvent e) {
}
public void windowClosed(WindowEvent e) {
}
public void windowClosing(WindowEvent e) {
}
public void windowDeactivated(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowOpened(WindowEvent e) {
}
}
但 是如果需要做一个关闭window的操作,如果直接实现这个接口的话,那么你必须对它声明的所以方法都实现,显然在逻辑中除了windowClosed(WindowEvente)方法外,对其他方法的实现都是做多余的操作.这样就出现了windowListener适配器类: 
  public abstract class WindowAdapter
  implements WindowListener
  {
  public void windowClosing(WindowEvent e) {} 
  public void windowClosed(WindowEvent e) {}
  public void windowIconified(WindowEvent e){}
  public void windowDeiconified(WindowEvent e){}
  public void windowActivated(WindowEvent e){}
  public void windowDeactivated(WindowEvent e){}
  }
显然他是一个抽象类,之是对WindowListener的一个简单的实现而已,所以的方法都只做了空实现[没有方法体].而他的好处是:如果你只需要关闭窗口这一事件,则可以让处理类继承WindowAdapter这个抽象类,重写他的windowClosing(WindowEvente)方法就是了.
WindowListener close = new WindowAdapter(
public void windowClosing(WindowEvent e){
System.exit(0);
}
);
这样比实现接口就轻松多了啊,把它整成抽象类,是因为他的方法都是空实现,显然拿到他的实例也没有用的

时间: 2024-10-29 20:18:02

详解 JAVA 适配模式和 接口适配器的相关文章

详解 JAVA 适配模式 和 接口适配器

JAVA适配模式 意图将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.(GoF) 场景 相信很多人都知道什么是显卡,也有很多人知道显卡的本名--图形适配器.恩,是的,正好这回说说Apater模式,就拿显卡来例子来分析一下Adapter模式. 我们知道显示器(Client)是用来显示图形的,它是不能显示数据,它只能够接受来自图形发送设备Target的信号.可是我们手头上只有CPU(Adaptee)这个产生各种描述图形的数据的数

Java设计模式详解之门面模式(外观模式)_java

门面模式(Facade Pattern)也叫外观模式,它隐藏系统的复杂性,并向客户端提供一个可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性,为子系统中的一组接口提供了一个统一的高层访问接口,这个接口使得子系统更容易被访问或使用.这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用. 简而言之,就是把一堆复杂的流程封装成一个接口供给用户更简单的使用,这个设计模式里有三个角色: 1)门面角色( facade ):

详解Java中的指针、引用及对象的clone

对象|详解 Java语言的一个优点就是取消了指针的概念,但也导致了许多程序员在编程中常常忽略了对象与引用的区别,本文会试图澄清这一概念.并且由于Java不能通过简单的赋值来解决对象复制的问题,在开发过程中,也常常要要应用clone()方法来复制对象.本文会让你了解什么是影子clone与深度clone,认识它们的区别.优点及缺点.看到这个标题,是不是有点困惑:Java语言明确说明取消了指针,因为指针往往是在带来方便的同时也是导致代码不安全的根源,同时也会使程序的变得非常复杂难以理解,滥用指针写成的

详解Java中的正则表达式

详解Java中的正则表达式,并列出常用的正则表达式语法和一些常用的场景. 判断一个字符串是否是由数字组成: 当不使用正则表达式的时候的实现代码: public class RegexDemo01 { public static void main(String[] args) { String s = "23432324"; char c[] = s.toCharArray();//将字符串转换成字符数组 for (int i = 0; i < c.length; i++) {

专家为您详解JAVA数据库基本操作

数据|数据库|详解 java 数据库基本操作1.java数据库操作基本流程2.几个常用的重要技巧:     可滚动.更新的记录集     批量更新     事务处理 java数据库操作基本流程:取得数据库连接 - 执行sql语句 - 处理执行结果 - 释放数据库连接 1.取得数据库连接  1)用DriverManager取数据库连接   例子    String className,url,uid,pwd;    className = "oracle.jdbc.driver.OracleDri

详解Java的堆内存与栈内存的存储机制_java

堆与内存优化    今天测了一个项目的数据自动整理功能,对数据库中几万条记录及图片进行整理操作,运行接近到最后,爆出了java.lang.outOfMemoryError,java heap space方面的错误,以前写程序很少遇到这种内存上的错误,因为java有垃圾回收器机制,就一直没太关注.今天上网找了点资料,在此基础上做了个整理.  一.堆和栈     堆-用new建立,垃圾回收器负责回收          1.程序开始运行时,JVM从OS获取一些内存,部分是堆内存.堆内存通常在存储地址的

详解java动态代理模式_java

本文针对java动态代理进行知识点整理,具体内容如下 一. JAVA的动态代理(比较官方说法) 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处 理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的 对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提 供特定的服务. 按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工

详解Java编程中的策略模式_java

策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 策略模式的结构 策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理.策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类.用一句话来说,就是:"准备一组算法,并将每一个算法封装起来,使得它们可以互换".下面就以一个示意性的实现讲解策略模式实例的结构. 这个

详解Java设计模式之备忘录模式的使用_java

定义与结构     备忘录(Memento)模式又称标记(Token)模式.GOF给备忘录模式的定义为:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 在讲命令模式的时候,我们曾经提到利用中间的命令角色可以实现undo.redo的功能.从定义可以看出备忘录模式是专门来存放对象历史状态的,这对于很好的实现undo.redo功能有很大的帮助.所以在命令模式中undo.redo功能可以配合备忘录模式来实现. 其实单就实现保存一个对