设计模式----适配器模式

概述

适配器模式(Adapter Pattern):消除类、对象、接口不匹配而造成的的兼容性问题,起桥梁作用

根据使用可以归结为三类

适配模式描述
类适配将一个类转换成满足另一个新接口的类——创建一个新类,继承原有的类,实现新的接口
对象适配将一个对象转换成满足另一个新接口的对象——持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就行
接口适配不希望实现一个接口中所有的方法——抽象类实现所有方法,新创建类时,继承抽象类

涉及角色

  • target
    对象:该角色负责定义所需的方法
  • client
    请求者:该角色负责使用target角色所定义的方法进行具体处理
  • adaptee
    被适配:持有特定方法的角色
  • adapter
    适配:使用adaptee角色的方法来满足target角色的需求,这是adapter模式的目的,也是adapter角色的作用。

UML

对于适配模式有两种形式的实现:1、使用继承;2、使用委托,即持有一个适配的对象

这里写图片描述

这里写图片描述

使用场景

  • 需要使用现有的类,而此类的接口不符合系统的需要
  • 需要要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口
  • 通过接口转换,将一个类插入另一个类系中
  • 需要使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口(仅对象适配)

优点

  • 更好的复用性
    系统需要使用现有的类,而此类的接口不符合系统的需要,那么通过使用适配器模式可以使这些功能得到更好的复用。
  • 更好的扩展性
    在实现适配器的功能时,可以调用自己开发的功能,从而扩展系统的功能:可以让任何两个没有关联的类一起运行;灵活性好;提高了类的复用

缺点

  • 过多地使用适配器,会让系统非常零乱,不易整体进行把握
  • 由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类

代码示例

按照上面的分类一个个演示

类的适配器

比如上个世纪的电视,基本只能看电视,现在的多媒体电视可以干很多事情,比如玩游戏等~,但看电视的功能没有变化,我们只需要实现玩游戏的相关调用逻辑即可~

有几个组成部分:待适配类,目标接口、适配器、测试类

package com.designpattern.adapter;

public class TV {
    public void watchTV() {
        System.out.println("watch television");
    }
}

定义新接口,包含待适配来类中的方法(同名)

package com.designpattern.adapter;

public interface MultimediaTV {
    public void watchTV();
    public void playGame();
}

要点:继承待适配类并实现目标接口,覆盖新定义的接口方法~

package com.designpattern.adapter;

public class AdapterClass extends TV implements MultimediaTV {


    @Override
    public void playGame() {
        // TODO Auto-generated method stub
        System.err.println("play game");
    }

}
package com.designpattern.adapter;

public class TestMain {
    public static void main(String[] args) {
        MultimediaTV multimediaTV = new AdapterClass();
        multimediaTV.watchTV();
        multimediaTV.playGame();
    }
}
watch television
play game

对象适配器

对象适配器,相对于类适配器不继承待适配的类,而是持有待适配类的实例,来解决兼容性

package com.designpattern.adapter;

public class TV {
    public void watchTV() {
        System.out.println("watch television");
    }
}

定义新接口(与类适配不同,这里的方法名可以自定义,可以不同名,因为在这里会调用对象的方法)

package com.designpattern.adapter;

public interface MultimediaTV {
    public void watchTV();
    public void playGame();
}
package com.designpattern.adapter;

public class AdapterObject  implements MultimediaTV {

    private TV tv;

    public AdapterObject(TV tv) {
        // TODO Auto-generated constructor stub
        this.tv=tv;
    }

    @Override
    public void watchTV() {
        // TODO Auto-generated method stub
        tv.watchTV();
    }
    @Override
    public void playGame() {
        // TODO Auto-generated method stub
        System.err.println("play game in AdapterObject");
    }
}
package com.designpattern.adapter;

public class TestMainObject {
    public static void main(String[] args) {

        TV tv = new TV();

        MultimediaTV multimediaTV = new AdapterObject(tv);
        multimediaTV.watchTV();
        multimediaTV.playGame();
    }
}

接口适配器

解决同一个接口的多个实现之间的重复代码(或者不必要的代码)。可以同一个一个抽象类实现所有未实现的方法,然后使用时继承该抽象类,覆盖相应的方法,达到减少不必要的代码。
比如还以多媒体电视为例
多媒体电视有多个品牌,抽象出来一个公共部分,使用一个抽象电视类实现所有多媒体电视定义的接口。在定义具体电视类时,继承该抽象类,覆盖相应的方法。

package com.designpattern.adapter;

public interface MediaTV {
    public void setShap(String shap);

    public void watchTV();

    public void playGame();

    public void surfInternet();

    public void shopping();
}
package com.designpattern.adapter;

public class AbstractTV implements MediaTV {

    @Override
    public void watchTV() {
        // TODO Auto-generated method stub
        System.err.println("watch TV");
    }

    @Override
    public void playGame() {
        // TODO Auto-generated method stub
        System.err.println("play Game");
    }

    @Override
    public void surfInternet() {
        // TODO Auto-generated method stub
        System.err.println("surf the Internet");
    }

    @Override
    public void shopping() {
        // TODO Auto-generated method stub
        System.err.println("shopping");
    }

    @Override
    public void setShap(String shap) {
        // TODO Auto-generated method stub
        System.err.println("tv shap:"+shap);
    }


}
package com.designpattern.adapter;

public class Letv extends AbstractTV{

    @Override
    public void setShap(String shap) {
        System.err.println("set Letv shap:"+shap);
    }
}
package com.designpattern.adapter;

public class PandaTv extends AbstractTV{

    @Override
    public void shopping() {
        System.err.println("nonsupport");
    }
}
package com.designpattern.adapter;

public class TestMainIntf {
    public static void main(String[] args) {
        AbstractTV letv = new Letv();
        AbstractTV pandatv = new PandaTv();
        letv.watchTV();
        letv.playGame();
        letv.setShap("方形的");
        letv.surfInternet();
        letv.shopping();


        System.err.println();

        pandatv.watchTV();
        pandatv.playGame();
        pandatv.setShap("臆想形的");
        pandatv.surfInternet();
        pandatv.shopping();
    }
}

运行结果:

watch TV
play Game
set Letv shap:方形的
surf the Internet
shopping

watch TV
play Game
tv shap:臆想形的
surf the Internet
nonsupport

如果写过jmeter插件,里面有大量的实例,比如写http的插件有两种途径:一种实现JavaSamplerClient还有一种是继承AbstractJavaSamplerClient,其实就是使用的这种方式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值