ITPub博客

首页 > 数据库 > 数据库开发技术 > 行为型设计模式(五):访问者模式 & 观察者模式

行为型设计模式(五):访问者模式 & 观察者模式

原创 数据库开发技术 作者:灸哥漫谈 时间:2023-12-22 00:09:36 0 删除 编辑

访问者模式 Visitor

1、什么是访问者模式

访问者模式允许定义一些不改变数据结构的前提下的操作。通过这种方式,可以在不修改元素类的情况下定义新的操作。访问者模式常用于对复杂对象结构进行操作,而又不希望在这些对象上破坏封装性。

2、为什么使用访问者模式

  1. 访问者模式将数据结构和操作分离,使得新增操作更加灵活,而不影响数据结构。

  2. 可以通过定义新的访问者来增加新的操作,而无需修改元素类,可扩展性强

3、如何使用访问者模式

设计实现一个图形编辑器,包含不同图形类型和对应的不同的操作

// 抽象元素类interface Shape {    void accept(Visitor visitor);}
// 具体元素类1:圆形class Circle implements Shape { private int radius;
Circle(int radius) { this.radius = radius; }
public int getRadius() { return radius; }
@Override public void accept(Visitor visitor) { visitor.visit(this); }}
// 具体元素类2:矩形class Rectangle implements Shape { private int width; private int height;
Rectangle(int width, int height) { this.width = width; this.height = height; }
public int getWidth() { return width; }
public int getHeight() { return height; }
@Override public void accept(Visitor visitor) { visitor.visit(this); }}
// 抽象访问者interface Visitor { void visit(Circle circle);
void visit(Rectangle rectangle);}
// 具体访问者1:移动操作class MoveVisitor implements Visitor { private int deltaX; private int deltaY;
MoveVisitor(int deltaX, int deltaY) { this.deltaX = deltaX; this.deltaY = deltaY; }
@Override public void visit(Circle circle) { System.out.println("Moving circle with radius " + circle.getRadius() + " by (" + deltaX + ", " + deltaY + ")"); }
@Override public void visit(Rectangle rectangle) { System.out.println("Moving rectangle with width " + rectangle.getWidth() + " and height " + rectangle.getHeight() + " by (" + deltaX + ", " + deltaY + ")"); }}
// 具体访问者2:缩放操作class ScaleVisitor implements Visitor { private double scaleFactor;
ScaleVisitor(double scaleFactor) { this.scaleFactor = scaleFactor; }
@Override public void visit(Circle circle) { System.out.println("Scaling circle with radius " + circle.getRadius() + " by factor " + scaleFactor); }
@Override public void visit(Rectangle rectangle) { System.out.println("Scaling rectangle with width " + rectangle.getWidth() + " and height " + rectangle.getHeight() + " by factor " + scaleFactor); }}
// 客户端代码public class Client { public static void main(String[] args) { Shape circle = new Circle(5); Shape rectangle = new Rectangle(10, 8);
Visitor moveVisitor = new MoveVisitor(2, 3); Visitor scaleVisitor = new ScaleVisitor(1.5);
// 执行移动操作 circle.accept(moveVisitor); rectangle.accept(moveVisitor);
// 执行缩放操作 circle.accept(scaleVisitor); rectangle.accept(scaleVisitor); }}

4、是否存在缺陷和不足

如果系统中新增了一个元素类,所有的具体访问者类都需要修改,不符合开闭原则。

5、如何缓解缺陷和不足

可以通过引入抽象访问者,将新增元素类的访问方法定义在抽象访问者中,然后具体访问者类只需要实现必要的访问方法。

观察者模式 Observer

1、什么是观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象。当主题对象状态发生变化时,所有依赖它的观察者都会得到通知并自动更新。

2、为什么使用观察者模式

  1. 观察者模式实现了发布者和订阅者之间的松耦合,使得它们可以独立变化,不影响彼此。

  2. 新的观察者可以随时加入,而不影响发布者的实现,可扩展性强。

3、如何使用观察者模式

设计实现一个简单的新闻订阅系统,其中有多个订阅者订阅不同类型的新闻

import java.util.ArrayList;import java.util.List;
// 主题接口interface Subject { void addObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers(String news);}
// 具体主题:新闻发行class NewsPublisher implements Subject { private List<Observer> observers;
NewsPublisher() { this.observers = new ArrayList<>(); }
@Override public void addObserver(Observer observer) { observers.add(observer); }
@Override public void removeObserver(Observer observer) { observers.remove(observer); }
@Override public void notifyObservers(String news) { for (Observer observer : observers) { observer.update(news); } }}
// 观察者接口interface Observer { void update(String news);}
// 具体观察者1:普通订阅者class RegularSubscriber implements Observer { private String name;
RegularSubscriber(String name) { this.name = name; }
@Override public void update(String news) { System.out.println(name + " received regular news: " + news); }}
// 具体观察者2:紧急订阅者class UrgentSubscriber implements Observer { private String name;
UrgentSubscriber(String name) { this.name = name; }
@Override public void update(String news) { System.out.println(name + " received urgent news: " + news); }}
// 客户端代码public class Client { public static void main(String[] args) { // 创建新闻发行主题 NewsPublisher newsPublisher = new NewsPublisher();
// 创建订阅者 Observer regularSubscriber1 = new RegularSubscriber("Alice"); Observer regularSubscriber2 = new RegularSubscriber("Bob"); Observer urgentSubscriber = new UrgentSubscriber("Charlie");
// 订阅者订阅主题 newsPublisher.addObserver(regularSubscriber1); newsPublisher.addObserver(regularSubscriber2); newsPublisher.addObserver(urgentSubscriber);
// 发布新闻 newsPublisher.notifyObservers("Important news: COVID-19 vaccine breakthrough!"); newsPublisher.notifyObservers("Regular news: Weather forecast for the week");
// 移除一个订阅者 newsPublisher.removeObserver(regularSubscriber2);
// 再次发布新闻 newsPublisher.notifyObservers("Urgent news: Emergency evacuation due to natural disaster!"); }}

4、是否存在缺陷和不足

  1. 在观察者模式中,观察者的更新顺序是不确定的,可能导致一些依赖顺序的问题。

  2. 通知模式比较单一,通知观察者的方式是同步的,如果某个观察者的更新操作耗时较长,可能影响整体性能。

5、如何缓解缺陷和不足

  1. 可以使用队列将观察者的更新操作异步执行,避免影响主题的通知效率。

  2. 可以引入顺序控制机制,明确观察者的更新顺序。


原文作者:灸哥漫谈;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2023-11-26

  • 博文量
    368
  • 访问量
    173281