0 观察者模式的传统写法不再被需要
观察者模式的作用:
核心观点:将 对数据的操作 和 数据本身 做了解耦,新添加数据操作的时候,对数据本身的类不会有任何修改
1 观察者模式实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| public class VisitorDemo { public static void main(final String[] args) { Car car = new Car(); car.accept(new CarElementPrintVisitor()); } }
interface CarElement { void accept(CarElementVisitor visitor); }
interface CarElementVisitor { void visit(Body body); void visit(Car car); void visit(Engine engine); } class Body implements CarElement { @Override public void accept(CarElementVisitor visitor) { visitor.visit(this); } } class Engine implements CarElement { @Override public void accept(CarElementVisitor visitor) { visitor.visit(this); } } class Car implements CarElement { private final List<CarElement> elements; public Car() { this.elements = List.of(new Body(), new Engine()); } @Override public void accept(CarElementVisitor visitor) { for (CarElement element : elements) { element.accept(visitor); } visitor.visit(this); } } class CarElementPrintVisitor implements CarElementVisitor { @Override public void visit(Body body) { System.out.println("Visiting body"); } @Override public void visit(Car car) { System.out.println("Visiting car"); } @Override public void visit(Engine engine) { System.out.println("Visiting engine"); } }
|
2 利用封装接口和类型switch特性(java17) 快速达到目标
代码少了一半,但是效果确完全相同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class VisitorDemo { public static void main(final String[] args) { Car car = new Car(); print(car); } private static void print(Car car) { car.elements() .map(element -> switch (element) { case Body body -> "Visiting body"; case Car car_ -> "Visiting car"; case Engine engine -> "Visiting engine"; }) .forEach(System.out::println); } }
sealed interface CarElement permits Body, Engine, Car { } class Body implements CarElement { } class Engine implements CarElement { } class Car implements CarElement { private final List<CarElement> elements; public Car() { this.elements = List.of(new Body(), new Engine()); } public Stream<CarElement> elements() { return Stream.concat(elements.stream(), Stream.of(this)); } }
|
使用注意:
使结构类型的接口密封 (你不应修改密封接口,若要修改,参见3)
对于操作,使用模式开关来确定每种类型的代码路径 (从switch到具体的类的类型)
避免使用默认分支,这样当你修改类型接口时,你才能获得在每个switch中出现编译错误,这可以引导你去修改