Adapter适配器模式(参考《java与设计模式》

为什么要有适配器模式?

系统在初期规划时设计了一个Target类,然后第三方提供了一个实现与Target功能的Adaptee类,但此时Target因为与系统其他部分都有联系,Adaptee已经设计好了,两者可能都不可修改了,此时为了调用Adaptee这一目的就需要通过一个Adapter来作为一个中介帮助。因为Adapter是Target的子类或者继承了他的接口,根据里氏代换原则,只需在

如何实现适配器模式?

类适配器

适配器继承需要通信的两个类,然后在目标类的方法中调用源类的方法,因为java是单继承的,所以目标类和源类一个是类一个是接口。

对象适配器

适配器类继承目标接口,然后在适配器类中持有源类的引用。

两者的区别是:因为java等语言是单继承的,所以对应类适配器,一个适配器只能给一个源类使用。对象适配器虽然可以将多个源Adaptee适配到同一个Target类但是她的缺点是,源类Adaptee各种方法深入Adatper类想要去掉一个很难全部找到,有时只能通过生成该Adaptee的子类然后重写它的方法,让Adapter持有这个子类来解决。不过对象适配器增加一个源类却是非常方便的。

UML类图

类适配器


对象适配器



代码示例

类适配器

package com.company;

public interface Target{
    void sampleOperation1();
    void sampleOperation2();
}
package com.company;

public class Adaptee {
    public void sampleOperation1(){};
}
package com.company;

public class Adapter extends Adaptee implements Target{

    @Override
    public void sampleOperation2() {
        //此方法为适配器类扩展Adaptee源类来满足目标接口
    }
}

对象适配器

Adaptee与Target和类适配器一样Adapter修改成

package com.company;

public class Adapter implements Target{

    private Adaptee adaptee;
    public Adapter(Adaptee adaptee){
        super();
        this.adaptee=adaptee;
    }
    @Override
    public void sampleOperation1() {
        adaptee.sampleOperation1();
    }

    @Override
    public void sampleOperation2() {
        //此方法为适配器类扩展Adaptee源类来满足目标接口
    }
}

例题java jdk 1.0 1.1 没有聚集框架,因此访问集合等类时使用的是Enumeration,在jdk 1.2出现后Iterator接口成为了访问聚集框架的标准,但是为了兼容以前的版本我们需要各实现一个集合类来实现Iterator到Enumeration之间的互相转变。

Iterator To Enumeration

package com.company;

import java.util.Enumeration;
import java.util.Iterator;

public class Itermeration implements Enumeration {

    private Iterator it;
    public Itermeration(Iterator it){
        this.it=it;
    }
    @Override
    public boolean hasMoreElements() {
        return it.hasNext();
    }

    @Override
    public Object nextElement() {
        return it.next();
    }
}

Enumeration To Iterator

因为Iterator接口中比Enumeration多remove和forEachRemaining两个函数,因此要在调用这两个函数的时候抛出异常

package com.company;

import java.util.Enumeration;
import java.util.Iterator;
import java.util.function.Consumer;

public class Enuterator implements Iterator {
    
    private Enumeration myEnum;
    
    public Enuterator(Enumeration myEnum)
    {
        this.myEnum=myEnum;
    }
    @Override
    public boolean hasNext() {
        return myEnum.hasMoreElements();
    }

    @Override
    public Object next() {
        return myEnum.nextElement();
    }
    
    public void remove(){
        throw new UnsupportedOperationException();
    }

    @Override
    public void forEachRemaining(Consumer action) {
        throw new UnsupportedOperationException();
    }
}

适配器模式在java中的应用

JDBC:不同的数据库是提供的接口是不同的,但是java操作SQL的方法是固定的,因此JDBC就是一个适配器的作用,来让java可以调用不同的数据库

AWT事件中各种个样的适配器:

注意这些适配器都是抽象类但是缺省实现了各种方法。

比如MouseAdapter

package java.awt.event;

/**
 * An abstract adapter class for receiving mouse events.
 * The methods in this class are empty. This class exists as
 * convenience for creating listener objects.
 * <P>
 * Mouse events let you track when a mouse is pressed, released, clicked,
 * moved, dragged, when it enters a component, when it exits and
 * when a mouse wheel is moved.
 * <P>
 * Extend this class to create a {@code MouseEvent}
 * (including drag and motion events) or/and {@code MouseWheelEvent}
 * listener and override the methods for the events of interest. (If you implement the
 * {@code MouseListener},
 * {@code MouseMotionListener}
 * interface, you have to define all of
 * the methods in it. This abstract class defines null methods for them
 * all, so you can only have to define methods for events you care about.)
 * <P>
 * Create a listener object using the extended class and then register it with
 * a component using the component's {@code addMouseListener}
 * {@code addMouseMotionListener}, {@code addMouseWheelListener}
 * methods.
 * The relevant method in the listener object is invoked  and the {@code MouseEvent}
 * or {@code MouseWheelEvent}  is passed to it in following cases:
 * <ul>
 * <li>when a mouse button is pressed, released, or clicked (pressed and  released)
 * <li>when the mouse cursor enters or exits the component
 * <li>when the mouse wheel rotated, or mouse moved or dragged
 * </ul>
 *
 * @author Carl Quinn
 * @author Andrei Dmitriev
 *
 * @see MouseEvent
 * @see MouseWheelEvent
 * @see MouseListener
 * @see MouseMotionListener
 * @see MouseWheelListener
 * @see <a href="https://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html">Tutorial: Writing a Mouse Listener</a>
 *
 * @since 1.1
 */
public abstract class MouseAdapter implements MouseListener, MouseWheelListener, MouseMotionListener {
    /**
     * {@inheritDoc}
     */
    public void mouseClicked(MouseEvent e) {}

    /**
     * {@inheritDoc}
     */
    public void mousePressed(MouseEvent e) {}

    /**
     * {@inheritDoc}
     */
    public void mouseReleased(MouseEvent e) {}

    /**
     * {@inheritDoc}
     */
    public void mouseEntered(MouseEvent e) {}

    /**
     * {@inheritDoc}
     */
    public void mouseExited(MouseEvent e) {}

    /**
     * {@inheritDoc}
     * @since 1.6
     */
    public void mouseWheelMoved(MouseWheelEvent e){}

    /**
     * {@inheritDoc}
     * @since 1.6
     */
    public void mouseDragged(MouseEvent e){}

    /**
     * {@inheritDoc}
     * @since 1.6
     */
    public void mouseMoved(MouseEvent e){}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值