Java设计模式——适配器模式及外观模式

Java设计模式之适配器模式和外观模式

适配器模式

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

  • 类适配器:多重继承完成,Java中不允许,高耦合
  • 对象适配器:只用组合完成,低耦合
  1. 创建目标接口
public interface Target {
    //这是源类Adapteee没有的方法
    public void Request(); 
}
  1. 创建被适配器
public class Adaptee {
    public void SpecificRequest(){
    }
}
  1. 创建适配器类(Adapter)
class Adapter implements Target{  
    // 直接关联被适配类  
    private Adaptee adaptee;  
    // 可以通过构造函数传入具体需要适配的被适配类对象  
    public Adapter (Adaptee adaptee) {  
        this.adaptee = adaptee;  
    }  
    @Override
    public void Request() {  
        // 这里是使用委托的方式完成特殊功能  
        this.adaptee.SpecificRequest();  
    }  
}  
  1. 适配器使用
public class AdapterPattern {
    public static void main(String[] args){
        //需要先创建一个被适配类的对象作为参数  
        Target mAdapter = new Adapter(new Adaptee());
        mAdapter.Request();

    }
}

适配器模式实际应用

JDK以前使用Enumeration枚举接口遍历,现在使用Iterator迭代器

public interface Enumeration<E> {
    boolean hasMoreElements();
    E nextElement();
}
public interface Iterator<E> {
    boolean hasNext();
    E next();
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
}

我们写一个适配器将枚举适配到迭代器

  • 目标接口:迭代器
  • 被适配接口:枚举接口

EnumerationhasMoreElements就对应IteratorhasNextnextElement对应next

Enumeration不支持remove,就像Iterator设计好的,抛出一个不支持的运行时异常。

public class EnumerationIteratorAdapter implements Iterator {
    private Enumeration enumeration;
    public EnumerationIteratorAdapter(Enumeration enumeration){
        this.enumeration = enumeration;
    }
    public boolean hasNext() {
        return enumeration.hasMoreElements();
    }
    public Object next() {
        return enumeration.nextElement();
    }
    public void remove() {
        throw new UnsupportedOperationException();
    }
}

测试:Vector

public static void main(String[] args) {
        Vector<Double> vector = new Vector<>();
        vector.add(12.21);
        vector.add(10.26);
        EnumerationIteratorAdapter enumerationIteratorAdapter = new EnumerationIteratorAdapter(vector.elements());
        double a;
        while (enumerationIteratorAdapter.hasNext()){
            a = (double) enumerationIteratorAdapter.next();
            System.out.println(a);
        }
    }

我们再写一个适配器将枚举适配到迭代器

  • 被适配接口:迭代器
  • 目标接口:枚举接口
public class IteratorEnumerationAdapter implements Enumeration {
    private Iterator iterator;
    public IteratorEnumerationAdapter(Iterator iterator){
        this.iterator = iterator;
    }
    public boolean hasMoreElements() {
        return iterator.hasNext();
    }
    public Object nextElement() {
        return iterator.next();
    }
}

测试:ArrayList

ArrayList<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        IteratorEnumerationAdapter iteratorEnumerationAdapter = new IteratorEnumerationAdapter(list.iterator());
        String a = "";
        while (iteratorEnumerationAdapter.hasMoreElements()){
            a = (String) iteratorEnumerationAdapter.nextElement();
            System.out.println(a);
        }

装饰者和适配器

  • 适配器:存在不被客户知道,客户只知道请求对应的行为,适配器帮助客户和被适配者解耦,将一个接口转换为另一个接口
  • 装饰者:不改变接口,但加入责任
  • 适配器将一个对象包装起来以改变其接口,装饰者将对象包装起来以增加新的行为或者责任。

外观模式

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

新的设计原则

  • 最少设计原则:只和你的密友谈话

设计中不要让太多的类耦合在一起,免得修改系统中的一部分又会影响到另一部分。如果系统各个部分依赖太多,这个系统会需要大量成本维护。

像下面这个代码:

public void getTemp(){
    //耦合了三个类
    return station.getFirstTemp().getSecondTemp();
}

该原则缺点:

虽然减少了对象的依赖,但是也会导致更多的类被创建出来用于处理组件的沟通,导致系统复杂度高,并且降低性能。

外观模式的使用

一个私人影院由多个子系统构成:DVD播放器、投影仪、自动屏幕、环绕立体声、爆米花机

你每次观影之前需要做很多准备工作,结束还要做很多清理工作

我们可以使用外观模式,提供一个更合理的接口类,简化你的子系统的使用。

  • 该外观接口中有watchMovie方法,里面综合了各个子系统需要做的一切准备工作
  • endMovie方法综合了所有的清理工作

接口

public interface HomeTheaterFacadeAPI {
    public void watchMovie();
    public void endMovie();
}
public class HomeTheaterFacade implements HomeTheaterFacadeAPI{
    private Amplifier amplifier;
    private CDplayer cDplayer;
    private DVDplayer dvDplayer;
    private PopCornPopper popCornPopper;
    private Screen screen;
    private TheaterLight theaterLight;
    private Projector projector;
    public HomeTheaterFacade(Amplifier amplifier,
                             CDplayer cDplayer,
                             DVDplayer dvDplayer,
                             PopCornPopper popCornPopper,
                             Screen screen,
                             TheaterLight theaterLight,
                             Projector projector){
        this.amplifier = amplifier;
        this.cDplayer = cDplayer;
        this.dvDplayer = dvDplayer;
        this.popCornPopper = popCornPopper;
        this.screen = screen;
        this.theaterLight = theaterLight;
        this.projector = projector;
    }
    public void watchMovie() {
        System.out.println("准备开始看电影");
        popCornPopper.on();
        popCornPopper.pop();
        theaterLight.dim(10);
        screen.down();
        projector.open();
        amplifier.on();
        amplifier.setDvdAndCd();
        amplifier.setVolume(20);
        dvDplayer.open();
        cDplayer.open();
    }
    public void endMovie() {
        System.out.println("正在关闭设备");
        popCornPopper.close();
        theaterLight.close();
        screen.up();
        projector.close();
        amplifier.close();
        dvDplayer.close();
        cDplayer.close();
    }
}

外观模式和适配器的使用

  • 当需要一个现有类而接口不符合要求时,使用适配器。
  • 当需要简化并统一一个很大的接口或者一群很复杂接口时,使用外观。(将客户和子系统解耦)

代码地址:Github适配器模式 Github外观模式


Java设计模式|策略模式

Java设计模式|观察者模式

Java设计模式|装饰者模式

Java设计模式|工厂模式

Java设计模式|命令模式

Java设计模式|适配器模式和外观模式

Java设计模式|模板方法模式

Java设计模式|迭代器模式和组合模式

Java设计模式|状态模式

Java设计模式|代理模式

Java设计模式|单例模式

Java设计模式|备忘录模式

Java设计模式|访问者模式

Java设计模式|复合模式

Java设计模式|桥接模式

Java设计模式|生成器模式

Java设计模式|享元模式/蝇量模式

Java设计模式|原型模式

Java设计模式|责任链模式

Java设计模式|中介者模式

  • 本文作者: dzou | 微信:17856530567
  • 本文链接: http://www.dzou.top/post/519a7c00.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
  • 并保留本声明和上方二维码。感谢您的阅读和支持!