适配器模式

适配器模式

1.在软件设计中也可能出现:需要开发的具有某种业务功能的组件在现有的组件库中已经存在,但它们与当前系统的接口规范不兼容,如果重新开发这些组件成本又很高,这时用适配器模式能很好地解决这些问题。

在适配器模式中,我们通过增加一个新的适配器类来解决接口不兼容的问题,使得原本没有任何关系的类可以协同工作。根据适配器类与适配者类的关系不同,适配器模式可分为对象适配器和类适配器两种,在对象适配器模式中,适配器与适配者之间是关联关系;在类适配器模式中,适配器与适配者之间是继承(或实现)关系。

2.结构
Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。

Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。

Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。

3.实现

3.1 对象适配器模式

/**
 * 被适配者
 */
public interface Turkey {
    void gobble(); // 火鸡叫声
    void fly();
}
/**
 * 被适配则实现类
 */
public class WildTurkey implements Turkey{
    @Override
    public void gobble() {
        System.out.println("Go Go!");
    }

    @Override
    public void fly() {
        System.out.println("我正在短距离飞行!");
    }
}
/**
 * 目标对象鸭子
 */
public interface Duck {
    void quack();//鸭子叫声
    void fly();
}

适配器:

/**
 * 在外面表现是 鸭子(目标),但是实质是火鸡(被适配者)
 */
public class TurkeyAdapter implements Duck { //实现目标的接口

    private Turkey turkey; //这种对象型适配器必须要组合  被适配者,也就是要有适配者的引用

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

    // 实际是火鸡在叫
    @Override
    public void quack() {
        turkey.gobble();//外面表现是quack,但是内部是turkey.gobble()
    }

    @Override
    public void fly() {
        //由于火鸡飞的短,所以多飞几次,让火鸡更像鸭子
        for(int i = 0; i < 6; i++){
            turkey.fly();
        }
    }
}

测试

public class MyTest {

    public static void main(String[] args) {
        WildTurkey turkey = new WildTurkey();
        Duck duck = new TurkeyAdapter(turkey);
        duck.quack(); //看似是鸭子,其实内置是火鸡
        duck.fly();
    }
}

3.2 类适配器模式

/**
 * 和 对象适配器模式唯一的不同就是  : 适配器直接继承 被适配者 (而不是组合)
 */
public class TurkeyAdapter extends WildTurkey implements  Duck {

    @Override
    public void quack() {
        super.gobble(); //直接继承 被适配者
    }

    @Override
    public void fly() {
        //让火鸡飞6次,飞的像鸭子
        super.fly();
        super.fly();
        super.fly();
        super.fly();
        super.fly();
        super.fly();
    }
}

测试:

public class MyTest {

    public static void main(String[] args) {
        TurkeyAdapter duck = new TurkeyAdapter();//直接new即可
        duck.quack();
        duck.fly();
    }
}

4.该模式的主要优点如下。

  • 客户端通过适配器可以透明地调用目标接口。
  • 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
  • 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。

其缺点是:对类适配器来说,更换适配器的实现过程比较复杂。

适配器模式是在现有的类和系统都不易修改的情况下使用,在系统设计之初慎用适配器模式。

测试

public class MyTest {

    public static void main(String[] args) {
        WildTurkey turkey = new WildTurkey();
        Duck duck = new TurkeyAdapter(turkey);
        duck.quack(); //看似是鸭子,其实内置是火鸡
        duck.fly();
    }
}

3.2 类适配器模式

/**
 * 和 对象适配器模式唯一的不同就是  : 适配器直接继承 被适配者 (而不是组合)
 */
public class TurkeyAdapter extends WildTurkey implements  Duck {

    @Override
    public void quack() {
        super.gobble(); //直接继承 被适配者
    }

    @Override
    public void fly() {
        //让火鸡飞6次,飞的像鸭子
        super.fly();
        super.fly();
        super.fly();
        super.fly();
        super.fly();
        super.fly();
    }
}

测试:

public class MyTest {

    public static void main(String[] args) {
        TurkeyAdapter duck = new TurkeyAdapter();//直接new即可
        duck.quack();
        duck.fly();
    }
}

4.该模式的主要优点如下。

  • 客户端通过适配器可以透明地调用目标接口。
  • 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
  • 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。

其缺点是:对类适配器来说,更换适配器的实现过程比较复杂。

适配器模式是在现有的类和系统都不易修改的情况下使用,在系统设计之初慎用适配器模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值