设计模式(一)—— 适配器模式

 

一、定义

将一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一个工作
 

二、适用的场景

要修改已经投产的接口
 

三、注意事项

适配器一般不用于开发阶段,通常用在服役的项目上
 

四、模式中的角色

  • 目标接口(Target):客户期待的接口
  • 需要适配的类(Adaptee):需要被适配的类
  • 适配器(adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。实现方法是适配器类继承需要适配的类,并实现目标接口
 
 

五、应用场景举例

案例一
1、A公司有一套员工管理系统,其系统正在使用中,且主要代码如下
public interface ICompanyA {
    //获取员工ID
    public String getID();
    //获取员工姓名
    public String getName();
    public String getPhone();
    public String getAddress();
}    

2、现在A公司需要将一部分业务外包给B公司,B公司的一部分开发人员也会归A的员工管理系统来管

但是B公司自己本身也有一套管理系统,主要代码如下

public interface ICompanyB {
    //获取员工ID
    public Map getIDB();
    //获取员工姓名
    public Map getInfo();
    public Map getTel();
    public Map getHome();
}
public class CompanyB implements ICompanyB{

    public Map getTel() {
        HashMap hashMap = new HashMap();
        hashMap.put("tel", "151xxxx");
        return hashMap;
    }

    public Map getHome() {
        HashMap hashMap = new HashMap();
        hashMap.put("home", "shandong");
        return hashMap;
    }

    public Map getIDB() {
        HashMap hashMap = new HashMap();
        hashMap.put("id", "100");
        return hashMap;
    }

    public Map getInfo() {
        HashMap hashMap = new HashMap();
        hashMap.put("info", "fzj");
        return hashMap;
    }
    
}

3、A公司的系统要获得B公司系统的数据,但由于数据格式不同

这时就需要有一个中转角色,来对其进行转换,这里就用到了我们所讲的适配器模式

public class Adapter extends CompanyB implements ICompanyA{

    private Map home = super.getHome();
    private Map id = super.getIDB();
    private Map name = super.getInfo();
    private Map tel = super.getTel();
    
    public String getName() {
        return (String) name.get("info");
    }

    public String getPhone() {
        return (String) tel.get("tel");
    }

    public String getAddress() {
        return (String) home.get("home");
    }

    public String getID() {
        return (String) home.get("id");
    }

}

 4、以上的代码已经解决了两个接口不一致的问题,但是接下来思考一个问题:如果B公司使用了三个接口来负责员工信息管理的,而java又不支持多继承,这个问题要怎么解决

案例二

如果B公司使用了两个或多个接口来负责员工信息管理的,而java又不支持多继承,这个问题要怎么解决?

这里假设一个场景,我们公司使用A公司和B公司的接口,需要使用适配器整合这两家公司的接口来适配我们公司的接口

 

A公司的接口

public class CompanyA {

    private List<Person> person;

    public List<Person> getPerson() {
        return person;
    }

    public void setPerson(List<Person> person) {
        this.person = person;
    }
}

B公司的接口

public class CompanyB {

    private Map<String,Person> personMap;

    public Map<String, Person> getPersonMap() {
        return personMap;
    }

    public void setPersonMap(Map<String, Person> personMap) {
        this.personMap = personMap;
    }
}

我们公司的接口

 

public interface CompanyOur {

    List<OurPerson> getPerson();

}

  

 

这里可以使用一个整合类来调用A公司和B公司的对象

public class CompanyAll {

    private CompanyA companyA;

    private CompanyB companyB;

    public CompanyA getCompanyA() {
        return companyA;
    }

    public void setCompanyA(CompanyA companyA) {
        this.companyA = companyA;
    }

    public CompanyB getCompanyB() {
        return companyB;
    }

    public void setCompanyB(CompanyB companyB) {
        this.companyB = companyB;
    }
}

实现对A、B公司的适配器

public class Client extends CompanyAll implements CompanyOur {

    private CompanyA  companyA = getCompanyA();
    private CompanyB  companyB = getCompanyB();

    @Override
    public List<OurPerson> getPerson() {

        List<OurPerson> list = new ArrayList<>();

        companyA.getPerson().forEach(
                person -> {
                    OurPerson ourPerson = new OurPerson();
                    ourPerson.setOurName(person.getName());
                    ourPerson.setOurHome(person.getHome());
                    list.add(ourPerson);
                }
        );

        companyB.getPersonMap().forEach(
                (x, y) -> {
                    OurPerson ourPerson = new OurPerson();
                    ourPerson.setOurName(y.getName());
                    ourPerson.setOurHome(y.getHome());
                    list.add(ourPerson);
                });


        return list;
    }


}

  

案例三

看《HeadFirst设计模式》一书中有一个挺逗的例子。原话是这样。

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

其实在现实生活中,你也可以成为适应任何人。比如,你身边有一个朋友天天吐槽,经常会说“holy shit”,“真倒霉”,你不喜欢他,但又不得不跟他生活在一起,这是你就可以在自己脑袋里装一个适配器,通过适配器,你会将抱怨转换为感谢、赞美。比如他说“倒霉”,经过适配器,你会想他说的是“真幸运”。时间久了,你会觉得他是乐观向上的人。说明你适配了他。

 

简短的说明,如何实现鸭子的例子。火鸡适配器类肯定是要实现鸭子接口的,引用火鸡对象,对接口方法进行实现。

 

参考

[1] 《设计模式之禅》 秦小波

[2] 《HeadFirst设计模式》

[3]  平时代码中用不到设计模式?Are you kidding me?

 

 

posted @ 2016-02-21 21:14  清泉白石  阅读(448)  评论(0编辑  收藏  举报