【设计模式】访问者模式

访问者模式

定义

访问者模式(Visitor Pattern)是面向对象编程及设计模式中的一种,它允许你在不改变一个类的层次结构的前提下,定义一个新的操作于该类层次的各个类的所有对象的算法。

解释一下:现在有一个封装好的数据结构,需要访问该数据结构的所有或部分数据,不同的数据访问可能有细微的区别,该设计模式分离了访问所有元素的操作与具体元素的操作

类图

适配器模式-类图

角色说明

  • 对象结构(Object Structure):已经封装好的数据结构,包含一系列Element对象
  • 抽象元素(Element):被访问的数据元素接口,定义了一个接受访问者的方法( accept )
  • 具体元素(ConcreteElement): 具体数据元素实现类,提供接受访问方法的具体实现。
  • 抽象访问者(Visitor):接口或者抽象类,定义了一系列操作方法,定义访问操作方法
  • 具体访问者(ConcreteVisitor):访问者接口的实现类,定义具体访问方法
  • 客户端(Client): 使用已定义好的数据结构,并访问该数据结构(间接访问所有元素)

实践

公司的一个项目的后台管理需要使用压缩包导入某些东西,压缩包中的每一级目录或元素都对应于数据库中的某些信息,毕竟压缩包是个树型结构,当时想到的做法是组合模式,但实现后发现很鸡肋,因为结构中每个元素都需要访问数据库,导致创建元素时不得不将相关DAO传过去并保存起来(因该还有更简单的做法),但是元素中包含那么多DAO总归是很奇怪的。

后来阅读了《软件设计:从专业到卓越》 这本书,在关注点分离中,作者举了个例子,就是打印文件夹中所有文件夹及文件的名字,作者经过一系列重构后得到了一个结论,遍历文件夹是一个关注点,遍历到的元素如何操作是另一个关注点,可以将两者分离开来

于是乎,我在第二次重构代码时就采用了这个方法

代码
class FileTree<T> {
	private FileTreeNode<T> root;
	public void addFile(List<String> filePath, T desc) {
        filePath.add(0, root.getFileName());
        root.addFile(filePath, desc);
    }
    public void foreach(Consumer<FileTreeNode<T>> consumer) {
        for (Map.Entry<String, FileTreeNode<T>> entry : root.getChildren().entrySet()) {
            entry.getValue().foreach(consumer);
        }
    }
}
public class FileTreeNode<T> {
    private String fileName;
    /**
     * 文件描述,可能是流,ZipEntry,File,String,byte[]
     */
    private T desc;
    private Map<String, FileTreeNode<T>> children;
    private FileTreeNode<T> parent;
    public void addFile(List<String> filePath, T desc) {
        // 添加节点
    }
    public void foreach(Consumer<FileTreeNode<T>> consumer) {
        consumer.accept(this);
        for (Map.Entry<String, FileTreeNode<T>> entry : children.entrySet()) {
            entry.getValue().foreach(consumer);
        }
    }
}

这个从某种程度上来说属于访问者模式,这里的访问者是java语言自带的函数式编程中的Consumer接口,利用关注点分离法,将具体的FileTree遍历方式与访问方式分离,从而使得foreach函数内聚性更强,更加灵活

学到这里突然发现有时候在学设计模式的时候也没必要钻牛角尖,大体知道常见设计模式的适用范围即可,这种非技术上的成长更加可贵,当你试图去了解一个设计模式,他里面蕴藏的逻辑无形之中对代码有了不可逆转的改变

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值