You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#实现Shape类按订阅者需求触发颜色变更事件通知

实现Shape类的按需通知方案

要解决这个问题,我们可以基于观察者模式,结合条件过滤来实现Shape类根据订阅者的不同需求发送颜色变更通知。下面提供两种常用的实现思路,你可以根据场景选择:


思路一:订阅者自行过滤(简单直接)

这种方式下,Shape类只负责在颜色变更时通知所有订阅者,订阅者自己判断是否需要处理该通知。

步骤1:定义核心接口与枚举

首先定义颜色枚举和观察者接口:

// 颜色枚举
public enum Color {
    RED, GREEN, YELLOW, BLUE, ORANGE
}

// 观察者接口
public interface ColorObserver {
    void onColorChanged(Color newColor);
}

步骤2:实现Shape类(主题)

Shape类维护订阅者列表,颜色变更时遍历通知所有订阅者:

import java.util.ArrayList;
import java.util.List;

public class Shape {
    private Color currentColor;
    private List<ColorObserver> observers = new ArrayList<>();

    // 订阅方法
    public void addObserver(ColorObserver observer) {
        if (!observers.contains(observer)) {
            observers.add(observer);
        }
    }

    // 取消订阅
    public void removeObserver(ColorObserver observer) {
        observers.remove(observer);
    }

    // 设置颜色并触发通知
    public void setColor(Color newColor) {
        if (this.currentColor != newColor) {
            this.currentColor = newColor;
            notifyObservers(newColor);
        }
    }

    // 通知所有订阅者
    private void notifyObservers(Color newColor) {
        for (ColorObserver observer : observers) {
            observer.onColorChanged(newColor);
        }
    }
}

步骤3:实现不同的订阅者

每个订阅者在onColorChanged方法中自行判断是否处理通知:

// Subscriber1:仅接收绿、黄、红
public class Subscriber1 implements ColorObserver {
    @Override
    public void onColorChanged(Color newColor) {
        if (newColor == Color.GREEN || newColor == Color.YELLOW || newColor == Color.RED) {
            System.out.println("Subscriber1 收到通知:颜色变为 " + newColor);
        }
    }
}

// Subscriber2:仅接收红
public class Subscriber2 implements ColorObserver {
    @Override
    public void onColorChanged(Color newColor) {
        if (newColor == Color.RED) {
            System.out.println("Subscriber2 收到通知:颜色变为 " + newColor);
        }
    }
}

// Subscriber3:接收所有颜色
public class Subscriber3 implements ColorObserver {
    @Override
    public void onColorChanged(Color newColor) {
        System.out.println("Subscriber3 收到通知:颜色变为 " + newColor);
    }
}

测试代码

public class Main {
    public static void main(String[] args) {
        Shape shape = new Shape();
        
        shape.addObserver(new Subscriber1());
        shape.addObserver(new Subscriber2());
        shape.addObserver(new Subscriber3());

        shape.setColor(Color.BLUE);    // 仅Subscriber3收到
        shape.setColor(Color.GREEN);   // Subscriber1和3收到
        shape.setColor(Color.RED);     // 三个订阅者都收到
        shape.setColor(Color.ORANGE);  // 仅Subscriber3收到
    }
}

思路二:Shape类主动过滤(更高效)

这种方式下,订阅者在注册时指定自己的过滤条件,Shape类只给符合条件的订阅者发送通知,减少不必要的通知开销。

步骤1:定义核心接口与枚举

和思路一一致,不过我们会用Predicate来定义过滤条件:

public enum Color {
    RED, GREEN, YELLOW, BLUE, ORANGE
}

public interface ColorObserver {
    void onColorChanged(Color newColor);
}

步骤2:实现Shape类(带过滤逻辑)

Shape类存储订阅者和对应的过滤条件,通知前先判断是否符合条件:

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class Shape {
    private Color currentColor;
    // 存储订阅者和对应的过滤条件
    private List<ObserverFilterPair> observerPairs = new ArrayList<>();

    // 内部类:绑定订阅者和过滤条件
    private static class ObserverFilterPair {
        ColorObserver observer;
        Predicate<Color> filter;

        ObserverFilterPair(ColorObserver observer, Predicate<Color> filter) {
            this.observer = observer;
            this.filter = filter;
        }
    }

    // 重载订阅方法:支持自定义过滤条件
    public void subscribe(ColorObserver observer, Predicate<Color> filter) {
        observerPairs.add(new ObserverFilterPair(observer, filter));
    }

    // 订阅所有颜色的重载方法
    public void subscribe(ColorObserver observer) {
        subscribe(observer, color -> true); // 过滤条件为"始终满足"
    }

    // 取消订阅
    public void unsubscribe(ColorObserver observer) {
        observerPairs.removeIf(pair -> pair.observer.equals(observer));
    }

    public void setColor(Color newColor) {
        if (this.currentColor != newColor) {
            this.currentColor = newColor;
            notifyObservers(newColor);
        }
    }

    // 仅通知符合条件的订阅者
    private void notifyObservers(Color newColor) {
        for (ObserverFilterPair pair : observerPairs) {
            if (pair.filter.test(newColor)) {
                pair.observer.onColorChanged(newColor);
            }
        }
    }
}

步骤3:注册订阅者(灵活指定过滤条件)

不需要单独定义订阅者类,直接用Lambda表达式简化:

public class Main {
    public static void main(String[] args) {
        Shape shape = new Shape();

        // Subscriber1:仅接收绿、黄、红
        shape.subscribe(
            color -> System.out.println("Subscriber1 收到通知:颜色变为 " + color),
            color -> color == Color.GREEN || color == Color.YELLOW || color == Color.RED
        );

        // Subscriber2:仅接收红
        shape.subscribe(
            color -> System.out.println("Subscriber2 收到通知:颜色变为 " + color),
            color -> color == Color.RED
        );

        // Subscriber3:接收所有颜色
        shape.subscribe(
            color -> System.out.println("Subscriber3 收到通知:颜色变为 " + color)
        );

        // 测试颜色变更
        shape.setColor(Color.BLUE);    // 仅Subscriber3收到
        shape.setColor(Color.GREEN);   // Subscriber1和3收到
        shape.setColor(Color.RED);     // 三个都收到
        shape.setColor(Color.ORANGE);  // 仅Subscriber3收到
    }
}

两种方案对比

方案优点缺点
订阅者自行过滤实现简单,Shape类逻辑单一会给所有订阅者发送通知,存在不必要的调用开销
Shape主动过滤更高效,仅发送必要通知Shape类需要维护过滤条件,逻辑稍复杂,但灵活性更强

你可以根据项目的性能需求和复杂度选择合适的方案。

内容的提问来源于stack exchange,提问作者pixel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:00:24