设计模式3.1&3.2 适配器模式与缺省适配模式


点击进入我的博客

3.1 适配器模式

适配器模式把一个类的接口变换成客户端所期待的另一种接口,使得原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

3.1.1 类的适配器结构

设计模式3.1&3.2 适配器模式与缺省适配模式_第1张图片
类的适配器
  • 目标(Target)角色:这就是所期待得到的接口,由于是类适配器模式,因此目标不可以是类。
  • 源(Adaptee)角色:现有需要适配的接口。
  • 适配器(Adapter)角色:适配器类是本模式的核心,必须是具体类。
interface Target {
    void operation1();
    void operation2();
}

class Adaptee {
    public void operation1() {}
}

class Adapter extends Adaptee implements Target {
    @Override
    public void operation2() {}
}
类的适配器
  • 类的适配器模式把被的类的API转换成目标类的API。
  • 是通过继承实现的。
类的适配器效果
  • 使用一个具体类把源适配到目标中。这样如果源以及源的子类都使用此类适配,就行不通了。
  • 由于适配器是源的子类,因此可以在适配器中重写源的一些方法。
  • 由于引进了一个适配器类,因此只有一个线路到达目标类,是问题得到简化。

3.1.2 对象的适配器结构

设计模式3.1&3.2 适配器模式与缺省适配模式_第2张图片
对象适配器
  • 目标(Target)角色:这就是所期待得到的接口,因此目标可以是具体或抽象的类
  • 源(Adaptee)角色:现有需要适配的接口。
  • 适配器(Adapter)角色:适配器类是本模式的核心,必须是具体类。
interface Target {
    void operation1();
    void operation2();
}

class Adaptee {
    public void operation1() {}
}

class Adapter implements Target {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void operation1() {
        adaptee.operation1();
    }

    @Override
    public void operation2() {
        // do something
    }
}
对象的适配器
  • 对象的适配器是通过依赖实现的
  • 推荐使用该方法
对象的适配器效果
  • 一个适配器可以把多种不同的源适配到同一个目标,即同一个适配器可以把源类和它的子类都适配到目标接口
  • 与类的适配器模式相比,要想置换源类的方法就不容易。
  • 增加新的方法方便的多

3.1.3 细节

使用场景
  1. 系统需要使用现有的类,而此类的接口不符合系统的需要
  2. 想要建立一个可以重复使用的类,用于与一些彼此间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
  3. 对对象的适配器儿模式而言,在设计里,需要改变多个已有的子类的接口,如果使用类的适配器模式,就需要针对每个子类做一个适配器类,这不太实际。
优点
  1. 可以让任何两个没有关联的类一起运行。
  2. 提高了类的复用。
  3. 增加了类的透明度。
  4. 灵活性好。
缺点
  1. 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
  2. 由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
注意点
  1. 目标接口可以忽略,此时目标接口和源接口实际上是相同的
  2. 适配器类可以是抽象类
  3. 可以有带参数的适配器模式

3.1.4 一个充电器案例

// 充电器只能接受USB接口
public class Charger {
    public static void main(String[] args) throws Exception{
        USB usb = new SuperAdapter(new TypeC());
        connect(usb);
        usb = new SuperAdapter(new Lightning());
        connect(usb);
    }

    public static void connect(USB usb) {
        usb.power();
        usb.data();
    }
}

// 充电器的接口都是USB的,假设有两个方法分别是电源和数据
interface USB {
    void power();
    void data();
}

// IOS的Lightning接口
class Lightning {
    void iosPower() {
        System.out.println("IOS Power");
    }
    void iosData() {
        System.out.println("IOS Data");
    }
}

// TYPE-C接口
class TypeC {
    void typeCPower() {
        System.out.println("TypeC Power");
    }
    void typeCData() {
        System.out.println("TypeC Data");
    }
}

// 超级适配器,可以适配多种手机机型
class SuperAdapter implements USB {
    private Object obj;

    public SuperAdapter(Object obj) {
        this.obj = obj;
    }

    @Override
    public void power() {
        if(obj.getClass() == Lightning.class) {
            ((Lightning)obj).iosPower();
        } else if(obj.getClass() == TypeC.class) {
            ((TypeC)obj).typeCPower();
        }
    }

    @Override
    public void data() {
        if(obj.getClass() == Lightning.class) {
            ((Lightning)obj).iosData();
        } else if(obj.getClass() == TypeC.class) {
            ((TypeC)obj).typeCData();
        }
    }
}

3.2 缺省适配模式

缺省适配模式为一个接口提供缺省实现,这样子类型可以从这个缺省实现进行扩展,而不必从原有接口进行扩展。

3.2.1 缺省适配模式结构

设计模式3.1&3.2 适配器模式与缺省适配模式_第3张图片
缺省适配模式
简单的例子
  • 下面程序中,Monk接口定义了两个方法,于是它的子类必须实现这两个方法。
  • 但出现了一个LuZhiShen,他只能实现一部分方法,另一部分方法无法实现
  • 所以需要一个抽象的适配类MonkAdapter实现此Monk接口,此抽象类给接口所有方法都提供一个空的方法,LuZhiShen只需要继承该适配类即可。
// 和尚
interface Monk {
    void practiceKungfu();
    void chantPrayer();
}

abstract class MonkAdapter implements Monk {
    @Override
    public void practiceKungfu() {}

    @Override
    public void chantPrayer() {}
}

class LuZhiShen extends MonkAdapter {
    @Override
    public void practiceKungfu() {
        System.out.println("拳打镇关西");
    }
}

3.2.2 细节

使用场景
  • 任何时候不准备实现一个接口中所有方法的时候
作用

缺省适配器模式可以使所需要的类不必实现不需要的接口。

核心点
  • 缺省适配的类必须是抽象类,因为这个类不应当被实例化
  • 缺省适配的类提供的方法必须是具体的方法,而不是抽象的方法。

你可能感兴趣的:(设计模式3.1&3.2 适配器模式与缺省适配模式)