设计模式之适配器模式

前言

适配器模式(Adapter Pattern),当你存在一个类,但是这个类不能拿来直接使用,必须要用适配方式。把一个类的接口变换成客户端所期待的另一种接口

实例代码

比如:你去香港旅游,跑去买了个iphone,结果发现是三角插座,国内不能使用,解决办法有两种:
1)重新买一个插头 2)买一个转换器即可

代码如下:

英标插头-三脚

/**
 * @Description 英标插头 3脚
 * @Date 2017/7/2 21:51
 * @Since v1.7
 * @Autor Nick
 */
public interface EnPluginInterface {

    void chargeWith3Pins();
}

/**
 * @Description
 * @Date 2017/7/2 21:51
 * @Since v1.7
 * @Autor Nick
 */
public class EnPlugin implements EnPluginInterface {
    @Override
    public void chargeWith3Pins() {
        System.out.println("charge with EnPlugin");
    }
}

国标插头-2脚

/**
 * @Description 国标插头 2脚
 * @Date 2017/7/2 21:43
 * @Since v1.7
 * @Autor Nick
 */
public interface CnPluginInterface {
    void chargeWith2Pins();
}



/**
 * @Description
 * @Date 2017/7/2 21:44
 * @Since v1.7
 * @Autor Nick
 */
public class CnPlugin implements CnPluginInterface {
    //充电
    @Override
    public void chargeWith2Pins() {
        System.out.println("charge with CnPlugin");
    }
}

在家里充电只能使用2脚插头

/**
 * @Description 在国内充电
 * @Date 2017/7/2 21:45
 * @Since v1.7
 * @Autor Nick
 */
public class Home {

    private CnPluginInterface cnPlugin;

    public Home() {
    }

    public Home(CnPluginInterface cnPlugin) {
        this.cnPlugin = cnPlugin;
    }

    public void setPlugin(CnPluginInterface cnPlugin) {
        this.cnPlugin = cnPlugin;
    }

    //充电
    public void charge() {
        //国标充电
        cnPlugin.chargeWith2Pins();
    }

}

家里使用2脚测试

/**
 * @Description
 * @Date 2017/7/2 22:13
 * @Since v1.7
 * @Autor Nick
 */
public class HomeTest {

    public static void main(String[] args) {
        CnPluginInterface cnPlugin = new CnPlugin();
        Home home = new Home(cnPlugin);

        home.charge();
    }
}

家里就是不能使用三脚插头,怎么办?这时候需要有一个适配器来适配

/**
 * @Description
 * @Date 2017/7/2 21:52
 * @Since v1.7
 * @Autor Nick
 */
public class PluginAdapter implements CnPluginInterface {

    private EnPluginInterface enPlugin;

    public PluginAdapter(EnPluginInterface enPlugin) {
        this.enPlugin = enPlugin;
    }

    @Override
    public void chargeWith2Pins() {
        enPlugin.chargeWith3Pins();
    }

}

拿转接器过来一试,发现果然可以充电了

/**
 * @Description
 * @Date 2017/7/2 22:13
 * @Since v1.7
 * @Autor Nick
 */
public class AdapterTest {

    public static void main(String[] args) {
        EnPluginInterface enPluginInterface = new EnPlugin();
        Home home = new Home();
        PluginAdapter pluginAdapter = new PluginAdapter(enPluginInterface);
        home.setPlugin(pluginAdapter);
        home.charge();
    }

}

Java中用了大量的适配器

以InputStreamReader和OutputStreamWriter类为例。

InputStreamReader和OutputStreamWriter类分别继承了Reader和writer接口,但是要创建他们的对象必须在构造函数中传入一个InputStreamOutputStream的实例,InputStreamReader和OutputStreamWriter类的作用也就是将InputStreamOutputStream适配到Reader和Writer。

适配器是InputStreamReader,源角色是InputStream代表的实例对象,目标接口就是Reader类。

InputStream:得到的是字节输入流,InputStream.read("filename")之后,得到字节流

Reader:读取的是字符流
InputStreamReader:从字节到字符的桥梁。InputStreamReader(InputStream.read("filename"));

reader.read(InputStreamReader(InputStream in));便可从字节变为字符,打印显示了。
java.io.Reader 和 java.io.InputStream 组成了Java 输入类。
Reader 用于读入16位字符,也就是Unicode 编码的字符;而 InputStream 用于读入 ASCII 字符和二进制数据。
Reader支持16位的Unicode字符输出,
InputStream支持8位的字符输出。
Reader和InputStream分别是I/O库提供的两套平行独立的等级机构,

适配器种类

适配器其实有两种:1)类适配器,针对特定的某个类 2)面向对象的适配器

类适配器

场景:人去应聘工作,人会英语和中文,岗位的要求是要会英语、中文、法语,我的目的是要让这个人去干这份工作

public class Person {

    private String name;
    private String sex;
    private int age;

    public void speakChinese(){
        System.out.println("I can speak Chinese!");
    }

    public void speakEnglish(){
        System.out.println("I can speak English!");
    }
    ...//以下省略成员变量的get和set方法
}


//目标接口
public interface Job {  

    public abstract void speakChinese();  
    public abstract void speakEnglish();  
    public abstract void speakFrench();  

}  

//适配器代码
public class Adapter extends Person implements Job{  

    public void speakFrench() {  

    }  

}  

适配器在这个岗位要求,只能为人服务

对象适配器

针对对象适配器,如果也要适配这个工作,对象的适配器模式,把“源”作为一个构造参数传入适配器,然后执行接口所要求的方法。这种适配模式可以为多个源进行适配。

public class Adapter implements Job {  

    Person person;  

    public Adapter(Person person) {  
        this.person = person;  
    }  

    public void speakEnglish() {  
        person.speakEnglish();  
    }  

    public void speakJapanese() {  
        person.speakJapanese();  
    }  

    //new add  
    public void speakFrench() {  

    }  

}  

默认适配器
一件事物,标准的属性有A、B、C,但是有个特例,只有A;
如:如果我说 和尚都不喝酒、不吃肉、梯度,你认同吧?

//和尚接口
public interface Monk {
    public void notDrink();
    public void notEatMeat();
    public void tonsure();
}

实例:鲁智深,鲁智深是不是和尚?答案是的。鲁智深梯度了,但是鲁智深喝酒吃肉?我可以建一个花和尚的接口,但是我不想这么做,我想让鲁智深也实现Monk这个接口,又不想让他管不喝酒、不吃肉的戒律

引入抽象类

public abstract class AbstractMonk implement Monk {
    public void notDrink() {}
    public void notEatMeat() {}
    public void tonsure() {}
}

花和尚

public class Luzhishen extends AbstractMonk {

    @Override
    public void tonsure() {
        System.out.println("我是鲁智深,我剃度了");
    }

}

应用场景总结

  • 适配器对象实现原有接口
  • 适配器对象组合一个实现新接口的对象(这个对象也可以不实现一个接口,只是一个单纯的对象)
  • 对适配器原有接口方法的调用被委托给新接口的实例的特定方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值