写给自己看的设计模式之《适配器模式》

一. 介绍

即定义一个包装类,用于包装不兼容的对象

包装类 = adapter
被包装类 = adaptee

1.1 场景

  • 系统需要复用现有类,而该类的接口不符合系统的需求
  • 多个组件功能类似,但接口不统一且可能会经常切换

1.2 优点

  • 更好的复用性
    系统需要使用现有的类,而此类的接口不符合系统的需要
  • 透明、简单
    客户端可以调用同一接口,因而对客户端来说是透明的
  • 更好的扩展性
    在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能
  • 解耦性
    将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码
  • 符合开放-关闭原则
    同一个适配器可以把适配者类和它的子类都适配到目标接口;可以为不同的目标接口实现不同的适配器,而不需要修改待适配类

1.3 缺点

  • 过多的使用适配器,会让系统非常零乱,不易整体进行把握

1.4 分类

  • 类的适配器
  • 对象的适配器

二. 类的适配器

使用继承关系,将被包装类的方法转换成目标方法

2.1 场景

  • 需要重新定义Adaptee的部分行为
  • 希望使用方便时

2.2 优点

  • 使用方便,代码简化
    仅仅引入一个对象,并不需要额外的字段来引用Adaptee实例
    缺点

2.3 缺点

  • 高耦合,灵活性低
    使用对象继承的方式,是静态的定义方式

2.4 使用

1. 创建目标接口
public interface Target {
    
    
    void requestFnc();
}

2. 创建被包装的类
public class Adaptee {
    
    
    public void sourceFnc() {
    
    
        System.out.println("adaptee fnc.");
    }
}

3. 创建适配类
/**
 * 类的适配器模式:使用继承关系连接到Adaptee类
 *
 * @author dkangel
 */
public class ClassAdapter extends Adaptee implements Target {
    
    
    /**
     * 适配目标方法
     */
    @Override
    public void requestFnc() {
    
    
        super.sourceFnc();
        System.out.println("convert sourceFnc to requestFnc.");
    }
}

4. 使用
public class Main {
    
    
    public static void main(String[] args) {
    
    
        Target target = new ClassAdapter();
        target.requestFnc();
    }
}

三. 对象的适配器

与类的适配器一样,将被包装类的方法转换成目标方法

不同:类的适配器使用继承关系连接adaptee,对象的适配器使用委派关系连接adaptee

2.1 场景

  • 灵活使用时
  • 需要同时配源类和其子类

2.2 优点

  • 灵活性高、低耦合
    采用对象组合的方式,是动态组合方式

2.3 缺点

  • 使用复杂
    需要引入对象实例

2.4 使用

1. 创建目标接口
public interface Target {
    
    
    void requestFnc();
}

2. 创建被包装的类
public class Adaptee {
    
    
    public void sourceFnc() {
    
    
        System.out.println("adaptee fnc.");
    }
}

3. 创建适配类
/**
 * 对象的适配器模式:使用委派关系连接到Adaptee类
 *
 * @author dkangel
 */
public class ObjAdapter implements Target {
    
    

    private Adaptee adaptee;

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

    @Override
    public void requestFnc() {
    
    
        this.adaptee.sourceFnc();
        System.out.println("convert sourceFnc to requestFnc.");
    }
}

猜你喜欢

转载自blog.csdn.net/Dkangel/article/details/105725574