设计模式:访问者模式

定义

访问者模式(Visitor Pattern)是一种将算法与对象结构分离的设计模式。这种模式中,可以在不修改已有程序结构的前提下,通过添加额外的“访问者”来定义作用于对象结构中各元素的新操作。它主要解决的是稳定的数据结构和易变的操作耦合问题。

应用场景

  • 当一个对象结构包含很多类对象,且这些类的对象对应的操作经常变化时。
  • 当需要对一个复杂的对象结构进行一些不依赖于对象具体类型的操作时。
  • 当需要对对象结构中的对象进行很多不同且不相关的操作,而需要避免让这些操作“污染”对象的类时。

示例代码

假设有一个电子商务系统,需要对不同类型的用户(如普通用户和VIP用户)进行不同的促销活动。

访问者接口和具体的访问者实现

interface Visitor {
    void visit(NormalUser user);
    void visit(VIPUser user);
}

class PromotionVisitor implements Visitor {
    @Override
    public void visit(NormalUser user) {
        System.out.println("给普通用户发送优惠券");
    }

    @Override
    public void visit(VIPUser user) {
        System.out.println("给VIP用户发送优惠券和积分");
    }
}

用户类接受访问的接口

interface User {
    void accept(Visitor visitor);
}

class NormalUser implements User {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

class VIPUser implements User {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

客户端代码

public class Client {
    public static void main(String[] args) {
        List<User> users = Arrays.asList(new NormalUser(), new VIPUser());
        Visitor promotion = new PromotionVisitor();
        
        for (User user : users) {
            user.accept(promotion);
        }
    }
}

反例

当对象结构非常稳定,几乎不会新增元素类型,同时操作经常变化时,使用访问者模式是合适的。如果对象结构经常变化,则每次新增类型都需要修改访问者接口和所有实现类,这违背了开闭原则,此时应考虑其他设计模式。

原则间的权衡与冲突

  • 开闭原则:访问者模式支持在不修改已有对象结构的情况下,向已有对象结构中添加新操作,符合开闭原则。但如果需要添加新的元素类,就需要修改访问者接口及其所有实现,这违背了开闭原则。
  • 单一职责原则:访问者模式允许将操作逻辑从对象结构中分离出来,每个访问者执行特定的操作,符合单一职责原则。

设计模式的局限性

  • 增加新的元素类比较困难,每添加一个新的元素类,都要在Visitor接口中添加一个新的访问操作,并在所有的访问者实现类中实现该操作,这使得系统变得复杂。
  • 访问者模式使得对象结构的修改变得困难,因为访问者依赖于对象结构中元素的具体类。

总结与建议

访问者模式适用于对象结构相对稳定,而操作易变的场景。它使得增加新操作变得简单,但增加新的元素类较为复杂。在使用访问者模式时,应该权衡其带来的灵活性和可能的复杂性。在对象结构频繁变化的场景下,应考虑其他设计模式。

相关推荐

  1. 设计模式——访问模式

    2024-04-21 13:24:03       50 阅读
  2. 设计模式访问模式

    2024-04-21 13:24:03       35 阅读
  3. 设计模式访问模式

    2024-04-21 13:24:03       33 阅读
  4. 【前端设计模式】之访问模式

    2024-04-21 13:24:03       58 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-21 13:24:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-21 13:24:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-21 13:24:03       82 阅读
  4. Python语言-面向对象

    2024-04-21 13:24:03       91 阅读

热门阅读

  1. Flutter-----异步编程:Future和Stream

    2024-04-21 13:24:03       35 阅读
  2. 【Python图像处理篇】opencv中的去畸变

    2024-04-21 13:24:03       35 阅读
  3. 设计模式:中介者模式

    2024-04-21 13:24:03       32 阅读
  4. 汽车笔记-保险

    2024-04-21 13:24:03       36 阅读