Java23种设计模式——深入理解对象适配器模式与抽象外观模式

该系列文章为博主学习笔记,原文请参考参考连接
本文禁止转载,但是欢迎大家留言区留言交流[微笑]

对象适配器模式

刚刚在思考觉得对象适配器模式和抽象外观模式觉得很像,都是一个客户端去调用一些子系统,通过一个接口或者一个抽象类屏蔽具体操做的流程。但是针对于客户端却又本质上的差别。

抽象外观模式:

这里写图片描述

这是上一篇中提到的抽象外观模式UMl图

我们先截取一半,为了方便与后文的对象适配器模式进行比较。

这里写图片描述


适配器模式参考链接:参考连接

图我们先放在一边,我们来说一下对象适配器模式:

以参考链接举的列子继续探讨,当客户端已经针对一个接口进行编程,知道这个接口的一些方法。当想要调用这些方法的时候,却发现另一个类(我们称为适配者类)中已经有了具体的实现。然后我们在接口和适配者类之间,创建了一个适配器类,并且在该适配器类中保留对适配者类的引用。通过适配器类进行对适配者类方法的调用。

这里写图片描述

代码:

public interface Target {
    public void sort();

    public void search();
}
//适配器类
public class AdapterTest implements Target {

    private Adaptee adaptee;

    public AdapterTest() {
        adaptee = new Adaptee();
    }

    @Override
    public void sort() {
        adaptee.sort();
    }

    @Override
    public void search() {
        adaptee.search();
    }
}
//适配器者类
public class Adaptee {
    public void sort(){
        System.out.println("Adaptee.sort");
    }

    public void search(){
        System.out.println("Adaptee.search");
    }
}
public class myClass {

    public static void main(String[] args) {
        Target target;
        target = new AdapterTest();
        target.sort();
        target.search();
    }
}

打印:

Adaptee.sort
Adaptee.search

对象适配器模式与抽象外观模式的差别

大家看到这里有没有发现对象适配器模式和抽象外观模式十分的相似
我们再来对比下两个模式的UMl流程图:

这里写图片描述

这里写图片描述

经过对比发现了惊人的相似,可以说就是同一个UMl的流程图,具体流程都为一下几部:
1、创建一个抽象类或者接口(抽象外观模式为:abstractFacade,对象适配器模式为:Targe)
2、创建一个实现类继承或者实现步骤1中的类(抽象外观模式为:Newfacade,对象适配器模式为:AdapterTest)
3、在实现类中持有另一个类的引用(抽象外观模式的实现类Newfacade持有了InitInternetTitle对象的引用,对象适配器模式的实现类AdapterTest持有了Adaptee对象的引用)

经过UML流程图和我上面分析的三个步骤,大家可以看到对象适配器模式和抽象外观模式没有什么本质的区别,最起码在中间过程的实现代码都是一样的。

经过我的深入分析发现有一点不一样,那就是客户端类的实现以及调用不一样

我们先来回顾一下抽象外观模式客户端都做了什么:

public class myClass {

    public static void main(String[] args){
        AbstractFacade abstractFacade;
        abstractFacade = new NewFacade();
        abstractFacade.doSomething();
    }
}

抽象外观模式的客户端,只是通过了抽象类事例了对象并且调用了doSomething方法,而这个方法里面都做了什么,客户端根本不知道,完全对用户屏蔽了。

再来看看对象适配器模式的客户端做了什么:

public class myClass {

    public static void main(String[] args) {
        Target target;
        target = new AdapterTest();
        target.sort();
        target.search();
    }
}

通过了抽象类事例了对象,但是唯一的区别就是客户端知道自己要做什么,没有对用户屏蔽具体做的业务,但是具体的业务可能不是自己实现的而是通过一个接口与其他类的其他方法相连接,这就是对象适配器模式。


类适配器模式

类适配器模式也很简单,只不过将在适配器类中引用适配者类对象改为适配器类继承适配者类。

这里写图片描述

具体代码:

public class AdapterTest extends Adaptee implements Target  {

    private Adaptee adaptee;

    public AdapterTest() {
        adaptee = new Adaptee();
    }

    @Override
    public void sort() {
        super.sort();
    }

    @Override
    public void search() {
        super.search();
    }
}

但是由于Java语言的特点,只允许单一继承,如果Target不是一个接口而是一个类,或者如果适配者类Adaptee是一个final类,final类不允许继承,我们将无法使用类适配器模式。

双向适配器模式

双向适配器模式对我的理解就相当于一个适配器存在多个适配者,适配者可以通过它调用目标类中的方法,目标类也可以通过它调用适配者类中的方法。
代码:

public interface Adaptee {
    public void specificRequest();
}
public interface Target {
    public void request();
}
public class Adaptertest implements Target, Adaptee {

    private Target target;
    private Adaptee adaptee;

    public Adaptertest(Target target) {
        this.target = target;
    }

    public Adaptertest(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    public void request() {
        adaptee.specificRequest();
    }

    public void specificRequest() {
        target.request();
    }
}
public class ConcreteAdaptee implements Adaptee{

    @Override
    public void specificRequest() {
        System.out.println("ConcreteAdaptee.specificRequest");
    }
}
public class ConcreteTarget implements Target{

    @Override
    public void request() {
        System.out.println("ConcreteTarget.request");
    }
}
public class myClass {

    public static void main(String[] args) {
        Target target=new Adaptertest(new ConcreteAdaptee());
        target.request();

        Adaptee adaptee=new Adaptertest(new ConcreteTarget());
        adaptee.specificRequest();
    }
}

输出:
ConcreteAdaptee.specificRequest
ConcreteTarget.request

最后优缺点引用下原文的吧:原文
这里写图片描述

这里在仔细说一下对象适配器的缺点如何通过代码更改

比如我们要置换ConcreteAdaptee类中的specificRequest方法,我们首先创建一个AfterAdaptee类并且继承ConcreteAdaptee类,并且重写需要被置换的方法。


public class AfterAdaptee extends ConcreteAdaptee {
    @Override
    public void specificRequest() {
        System.out.println("AfterAdaptee.specificRequest");
    }
}

然后在客户端机型稍微的更改即可:

public class myClass {

    public static void main(String[] args) {
        Target target=new Adaptertest(new AfterAdaptee());
        target.request();

        Adaptee adaptee=new Adaptertest(new ConcreteTarget());
        adaptee.specificRequest();
    }
}

打印:

AfterAdaptee.specificRequest
ConcreteTarget.request

微信公众号:
这里写图片描述

QQ交流群:365473065

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值