当前位置: 首页 > article >正文

设计模式】Listener模式和Visitor模式的区别

文章目录

  • 前言
  • 一、介绍
      • Listener模式
      • Visitor模式
  • 二、代码实现
      • 2.1 Listener模式的Java实现
      • 2.2Listener模式的Go实现
      • 2.3Visitor模式的Java实现
      • 2.4Visitor模式的Go实现
  • 三、总结


前言

在软件设计中,设计模式是解决特定问题的通用解决方案。Listener模式和Visitor模式是两种常见的行为设计模式,它们在不同的场景下提供了解决问题的有效方法。本文将详细解释这两种模式,并通过Java和Go语言的代码示例展示它们的实现,最后总结它们的区别和适用场景。


一、介绍

Listener模式

Listener模式(监听器模式) 是一种行为设计模式,主要用于事件驱动的编程。它允许一个对象(监听器)注册到另一个对象(事件源),以便在特定事件发生时接收通知。

主要特点:
1.解耦: 事件源和监听器之间是松耦合的,事件源只需要知道监听器实现了某个接口,而不需要知道具体的实现细节。
2.灵活性: 可以动态添加或移除监听器。
3.异步处理: 事件通知通常是异步的,这意味着事件源在触发事件后可以继续执行其他任务,而不需要等待监听器处理完事件。

典型应用:

  • GUI应用程序中的按钮点击事件。
  • 网络编程中的数据接收事件。

Visitor模式

Visitor模式(访问者模式) 是一种行为设计模式,它允许你在不改变对象结构的前提下,定义作用于这些对象的新操作。它将操作的定义与对象结构分离,使得新的操作可以很容易地添加。

主要特点:
1.双重分派: Visitor模式使用双重分派机制,即首先调用对象的accept方法,然后在accept方法中调用访问者的visit方法。
2.扩展性: 可以很容易地添加新的操作,而不需要修改对象结构。
**3.复杂性:**增加了系统的复杂性,因为需要定义多个访问者类和accept方法。

典型应用:

  • 编译器中的语法树遍历。
  • 复杂对象结构的操作,如文件系统遍历。

二、代码实现

2.1 Listener模式的Java实现

// 定义监听器接口
public interface EventListener {
    void onEvent();
}

// 事件源类
public class EventSource {
    private List<EventListener> listeners = new ArrayList<>();

    public void addListener(EventListener listener) {
        listeners.add(listener);
    }

    public void removeListener(EventListener listener) {
        listeners.remove(listener);
    }

    public void triggerEvent() {
        for (EventListener listener : listeners) {
            listener.onEvent();
        }
    }
}

// 实现监听器
public class MyEventListener implements EventListener {
    @Override
    public void onEvent() {
        System.out.println("Event triggered!");
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        EventSource eventSource = new EventSource();
        MyEventListener listener = new MyEventListener();
        eventSource.addListener(listener);
        eventSource.triggerEvent();
    }
}

2.2Listener模式的Go实现

package main

import (
	"fmt"
)

// 定义监听器接口
type EventListener interface {
	OnEvent()
}

// 事件源类
type EventSource struct {
	listeners []EventListener
}

func (es *EventSource) AddListener(listener EventListener) {
	es.listeners = append(es.listeners, listener)
}

func (es *EventSource) RemoveListener(listener EventListener) {
	for i, l := range es.listeners {
		if l == listener {
			es.listeners = append(es.listeners[:i], es.listeners[i+1:]...)
			break
		}
	}
}

func (es *EventSource) TriggerEvent() {
	for _, listener := range es.listeners {
		listener.OnEvent()
	}
}

// 实现监听器
type MyEventListener struct{}

func (mel *MyEventListener) OnEvent() {
	fmt.Println("Event triggered!")
}

func main() {
	eventSource := &EventSource{}
	listener := &MyEventListener{}
	eventSource.AddListener(listener)
	eventSource.TriggerEvent()
}

2.3Visitor模式的Java实现

// 定义访问者接口
public interface Visitor {
    void visit(ElementA element);
    void visit(ElementB element);
}

// 定义元素接口
public interface Element {
    void accept(Visitor visitor);
}

// 具体元素A
public class ElementA implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 具体元素B
public class ElementB implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 具体访问者
public class ConcreteVisitor implements Visitor {
    @Override
    public void visit(ElementA element) {
        System.out.println("Visiting ElementA");
    }

    @Override
    public void visit(ElementB element) {
        System.out.println("Visiting ElementB");
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        List<Element> elements = Arrays.asList(new ElementA(), new ElementB());
        Visitor visitor = new ConcreteVisitor();
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

2.4Visitor模式的Go实现

package main

import (
	"fmt"
)

// 定义访问者接口
type Visitor interface {
	VisitElementA(*ElementA)
	VisitElementB(*ElementB)
}

// 定义元素接口
type Element interface {
	Accept(Visitor)
}

// 具体元素A
type ElementA struct{}

func (e *ElementA) Accept(visitor Visitor) {
	visitor.VisitElementA(e)
}

// 具体元素B
type ElementB struct{}

func (e *ElementB) Accept(visitor Visitor) {
	visitor.VisitElementB(e)
}

// 具体访问者
type ConcreteVisitor struct{}

func (cv *ConcreteVisitor) VisitElementA(e *ElementA) {
	fmt.Println("Visiting ElementA")
}

func (cv *ConcreteVisitor) VisitElementB(e *ElementB) {
	fmt.Println("Visiting ElementB")
}

func main() {
	elements := []Element{&ElementA{}, &ElementB{}}
	visitor := &ConcreteVisitor{}
	for _, element := range elements {
		element.Accept(visitor)
	}
}


三、总结

Listener模式和Visitor模式虽然都是行为设计模式,但它们解决的问题和应用场景有所不同。

  • Listener模式主要用于事件驱动的编程,适用于需要在特定事件发生时通知多个监听器的场景。它通过解耦事件源和监听器,使得系统更加灵活和可扩展。

  • Visitor模式则用于在不改变对象结构的前提下,定义新的操作。它通过双重分派机制,使得新的操作可以很容易地添加,适用于需要对复杂对象结构进行操作的场景。

通过本文的解释和代码示例,希望你能更好地理解这两种设计模式的区别和应用场景。在实际开发中,根据具体需求选择合适的设计模式,可以提高代码的可维护性和扩展性。


http://www.kler.cn/a/301166.html

相关文章:

  • 【大模型】prompt实践总结
  • 4-7-1.C# 数据容器 - LinkedList(LinkedList 的定义、LinkedList 结点的遍历、LinkedList 的常用方法)
  • SpringBoot Data Redis连接Redis-Cluster集群
  • gitlab容器的迁移(部署)并配置自动备份
  • 计算机网络-理论部分(二):应用层
  • leetcode-44-通配符匹配
  • 在JavaScript中实现简单的发布/订阅模式
  • 《C++位域:在复杂数据结构中的精准驾驭与风险规避》
  • spark读取csv文件
  • 云计算第四阶段----CLOUD 01-03
  • MySQL:视图【详解】
  • socket通讯原理及例程(详解)
  • Spring Framework系统框架
  • 函数栈帧的小知识理解
  • GEE :利用MODIS土地分类数据监测指定区域2001-2024年农作物的时序面积
  • 用HTML写一个动态的的电子相册实战详细案例
  • 论文阅读翻译之Deep reinforcement learning from human preferences
  • 分布式风电电池储能系统
  • ucx 编译安装检验方式备忘
  • 大模型笔记02--基于fastgpt和oneapi构建大模型应用平台
  • Axure高效打造大屏可视化BI数据展示
  • 主成分分析(Principal Component Analysis,PCA)—无监督学习方法
  • 深度神经网络DNN、RNN、RCNN及多种机器学习金融交易策略研究|附数据代码
  • 模拟k的次方和从0-n次方
  • 最好磁吸充电宝是哪个牌子?目前公认好用磁吸充电宝排行榜!
  • 1658.将x减到0的最小操作数