Bruce Eckel:再聊设计模式(篇五)改变接口

Bruce Eckel

读完需要

10

分钟

速读仅需 1 分钟

布鲁斯 • 埃克尔(Bruce Eckel),C++ 标准委员会的创始成员之一,知名技术顾问,专注于编程语言和软件系统设计方面的研究,常活跃于世界各大顶级技术研讨会。
他自 1986 年以来,累计出版 Thinking in C++、Thinking in Java、On Java 等十余部经典计算机著作,曾多次荣获 Jolt 最佳图书奖(被誉为“软件业界的奥斯卡”),其代表作 Thinking in Java 被译为中文、日文、俄文、意大利文、波兰文、韩文等十几种语言,在世界范围内产生了广泛影响。

Bruce Eckel:再聊设计模式(篇一)设计模式分类

Bruce Eckel:再聊设计模式(篇二)封装实现

Bruce Eckel:再聊设计模式(篇三)工厂模式

Bruce Eckel:再聊设计模式(篇四)函数对象模式

8

   

改变接口

有时你要解决的问题可能就像“我没有想要的接口”这么简单。有两种设计模式可以解决这个问题:适配器模式(Adapter)接收一种类型为参数,并生成面向另一种类型的接口;外观模式(Facade)可以创建一个面向一组类的接口,这只是提供了一种更为简便的方式,来处理一个库或一批资源。

8.1

   

适配器模式

当你有了 A,而且想要 B 的时候,适配器模式便可以解决你的问题。这里唯一的需求就是生成 B,有多种方法可以完成该适配工作:

// patterns/adapt/Adapter.java
// 多种适配器模式
// {java patterns.adapt.Adapter}
package patterns.adapt;

class WhatIHave {
  public void g() {}
  public void h() {}
}

interface WhatIWant {
  void f();
}

class ProxyAdapter implements WhatIWant {
  WhatIHave whatIHave;
  ProxyAdapter(WhatIHave wih) {
    whatIHave = wih;
  }
  @Override public void f() {
    // 用WhatIHave中的方法实现行为:
    whatIHave.g();
    whatIHave.h();
  }
}

class WhatIUse {
  public void op(WhatIWant wiw) {
    wiw.f();
  }
}

// 方法2:构造传入op()中使用的适配器
class WhatIUse2 extends WhatIUse {
  public void op(WhatIHave wih) {
    new ProxyAdapter(wih).f();
  }
}

// 方法3:在WhatIHave内部构造适配器
class WhatIHave2 extends WhatIHave
implements WhatIWant {
  @Override public void f() {
    g();
    h();
  }
}

// 方法4:使用内部类
class WhatIHave3 extends WhatIHave {
  private class InnerAdapter implements WhatIWant{
    @Override public void f() {
      g();
      h();
    }
  }
  public WhatIWant whatIWant() {
    return new InnerAdapter();
  }
}

public class Adapter {
  public static void main(String[] args) {
    WhatIUse whatIUse = new WhatIUse();
    WhatIHave whatIHave = new WhatIHave();
    WhatIWant adapt= new ProxyAdapter(whatIHave);
    whatIUse.op(adapt);
    // 方法2:
    WhatIUse2 whatIUse2 = new WhatIUse2();
    whatIUse2.op(whatIHave);
    // 方法3:
    WhatIHave2 whatIHave2 = new WhatIHave2();
    whatIUse.op(whatIHave2);
    // 方法4:
    WhatIHave3 whatIHave3 = new WhatIHave3();
    whatIUse.op(whatIHave3.whatIWant());
  }
}

在 ProxyAdapter 的应用上,我对术语“代理”的使用没有那么严格。《设计模式》一书的作者主张代理必须具有和其代理的对象完全相同的接口。将代理和适配器这两个词合并为代理适配器(ProxyAdapter)来使用也许更合理。

8.2

   

外观模式

这是我在将需求转化为对象设计的开始阶段所遵循的原则:

如果有一段逻辑很丑陋,那么就把它藏到对象里。

这基本上就是外观模式所完成的任务。如果你有一堆相当杂乱的类和交互逻辑,并且不需要让调用方程序员看到,就可以将这些藏到一个接口后面,以一种更易懂的形式(只)暴露出外部需要知道的信息。外观模式通常被实现为单例抽象工厂。可以使用包含静态工厂方法的类来实现这个效果:

// patterns/Facade.java

class A { A(int x) {} }
class B { B(long x) {} }
class C { C(double x) {} }

// 其他不需要由外观暴露出去的类都放到这里

public class Facade {
  static A makeA(int x) { return new A(x); }
  static B makeB(long x) { return new B(x); }
  static C makeC(double x) { return new C(x); }
  public static void main(String[] args) {
    // 调用方程序员通过调用静态方法得到对象:
    A a = Facade.makeA(1);
    B b = Facade.makeB(1);
    C c = Facade.makeC(1.0);
  }
}

《设计模式》中给出的示例并不是真正的外观模式,只是一个用到了其他类的类而已。

8.3

   

可作为外观模式变体的 Java 包

对我来说,外观模式会给人一种相当“面向过程”(而非面向对象)的感觉:我们只是在调用一些生成对象的函数而已。而这实际上和抽象工厂又有多大区别呢?外观模式的重点在于将一组类(以及它们之间的交互)形成的库部分隐藏起来,不让调用方程序员看到,使得这一组类对外暴露出的接口更好用、更易懂。而这正是 Java 的包特性所实现的功能。在库以外只能创建和使用 public 的类,而所有非 public 的类都只能在包范围内访问。这就好像外观模式是 Java 的内建特性。公平地讲,《设计模式》面向的主要是使用 C++的群体。虽然 C++有命名空间来防止全局冲突和类名冲突,但这并不能提供由 Java 中的非 public 类带来的类隐藏机制。大部分时候,Java 的包似乎就可以解决外观模式所要解决的问题了。

9

   

解释器模式:运行时的灵活性

在一些应用程序中,用户需要在运行时拥有更高的灵活性,例如创建用来描述系统所需行为的脚本。解释器设计模式可以用来创建语言解释器,并将其嵌入这样的程序中。

在构建应用程序的过程中,开发自定义语言以及为其构建解释器是一件费时费力的事。最好的方案是复用代码:嵌入一个已构建好并且调试过的解释器。Python 语言可以免费地嵌入到营利性质的应用程序中,而无须任何许可协议、版税或其他产权负担。另外,Python 还有一个称为 Jython 的版本(已经过时了,但仍然能用),它是彻底的 Java 字节码,因此将它加入 Java 程序是相对比较简单的。Python 是一种脚本语言,易于学习,编写和阅读的逻辑性很强,支持函数和对象,拥有大量可用的库,并且几乎可以在所有的平台上运行。你可以通过 Python 网站进一步学习。


11798d8ba40ff90d31ffbb76fa9703ae.png

8bc77bd4d72e44f3c3191af6cae266cc.jpeg

本书特色

  • 查漏宝典:涵盖Java关键特性的设计原理和应用方法

  • 避坑指南:以产业实践的得失为鉴,指明Java开发者不可不知的设计陷阱

  • 经典普适:值得不同层次的Java开发者反复研读

  • 专家领读:4位一线业务专家、知名作译者帮你拆解书中难点,总结Java开发精要

值得一提的是,为了帮助新手加深理解,出版方邀请了4位从业10年以上知名作译者DDD 专家张逸、服务端专家梁桂钊、软件系统架构专家王前明、译者陈德伟)为本书录制【精讲视频】和【导读指南】,该视频已在B站和图灵社区发布,感兴趣的朋友可以去看看。

82675e19966335fe511c70163d393b47.png

往期推荐

Bruce Eckel:再聊设计模式(篇一)

Bruce Eckel:再聊设计模式(篇二)封装实现

Bruce Eckel:再聊设计模式(篇三)工厂模式

Bruce Eckel:再聊设计模式(篇四)函数对象模式

Bruce Eckel - 详解函数式编程(卷一)

Bruce Eckel - 详解函数式编程(卷二)

Bruce Eckel - 详解函数式编程(卷三)

如何在 SpringBoot 项目中控制 RocketMQ消费线程数量

同事多线程使用不当导致OOM,被我怒怼了

怎样才能持续输出技术原创文章?

后Kubernetes时代的微服务

我,程序员,马上35岁...

史海峰:在时代节点上顺势而为是一种幸运

知明:技术 Leader 的思考法

一文理解分布式开发中的服务治理

聊聊 8 种架构模式

Google工程师是怎么写设计文档的?

聊聊技术人员如何做好团队管理

为什么大数据平台要回归 SQL

如葑:阿里云原生网关Envoy Gateway实践

如何用研发效能搞垮一个团队

他教全世界程序员怎么写好代码,答案写在这里!

研发效能提升的实践框架、模式与反模式

聊聊大中型公司都热衷于造轮子的故事

被滥用的“架构师”!

构建健壮的分布式系统

阿里在云原生架构下的微服务选型和演进

f995629847741f0e49093c388cca6a17.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值