适配器模式(对象适配器学习笔记)

  1. 意图

  将一个类的接口装换成客户但愿的另一个接口java

  2. 动机

  有时,为复用而设计的工具类不可以被复用仅仅是由于它的接口与专业应用领域所须要的接口不匹配。Adapter常常还要负责提供那些被匹配的类所没有提供的功能(有点相似装饰模式)ide

  3. 适用性

  • 想使用一个已经存在的类,而它的接口不符合你的需求
  • 想要建立一个能够复用的类,该类能够与其余不相关的类或不可预见的类(即那些接口可能不必定兼容的类)协同工做
  • 复用一些类,它们处于同一继承体系,而且又有了一些共同的方法,可是这些共同的方法不是全部这一继承体系中的子类所共有的。不可能对每个都进行子类化以匹配它们的接口。对象适配器能够适配它的父类接口

  4. 结构

  

  5. 效果

  1) 容许一个Adapter与多个Adaptee——Adaptee自己以及它的全部子类——同时工做。Adapter能够一次给全部的Adaptee添加功能函数

  2) 使得重定义Adapter的行为比较困难。这就须要生成Adaptee的子类,而且使得Adapter引用这个子类而不是Adaptee自己工具

  3) 单一职责原则_你能够将接口或数据转换代码从程序主要业务逻辑中分离this

  4) 开闭原则。 只要客户端代码经过客户端接口与适配器进行交互, 你就能在不修改现有客户端代码的状况下在程序中添加新类型的适配器spa

  6. 代码实现

  让方钉适配圆孔

  round/RoundHole.java: 圆孔设计

package adapter.round;

/**
 * @author GaoMing
 * @date 2021/7/12 - 9:07
 * RoundHoles are compatible with RoundPegs.
 */
public class RoundHole {
    private double radius;

    public RoundHole(double radius) {
        this.radius = radius;
    }

    public double getRadius() {
        return radius;
    }

    public boolean fits(RoundPeg peg) {
        boolean result;
        result = (this.getRadius() >= peg.getRadius());
        return result;
    }
}

  round/RoundPeg.java: 圆钉  代理

package adapter.round;

/**
 * @author GaoMing
 * @date 2021/7/12 - 9:07
 */
public class RoundPeg {
    private double radius;

    public RoundPeg() {}

    public RoundPeg(double radius) {
        this.radius = radius;
    }

    public double getRadius() {
        return radius;
    }
}

  square/SquarePeg.java: 方钉code

package adapter.square;

/**
 * @author GaoMing
 * @date 2021/7/12 - 9:08
 * SquarePegs are not compatible with RoundHoles (they were implemented by
 * previous development team). But we have to integrate them into our program.
 */
public class SquarePeg {
    private double width;

    public SquarePeg(double width) {
        this.width = width;
    }

    public double getWidth() {
        return width;
    }

    public double getSquare() {
        double result;
        result = Math.pow(this.width, 2);
        return result;
    }
}

  adapters/SquarePegAdapter.java: 方钉到圆孔的适配器xml

package adapter.adapters;

import adapter.round.RoundPeg;
import adapter.square.SquarePeg;

/**
 * @author GaoMing
 * @date 2021/7/12 - 9:25
 * Adapter allows fitting square pegs into round holes.
 */
public class SquarePegAdapter extends RoundPeg {
    private SquarePeg peg;

    public SquarePegAdapter(SquarePeg peg) {
        this.peg = peg;
    }

    @Override
    public double getRadius() {
        double result;
        // Calculate a minimum circle radius, which can fit this peg.
        result = (Math.sqrt(Math.pow((peg.getWidth() / 2), 2) * 2));
        return result;
    }
}

  Demo.java: 客户端代码

package adapter;

import adapter.adapters.SquarePegAdapter;
import adapter.round.RoundHole;
import adapter.round.RoundPeg;
import adapter.square.SquarePeg;

/**
 * @author GaoMing
 * @date 2021/7/12 - 9:07
 */
public class Demo {
    public static void main(String[] args) {
        // Round fits round, no surprise.
        RoundHole hole = new RoundHole(5);
        RoundPeg rpeg = new RoundPeg(5);
        if (hole.fits(rpeg)) {
            System.out.println("Round peg r5 fits round hole r5.");
        }

        SquarePeg smallSqPeg = new SquarePeg(2);
        SquarePeg largeSqPeg = new SquarePeg(20);
        // hole.fits(smallSqPeg); // Won't compile.

        // Adapter solves the problem.
        SquarePegAdapter smallSqPegAdapter = new SquarePegAdapter(smallSqPeg);
        SquarePegAdapter largeSqPegAdapter = new SquarePegAdapter(largeSqPeg);
        if (hole.fits(smallSqPegAdapter)) {
            System.out.println("Square peg w2 fits round hole r5.");
        }
        if (!hole.fits(largeSqPegAdapter)) {
            System.out.println("Square peg w20 does not fit into round hole r5.");
        }
    }
}

  执行结果  

Round peg r5 fits round hole r5.
Square peg w2 fits round hole r5.
Square peg w20 does not fit into round hole r5.

 

  7. 与其余模式的关系

  • 桥接模式一般会于开发前期进行设计, 使你可以将程序的各个部分独立开来以便开发。 另外一方面, 适配器模式一般在已有程序中使用, 让相互不兼容的类能很好地合做
  • 适配器能够对已有对象的接口进行修改, 装饰模式则能在不改变对象接口的前提下强化对象功能。 此外, 装饰还支持递归组合, 适配器则没法实现
  • 适配器能为被封装对象提供不一样的接口, 代理模式能为对象提供相同的接口, 装饰则能为对象提供增强的接口 
  • 外观模式为现有对象定义了一个新接口, 适配器则会试图运用已有的接口。 适配器一般只封装一个对象, 外观一般会做用于整个对象子系统上

  8. 已知应用

  适配器模式在 Java 代码中很常见。 基于一些遗留代码的系统经常会使用该模式。 在这种状况下, 适配器让遗留代码与现代的类得以相互合做  

  • java.util.Arrays#asList()
  • java.util.Collections#list()
  • java.util.Collections#enumeration()
  • java.io.InputStreamReader(InputStream) (返回 Reader对象)
  • java.io.OutputStreamWriter(OutputStream) (返回 Writer对象)
  • javax.xml.bind.annotation.adapters.XmlAdapter#marshal() 和 #unmarshal()

  识别方法: 适配器能够经过以不一样抽象或接口类型实例为参数的构造函数来识别。 当适配器的任何方法被调用时, 它会将参数转换为合适的格式, 而后将调用定向到其封装对象中的一个或多个方法

相关文章
相关标签/搜索