设计模式适配器模式

7次阅读

共计 2178 个字符,预计需要花费 6 分钟才能阅读完成。

我们周围的适配器

比方说:如果你需要在欧洲国家使用美国制造的笔记本电脑,你可能需要使用一个交流电的适配器 ……

适配器改变了插座的接口,以符合美式笔记本电脑的需求。


面向对象适配器

假设已经有一个软件系统,你希望它能和一个新的厂商类库搭配使用,但是这个新的厂商设计出来的接口不同于旧的厂商的接口

要解决这个问题,可以写一个适配器类来将新的厂商接口转换成你所期待的接口


火鸡转换器

如果它走起路来像只鸭子,叫起来像只鸭子,那么它 必定 可能是一只 鸭子 包装了鸭子适配器的火鸡

鸭子接口

public interface Duck {
    /**
     * 叫
     */
    public void quack();

    /**
     * 飞
     */
    public void fly();}

绿头鸭子是鸭子的子类

public class MallardDuck implements Duck {
    @Override
    public void quack() {System.out.println("Quack");
    }

    @Override
    public void fly() {System.out.println("I'm flying");
    }
}

火鸡接口

public interface Turkey {
    /**
     * 叫
     */
    public void gobble();

    /**
     * 飞
     */
    public void fly();}

火鸡的实现类

public class WildTurkey implements Turkey {

    @Override
    public void gobble() {System.out.println("Gobble gobble");
    }

    @Override
    public void fly() {System.out.println("I'm flying short distance");
    }
}

现在,假如我们缺鸭子对象,需要一些火鸡来冒充,然而因为火鸡和鸭子的接口不同,不能直接拿来使用,需要编写一个适配器

public class TurkeyAdapter implements Duck {
    
    Turkey turkey;

    public TurkeyAdapter(Turkey turkey) {this.turkey = turkey;}

    public void quack() {turkey.gobble();
    }

    public void fly() {for (int i = 0; i < 5; i++) {turkey.fly();
        }
    }
}

测试

public class DuckTest {public static void main(String[] args) {MallardDuck duck = new MallardDuck();
        WildTurkey turkey = new WildTurkey();
        TurkeyAdapter turkeyAdapter = new TurkeyAdapter(turkey);
        System.out.println("Turkey-------------------------");

        turkey.gobble();
        turkey.fly();
        System.out.println("Duck--------------------------");
        testDuck(duck);

        System.out.println("TurkeyAdapter---------------");
        testDuck(turkeyAdapter);

    }

    static void testDuck(Duck duck){duck.quack();
        duck.fly();}
}

测试结果


适配器模式解析

定义

将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。

上文已经看到了适配器模式的例子,现在来看它的类图

对象和类的适配器

对象适配器的类图

  • Target 目标角色
    该角色定义把其他类转换为何种接口,也就是我们的期望接口,例子中的 IUserInfo 接口就是目标角色。
  • Adaptee 源角色
    你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象,经过适配器角色的包装,它会成为一个崭新、靓丽的角色。
  • Adapter 适配器角色
    适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:把源角色转换为目标角色,怎么转换?通过继承或是类关联的方式。
类适配器的类图

在 java 中是不可能实现类适配器的,因为需要多重继承才能实现它,它和对象适配器的唯一区别就是类适配器继承了 Target 和 Adaptee,而对象适配器利用组合的方式将请求传送给适配器。

适配器模式的优点

  • 适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定
    他们就成。
  • 增加了类的透明性
    想想看,我们访问的 Target 目标角色,但是具体的实现都委托给了源角色,而这些对高
    层次模块是透明的,也是它不需要关心的。
  • 提高了类的复用度
    当然了,源角色在原有的系统中还是可以正常使用,而在目标角色中也可以充当新的演
    员。
  • 灵活性非常好
    某一天,突然不想要适配器,没问题,删除掉这个适配器就可以了,其他的代码都不用
    修改,基本上就类似一个灵活的构件,想用就用,不想就卸载

适配器模式的使用场景

你有动机修改一个已经投产中的接口时,适配器模式可能是最适合你的模式。比如系统扩展了,需要使用一个已有或新建立的类,但这个类又不符合系统的接口,怎么办?使用适配器模式。

正文完
 0