前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊 Java 新特性与设计模式

聊聊 Java 新特性与设计模式

作者头像
Java技术江湖
发布2023-01-04 13:16:49
2950
发布2023-01-04 13:16:49
举报

Java 平台与 OpenJDK

让我们从 Java 虚拟机开始。

  • 编译器负责生成字节码;
  • JIT 编译器负责优化成本地代码;
  • JVM 解释器负责输出期望结果。
  • 字节码优化技术:内联 inlining、消除 elimination、标量化 scalarization。

下面是一个优化后的结果示例:

代码语言:javascript
复制
static factory_method.Car produce(java.lang.String); 
  descriptor: (Ljava/lang/String;)Lfactory_method/Car;
  flags: (0x0008) ACC_STATIC
  Code:
    stack=7, locals=5, args_size=1
      0: new #7  // class factory_method/FactoryMethodEvent
      3: dup
      ...
      19: aload_3
      20: invokevirtual #17 // Method java/lang/String.hashCode:()I
      23: lookupswitch { // 2
        3135580: 48
        3556498: 63
        default: 75
      }
      48: aload_3
      49: ldc #23  // String fast
      51: invokevirtual #25  // Method java/lang/String.equals:(Ljava/lang/Object;)Z

用 SOLID 思想看设计模式

概述 SOLID 原则以及与现在开发需要考虑的一些设计原则:

  • SOLID 原则:单一功能、开闭原则、里氏替换、接口隔离以及依赖反转;
  • 不要重复自己,关注点分离,CAP 原则;
  • 编程语言和技术不可知;
  • 微服务架构、分布式系统领域驱动设计、数据流;
  • 可扩展性、可维护性与安全性。

设计模式分创建型、结构型、行为型,其中行为型设计模式需要考虑服务、运行时的并发。

一些重要项目

  • Valhalla 项目:利用通用 API、基础类型和值类型,提升机器学习和大数据应用程序性能
    • 隐藏类(JEP-371)、对值类型 class 进行警告 (JEP-390) 等
  • Panama 项目:为 JVM 和非 Java API 提供桥梁,可以更容易地实现 App 之间的 I/O
    • 外部函数和内存 API (JEP-424)、Vector API (JEP-426)等
  • Amber 项目:通过 Java 语言自身演进提升生产率
    • 局部变量类型推断 (JEP-286)、switch 表达式改进 (JEP-361)
    • TextBlocks (JEP-378)、Records (JEP-395), instanceof 的模式匹配 (JEP-394)
    • 密封类 (JEP-409)、默认支持 UTF-8 (JEP-400)、Record 模式 (JEP-405)等
  • Loom 项目: 易于使用,高吞吐量、轻量级并发和编程方法
    • 虚拟线程 (JEP-425)、结构化并发 (JEP-428)等

简化创建对象

  • 备选方案:Factory 或 Builder。二者有何区别?
    • 前者是封装,后者是逐步构建直到最后生产
    • 其它区别包括,如何补充信息、实现可测试性等
  • 其它选择:
    • 抽象工厂、原型模式、单例模式、 对象池延迟初始化、依赖注入

JDK 中使用 Builder:使用 StringBuilder 或者像下面这样:

代码语言:javascript
复制
public class Thread implements Runnable { //JDK19(Preview)
    public sealed interface Builder permits Builder.OfPlatform,
        Builder.OfVirtual, ThreadBuilders.BaseThreadBuilder {
        ..
    }
}

JDK 中的工厂:使用 Java Collection framework,例如 List、Set 或者 Map。

代码语言:javascript
复制
static <E> List <E> of (E e1, E e2, E e3) {
    return ImmutableCollections.listFromTrustedArray(e1, e2, e3);
}
static <K, V> Map <K, V> of (K k1, V v) {
    return new ImmutableCollections.Map1 < > (k1, v1);
}

下面是 CarFactory 示例及运行效果:

代码语言:javascript
复制
record FastCar(String type) implements Car { ...
sealed interface Factory permits CarFactory { ...
final class CarFactory {
    static Vehicle produce(String type) {
        var result =
            switch (type) {
                case "fast" - > {
                    ...
                    yield new FastCar(“super”);
                }
                case String s
                when s.length() > 10 - > new SlowCar()
                ...

如何结构化思考

如何围绕实例化对象组织代码(指令)

  • 备选方案:适配器或享元模式;
  • 其它方案:组合模式、装饰器模式、外观模式(也称门面模式)、过滤器模式、模块模式、控制器模式、标记型接口、代理模式、双胞胎模式。

JDK 中的适配器:

代码语言:javascript
复制
public final class Spliterators { ...
    public static <T> Iterator <T> iterator(Spliterator <<?extends T> spliterator) {
        Objects.requireNonNull(spliterator);
        class Adapter implements Iterator <T> , Consumer <T> {
            ...
        }
    }
}

public Collections {
    ...
    public static <T> ArrayList <T> list(Enumeration <T> e) { ... }

JDK 中的友元:

Integer、Byte、Character 等包装类,以及 valueOf(...) 方法使用到的缓存:

代码语言:javascript
复制
return IntegerCache.cache[i + (-IntegerCache.low)];

下面是 Engine 密封接口示例及运行效果:

代码语言:javascript
复制
var engine = counter++ % 2 == 0 ? new DieselEngine() : new ElectricEngine();
var fastCar = new FastCar(engine);

class FastCar {
    ...
    FastCar(Engine engine) { 
        ...
    }
    public void drive() {
        ...
        if (engine instanceof ElectricEngine ee) {
            ee.checkBatteries();
        }
        engine.run();
...
sealed interface Engine {
    void run();
}

运行时设置行为

运行时如何维护对象之间的信息传递?

由 JVM 和代码库提供灵活性和可维护性。

  • 备选方案:责任链模式、命令模式、缓存;
  • 其它方案:状态模式、策略模式、解释器模式、迭代器模式、中介者模式、 备忘录模式、Null 对象、观察者模式、管道、模板方法、访问者模式等。

JDK 中的责任链:

代码语言:javascript
复制
public class Logger {
    public void log(Level level, Supplier < String > msgSupplier)
    //overloaded method, Levels: OFF, SEVERE, WARNING ...

JDK 中的命令:

代码语言:javascript
复制
java.lang.Runnable, java.lang.Callable

JDK 中的缓存:

代码语言:javascript
复制
java.util.Locale
private static class Cache extends LocaleObjectCache < Object, Locale > {
    private static final Cache LOCALECACHE = new Cache();

并发相关

那么并行执行的代码该如何考虑呢?

根据问题的多线程性质选择适合的设计模式组合。

  • 备选方案:线程池模式;
  • 其它方案:主动对象模式、异步方法调用、Balking 模式、双重检查锁定、读写锁、调度器等。

下图中可以看到并发相关 package 在 JDK 中的依赖关系(由 Java Mission Control 8.3 生成)

下面是一个使用虚拟线程的示例:

代码语言:javascript
复制
var threadPerTaskExecutor = Executors.newThreadPerTaskExecutor(threadFactory);
var executor = Executors.newVirtualThreadPerTaskExecutor();
threadPerTaskExecutor.execute(() - > {
    while (active.get()) {
        executor.submit(new ComputableTask(counter));
    }
})

总结

设计模式和 JDK 新功能带来了以下好处:

  • 密封类、模式匹配让代码变得更清晰;
  • switch 语法改进、引入 Record 减少了冗余代码;
  • Amber 项目、Loom 项目增强了项目可维护性;
  • 虚拟线程、结构化并发、switch、局部变量类型推断让组合变得更简单;
  • 带来更好的可观测性、性能分析、调试功能。

参考资料

  • Amber项目: https://openjdk.org/projects/amber/
  • Valhalla项目: https://openjdk.org/projects/valhalla/
  • Panama项目: https://openjdk.org/projects/panama/
  • JFR项目: https://github.com/openjdk/jmc
  • OpenJDK: https://openjdk.org/
  • foojay.io: https://foojay.io/today/author/miro-wengner/
  • OpenValue博客: https://openvalue.blog/
  • Practical Design Patterns for Java Developers [PACKT]

转自:Miroslav Wengner 与 Benedikt Neumayr, 链接:slideshare.net/miragemiko/new-java-features-simplified-design-patternslit3826

- EOF -

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-01-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java技术江湖 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档