设计模式-访问者模式

访问者模式(Visitor Pattern)是一种行为型设计模式,用于在不更改现有对象结构的情况下,定义对对象结构中各个元素的访问操作。它将算法与元素的结构分离,使得可以在不改变元素类的前提下,定义新的操作。

 

访问者模式由以下几个核心角色组成:

  1. 访问者(Visitor):定义了对元素对象的不同访问操作,为每种元素类型都提供了访问方法。通常通过多态的方式来实现对不同元素的处理。
  2. 具体访问者(Concrete Visitor):实现了访问者接口,定义了对不同元素类型的具体访问操作。
  3. 元素(Element):定义了接受访问者访问的接口,可以是一个或多个具体元素类。
  4. 具体元素(Concrete Element):实现了元素接口,定义了接受访问者访问的具体操作。
  1. 对象结构(Object Structure):存储和管理元素对象的集合,提供访问者访问元素的接口。

 

访问者模式的工作流程如下:

  1. 客户端创建并配置具体访问者对象。
  2. 客户端创建元素对象,并将它们添加到对象结构中。
  3. 对象结构提供接收访问者的方法,将具体访问者作为参数传递给元素对象。
  4. 元素对象调用接受访问者的方法,传递自身,并调用访问者的相应方法。
  5. 具体访问者根据访问的元素类型执行相应的操作,可以通过重载或多态的方式实现。

 

访问者模式的优点包括:

  1. 符合开闭原则:通过让元素类保持稳定,将新的操作添加到访问者类中,实现了对元素类的扩展而无需修改元素类本身。
  2. 将相关操作集中管理:将对一个复杂对象的一组操作定义在一个访问者类中,使得这些操作在一个对象结构中可以一致地应用,提高了系统的可维护性。
  3. 增加新的访问者类相对容易:在需要增加新的操作时,只需要实现一个新的访问者类,符合了单一职责原则。

 

然而,访问者模式也存在一些缺点

  1. 增加新的元素类相对困难:当需要添加新的元素类时,除了需要创建新的元素类,还需要修改所有的访问者类,违反了开闭原则。
  2. 破坏封装:元素对象需要将自身传递给访问者对象,使得元素对象的细节暴露给了访问者对象,破坏了元素对象的封装性。

 

下面是一个简单的访问者模式的示例代码,以电影院中观众对电影进行评分为例:

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

// 具体元素:电影类
class Movie implements Element {
    private String name;
    private double rating;

    public Movie(String name, double rating) {
        this.name = name;
        this.rating = rating;
    }

    public String getName() {
        return name;
    }

    public double getRating() {
        return rating;
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 访问者接口
interface Visitor {
    void visit(Movie movie);
}

// 具体访问者:评分访问者类
class RatingVisitor implements Visitor {
    @Override
    public void visit(Movie movie) {
        double rating = movie.getRating();
        System.out.println("评分电影:" + movie.getName() + ",评分:" + rating);
    }
}

// 具体访问者:观众类型访问者类
class AudienceTypeVisitor implements Visitor {
    @Override
    public void visit(Movie movie) {
        String name = movie.getName();
        double rating = movie.getRating();
        if (rating >= 8.0) {
            System.out.println("电影:" + name + " 是一部优秀的影片");
        } else if (rating >= 6.0) {
            System.out.println("电影:" + name + " 是一部不错的影片");
        } else {
            System.out.println("电影:" + name + " 是一部一般的影片");
        }
    }
}

// 对象结构:电影院类
class MovieTheater {
    private List<Element> movies;

    public MovieTheater() {
        movies = new ArrayList<>();
    }

    public void addMovie(Element movie) {
        movies.add(movie);
    }

    public void accept(Visitor visitor) {
        for (Element movie : movies) {
            movie.accept(visitor);
        }
    }
}

// 客户端代码
public class VisitorDemo {
    public static void main(String[] args) {
        // 创建电影院和电影
        MovieTheater movieTheater = new MovieTheater();
        movieTheater.addMovie(new Movie("The Shawshank Redemption", 9.3));
        movieTheater.addMovie(new Movie("Inception", 8.8));
        movieTheater.addMovie(new Movie("The Dark Knight", 9.0));

        // 创建访问者并进行访问
        Visitor ratingVisitor = new RatingVisitor();
        movieTheater.accept(ratingVisitor);

        Visitor audienceTypeVisitor = new AudienceTypeVisitor();
        movieTheater.accept(audienceTypeVisitor);
    }
}

 

在上述示例中,我们定义了一个元素接口 Element,包含了一个 accept()方法用于接受访问者访问。具体的元素类 Movie 实现了 Element 接口,并提供了一些辅助方法。

访问者接口 Visitor 定义了不同类型的访问方法,其中 visit(Movie movie) 是用于访问电影元素的方法。

具体访问者类 RatingVisitorAudienceTypeVisitor 实现了 Visitor 接口,并针对不同的访问操作给出了具体的实现。

对象结构类 MovieTheater 维护着一组电影元素对象,并提供了 accept() 方法来让访问者访问这些电影。在 accept() 方法内部,会依次调用每个电影元素的 accept() 方法,将自身作为参数传递给访问者。

最后,我们在客户端代码中创建了一个电影院对象,添加了几个电影元素,并创建了评分访问者和观众类型访问者。通过调用电影院对象的 accept() 方法,并传入不同的访问者,实现对电影的评分和观众类型的判断。

输出结果为:

评分电影:The Shawshank Redemption,评分:9.3
评分电影:Inception,评分:8.8
评分电影:The Dark Knight,评分:9.0
电影:The Shawshank Redemption 是一部优秀的影片
电影:Inception 是一部不错的影片
电影:The Dark Knight 是一部优秀的影片

通过访问者模式,我们可以将数据结构和数据操作相分离,实现了对元素的不同访问操作,而不需要修改元素类的结构。这样可以提高代码的可扩展性和灵活性。

 

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
访问者模式是GOF设计模式中的一种行为型模式。它被描述为最复杂且最难以理解的一种模式。访问者模式的目的是封装一些作用于某种数据结构中的各元素的操作,可以在不改变这些元素的类的前提下定义这些操作。它通过将数据结构与操作分离,使得可以在不改变数据结构的前提下添加新的操作,提高了代码的灵活性和可扩展性。 访问者模式的构成包括元素(Element)、访问者(Visitor)和对象结构(Object Structure)。元素表示数据结构中的各个元素,它们通常会提供一个接受访问者的方法。访问者则表示对元素的操作,它们可以根据具体的元素类型进行不同的操作。对象结构则是一个容器,用于存放元素,并提供让访问者访问元素的接口。 访问者模式适用于数据结构相对稳定,但其操作经常发生变化的情况。它可以将操作的变化封装在访问者中,而无需改变元素的类。这样一来,当需要新增一种操作时,只需要新增一个访问者,而不需要改变元素的类。 访问者模式的优点包括增加新的操作非常方便,由于具体访问者类与具体元素类之间没有直接的关联,因此增加新的访问者类对原有类库无影响。同时,它也符合开闭原则,对于元素的类库可以在不修改源代码的情况下添加新的操作。 总结起来,访问者模式是一种通过将数据结构与操作分离的设计模式,可以在不改变数据结构的前提下添加新的操作。它的构成包括元素、访问者和对象结构,适用于数据结构相对稳定,但操作经常变化的情况。访问者模式的优点包括增加新的操作方便,符合开闭原则。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [详解设计模式访问者模式](https://blog.csdn.net/weixin_45187434/article/details/128197861)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [设计模式 访问者模式](https://download.csdn.net/download/zjn640322/9685149)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值