Kotlin 设计模式:简化观察者模式

观察者模式是一种行为设计模式,其中对象(主体)维护其依赖者(观察者)的列表,并自动通知它们任何状态更改。

此模式可确保在发生某些状态更改时通知多个对象。它广泛用于实现分布式事件处理系统。

观察者模式将主体与其观察者解耦,并允许动态添加或删除观察者。

Java 中的方法

让我们设计一个在温度变化时发送通知,让显示屏对应做出变化的气象站。Java示例如下:

csharp 复制代码
// Observer Interface:
public interface Observer {
    void update(float temperature);
}

// Subject Interface:
public interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers();
}

// Concrete Subject:
public class WeatherStation implements Subject {
    private float temperature;
    private List<Observer> observers = new ArrayList<>();

    public void setTemperature(float temperature) {
        this.temperature = temperature;
        notifyObservers();
    }

    public void registerObserver(Observer o) {
        observers.add(o);
    }

    public void removeObserver(Observer o) {
        observers.remove(o);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(temperature);
        }
    }
}

// Concrete Observer:
public class Display implements Observer {
    private String displayId;

    public Display(String id) {
        this.displayId = id;
    }

    public void update(float temperature) {
        System.out.println(displayId + ": Temperature updated: " + temperature);
    }
}

// Client:
public class WeatherApp {
    public static void main(String[] args) {
        WeatherStation station = new WeatherStation();
        Display display1 = new Display("Display 1");
        Display display2 = new Display("Display 2");

        station.registerObserver(display1);
        station.registerObserver(display2);
        station.setTemperature(30f);
    }
}

在此Java 示例中,WeatherStation是Subject,Display是在温度变化时更新的观察者。当站点温度发生变化时,两者都会显示display1display2收到通知 ( )。update(float temperature)

Java 8+ 中的函数式方法

您可以使用Java 8+ 函数式特性来简化观察者模式,并使用函数式接口和 Java 的 lambda 表达式实现非常相似的方法。

以下是如何调整的示例:

java 复制代码
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class WeatherStation {
    private float temperature;
    private List<Consumer<Float>> onTemperatureChangeListeners = new ArrayList<>();

    public void setTemperature(float temperature) {
        this.temperature = temperature;
        notifyTemperatureChange(temperature);
    }

    private void notifyTemperatureChange(float newTemperature) {
        onTemperatureChangeListeners.forEach(listener -> listener.accept(newTemperature));
    }

    public void onTemperatureChange(Consumer<Float> listener) {
        onTemperatureChangeListeners.add(listener);
    }
}

// Usage:
WeatherStation station = new WeatherStation();

// Registering listeners using lambda expressions:
station.onTemperatureChange(temp -> System.out.println("Display 1: Temperature updated to " + temp));
station.onTemperatureChange(temp -> System.out.println("Display 2: Temperature updated to " + temp));

// Simulating a temperature change:
station.setTemperature(30f);

在这个Java示例中:

  • 该类WeatherStation维护一个对象列表Consumer<Float>,这些对象是 Java 中可与 lambda 表达式一起使用的函数接口。
  • onTemperatureChange方法允许注册Consumerlambda 表达式,当温度变化时将调用该表达式。
  • setTemperature被调用时,它会触发notifyTemperatureChange,它会使用新的温度执行所有已注册的 lambda 表达式。

Kotlin 的方法:

Kotlin 提供观察者委托功能。Delegates.observable()简化了对象属性更改的观察者模式实现:

您可以组合观察者委托来观察属性更改和高阶函数来注册回调。

kotlin 复制代码
import kotlin.properties.Delegates

class WeatherStation {
    // Observable property with callbacks:
    var temperature: Float by Delegates.observable(0f) { _, _, newValue ->
            onTemperatureChangeListeners.forEach { it(newValue) }
    }

    // List of callbacks:
    private val onTemperatureChangeListeners = mutableListOf<(Float) -> Unit>()

    // Function to add callbacks:
    fun onTemperatureChange(listener: (Float) -> Unit) {
        onTemperatureChangeListeners.add(listener)
    }
}

// Client:
fun main() {
    val station = WeatherStation()

    // Registering callbacks:
    station.onTemperatureChange { println("Display 1: Temperature updated to $it") }
    station.onTemperatureChange { println("Display 2: Temperature updated to $it") }

    // Simulating temperature change:
    station.temperature = 30f
}

在这个Kotlin实现中:

  • temperature中的属性 是WeatherStation可观察属性。当它改变时,所有注册的回调onTemperatureChangeListeners都会被调用。
  • onTemperatureChange方法允许注册对温度变化做出反应的 lambda 表达式(回调)。
  • 客户端注册回调WeatherStation,每当属性更改时就会执行回调temperature

这种方法的好处:

  • 简单性: 这种方法通过消除对接口和具体观察者类的需求来简化观察者模式。
  • 灵活性: 很容易在运行时动态添加或删除行为(回调)。
  • 表现力: 利用 Kotlin 的语言功能可以生成更具可读性和可维护性的代码。

Kotlin 特性简化了观察者模式

  • 高阶函数和 Lambda: 使用函数(行为)作为参数来实现简洁的观察者实现。
  • 委托属性 ( Delegates.observable()): 简化属性更改观察。

KotlinDelegates.observable()提供了传统观察者模式的简洁而强大的替代方案,特别是对于简单的用例。对于更复杂的场景,标准实现还是有一定作用的.

相关推荐
牛奶咖啡131 小时前
学习设计模式《五》——工厂方法模式
学习·设计模式·工厂方法模式·ioc/di·参数化工厂方法
渊渟岳1 小时前
学习设计模式有这两就够了:手册+实战项目
设计模式
Pasregret7 小时前
迭代器模式:统一数据遍历方式的设计模式
设计模式·迭代器模式
不当菜虚困7 小时前
JAVA设计模式——(二)组合模式
java·设计模式·组合模式
CHQIUU10 小时前
Java 设计模式心法之第4篇 - 单例 (Singleton) 的正确打开方式与避坑指南
java·单例模式·设计模式
碎梦归途10 小时前
23种设计模式-结构型模式之享元模式(Java版本)
java·开发语言·jvm·设计模式·享元模式
Pasregret10 小时前
模板方法模式:定义算法骨架的设计模式
算法·设计模式·模板方法模式
zhaoyqcsdn10 小时前
抽象工厂模式及其在自动驾驶中的应用举例(c++代码实现)
c++·经验分享·笔记·设计模式
中杯可乐多加冰13 小时前
借助 Amazon Q 实现内容分发网络(CDN)CDK 构建的全流程实践
掘金·金石计划·deepseek
李菠菜16 小时前
SpringBoot项目中策略模式与简单工厂、模板方法的优雅融合实践
spring boot·后端·设计模式