Adapter Patterns

GoF定义:将一个类的接口转换为客户端接受的另一个接口。这个模式让接口不兼容的类也能正常工作

概念

最好的说明这个模式的方式就是例子(【滑稽】)

例子

现实世界:手机充电器为例,如果没有支持这个充电器的插板,那么可以使用适配器来辅助充电。翻译工作也算是这个模式的一个例子
代码世界:有时因为两个接口有各自不同的特性,不能让它们一起工作,这时可以通过适配器来解决问题

展示

这个例子中,Calculator可以直接计算一个长方形的面积,如果我们希望通过这个类的getArea方法获取三角形的面积,应该怎么办?这里我们创建一个CalculatorAdapter类,将三角形作为参数传入它的getArea方法,实际上调用的还是Calculator中的同名方法,得到的三角形面积,但对于用户来说,这个操作和直接将三角形传入Calculator没有区别

代码

public class AdapterPatternEx
{
    public static void main(String[] args)
    {
        System.out.println("***Adapter Pattern Demo***");
        CalculatorAdapter cal=new CalculatorAdapter();
        Triangle t = new Triangle(20,10);
        System.out.println("\nAdapter Pattern Example\n");
        System.out.println("Area of Triangle is :" + cal.getArea(t));
    }
}

class Rect
{
    public double l;
    public double h;
}

class Triangle
{
    // 底
    public double b;
    public double h;

    public Triangle(double b, double h)
    {
        this.b = b;
        this.h = h;
    }
}

class Calculator
{
    public double getArea(Rect r)
    {
        return r.l * r.h;
    }
}

class CalculatorAdapter
{
    public double getArea(Triangle t)
    {
        Calculator calculator = new Calculator();
        Rect r = new Rect();
        r.h = t.h * 0.5;
        r.l = t.b;
        return calculator.getArea(r);
    }
}

另一种形式

GoF指出有两种主要的适配器模式

  1. 使用多继承来实现类之间的适配(Java不支持多继承,所以需要通过接口来实现这种适配方式)
  2. 对象适配,依赖对象的构成

上述UML展示了这两种概念

public class OtherAdapterEx
{
    public static void main(String[] args)
    {
        System.out.println("***Class and Object Adapter Demo***"); 
        ClassAdapter ca1=new ClassAdapter();
        System.out.println("Class Adapter is returning :"+ca1.getIntValue());
        
        ClassAdapter ca2=new ClassAdapter();
        ObjectAdapter oa=new ObjectAdapter(new IntegerValue()); 
        System.out.println("Object Adapter is returning :"+oa.getIntValue());
    }
}

interface IIntegerValue
{
    int getIntValue();
}

// 接口的实现类(正常只需要这个类)
class IntegerValue implements IIntegerValue
{
    @Override
    public int getIntValue()
    {
        return 5;
    }
}

// 类上的适配器,子类在同样的实现方法中做一些改变(结果可能不同)
class ClassAdapter extends IntegerValue
{
    @Override
    public int getIntValue()
    {
        return 2 + super.getIntValue();
    }
}

class ObjectAdapter implements IIntegerValue
{
    IntegerValue integerValue;

    public ObjectAdapter(IntegerValue integerValue)
    {
        this.integerValue = integerValue;
    }

    @Override
    public int getIntValue()
    {
        return 2 + this.integerValue.getIntValue();
    }
}

适配器在适配对象时应该考虑到什么程度?
如果适配目标和被适配目标接口很相似,那么用适配器模式并没有太大作用。如果两个接口并没有那么多的相似性,那么适配器就要做很多额外工作来匹配不同接口的功能

思考

  1. 适配器模式中,类适配就是将那个不适配的类改成一个构造器;而对象适配是单独定义一个适配器,接收被适配对象然后进行改造原功能
  2. 此模式中,被适配的类起码在语义上和适配类是有关系的(假设是求面积,那么被适配的类起码具备面积这个属性)
  3. 适配器模式就是想尽量少的定义功能,即减少不同的接口但是具有相同方法的情况(RecInterface/TriangleInterface中都有一个getArea方法)
posted on 2020-11-29 17:08  老鼠不上树  阅读(77)  评论(0)    收藏  举报