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
相关产品推荐
相关产品推荐

