设计模式--适配器模式、外观模式

本文介绍了适配器模式和外观模式的概念及应用场景。适配器模式通过转换接口使不兼容的类能够协同工作;外观模式则通过提供简单接口隐藏子系统的复杂性。

适配器模式和外观模式

适配器模式将一个类的接口。转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。

所谓适配器,你可以将其理解成将一种数据类型通过适配器让其适用于另一种类型。以上面的图为例。加入Client需要一个Targe类型(目标类型)的实体,但是我们只有一个Adaptee(被适配者)类型。这时候我们可以通过一个中间的适配器Adapter来完成。

它的操作一点也不神秘,仅仅是让Adapter实现Target,这样Adapter就可以被当成Target来使用了。而Adapter内部的逻辑则委托给Adaptee来实现。所以,我们需要为Adapter传入指定一个被适配者。

示例

我们可以考虑变压器的工作效果,假设高电压为HightVoltage、低电压为LowVoletage以及变压器为Transformer. 那么现在我们需要将高电压经过变压器转换成低电压来使用。那么我们可以定义

public interface HightVoltage {
    int output();
}

public class Voltage220 implements HightVoltage {
    @Override
    public int output() { 
        return 220; 
    }
}

public interface LowVoltage {
    int output();
}

public class Transormer implements LowVoltage {
    private HightVoltage hightVoltage;

    public Transformer(HightVoltage hightVoltate) {
        this.hightVoltage = hightVoltage;
    }

    public int output() {
        hightVoltage.output() / 2;
    }
}

public static void main(String ...args) {
    HightVoltage voltage220 = new Voltage220();
    LowVoltage lowVoltage = new Transformer(voltage220);
}

在上面的代码中我们需要实现的操作是将220V的电压转换成可用的110V的电压。这里我们使用了一个变压器将传入的电压做了除以2的处理。也许,你会觉得这更像是装饰器模式。因为它只是在高电压的基础上进行了一层封装来,修改了输出电压的方法。但是,这里和装饰器不同的一点是,最终我们适配器的结果赋值给了LowVoltage实例,而不是HightVoltage. 如果是装饰器的话,为了营造出我们只是为原来的对象“添加了一些佐料”的假象(实际上引用都已经变了),需要将装饰之后的结果赋值给原来的对象。这里并没有赋值给原来的对象,而是新的类型,所以这里是适配器而不是装饰器。这是装饰器和适配器直观上的区别。

外观模式

外观模式将一个或者数个类的复杂实现隐藏在背后,只暴露几个方法给客户端使用。通过使用外观类,可以将一个复杂的子系统变得更加容易。

以上是外观模式的一个类图。这里需要Facade类引用模块A、模块B和模块C,并三者组合起来实现的功能封装在Facade的一个方法中。

也就是将一系列操作封装在一个方法中供给外部调用,比如关闭电视机操作,它其实涉及的东西很多,但是对我们用户而言,只要按一下关机按钮就可以了。

另一个使用场景

以上是门面模式的一种使用情景。此外,它还被用来隐藏对外接口。比如,

public interface IBase {
    void method01();
    void method02();
    void method03();
}

public class MyClass implements IBase {

    public MyClass() {}

    @Override
    public void method01() {}

    @Override
    public void method02() {}

    @Override
    public void method03() {}

    public void method04() {}

    public void method05() {}
}

这里我们定义了一个基接口IBase,并且定义了一个它的实现MyClass,而且又在MyClass中添加了一些方法method04()、method05(),现在假设我们需要将MyClass给别人使用,但是我们又不希望将method04()、method05()方法暴露,而且也不希望用户在使用的时候将我们的给的实例强制转换成MyClass来使用。这时候我们可以使用门面模式来解决这个问题。我们只需要按照下面的方式定义一个门面,并将其作为参数提供给用户使用即可。

public class MyClassFacade implements IBase {
    private MyClass myClass;

    public MyClassFacade(MyClass myClass) {
        this.myClass = myClass;
    }

    @Override
    public void method01() {
        myClass.method01();
    }

    @Override
    public void method02() {
        myClass.method02();
    }

    @Override
    public void method03() {
        myClass.method03();
    }
}

外观模式的总结

为了使用外观模式,在设计的时候我们应该注意:

  1. 在设计初期阶段,应该有意识的将不同的层进行分离,比如经典的三层框架;
  2. 其次,在开发阶段,子系统往往因为不断重构而演变得越来越复杂,增加外观可以提供一个简单的接口。

更多内容

1、该项目整理了设计模式、Java语法、JVM、SQL、数据结构与算法等相关内容:https://github.com/Shouheng88/Java-Programming。

2、由于时间仓促,不免于存在错误,欢迎批评指正。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值