前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式——访问者模式

设计模式——访问者模式

作者头像
Java架构师必看
发布2021-05-14 10:32:59
4190
发布2021-05-14 10:32:59
举报
文章被收录于专栏:Java架构师必看

设计模式——访问者模式

强烈推介IDEA2020.2破解激活,IntelliJ IDEA 注册码,2020.2 IDEA 激活码

在开发中,有些集合存在多种不同的对象实例(例如:男人、女人),且每个对象也存在多种不同的访问者或处理方式(性格:暴躁、温和)。这样的例子还有很多,例如:好声音节目中不同评委,以及评委对他们的评价的选项,等等。这些被处理的数据元素相对稳定,而访问方式多种多样的数据结构,如果使用 “访问者模式” 来处理比较方便。访问者模式能把处理方法从数据结构中分离出来,并可以根据需要增加新的处理方式,且不用修改原来的程序代码与数据结构,这提高了代码的扩展性和灵活性。

一、访问者模式基本介绍


【1】访问者模式(Visitor Pattern)封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新操作。为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。 【2】主要将数据结构与数据操作分离:解决数据结构和操作耦合性问题。 【3】访问者模式的基本工作原理:在被访问者(上面提到的评委)的类里面加一个对外提供接待访问者的接口。 【4】访问者模式主要应用场景:需要对一个对象结构中的对象进行很多不同的操作(这些操作彼此没有关联),同时避免让这些操作 “污染” 这些类对象,可以选用访问者模式。

二、访问者模式的优缺点


【访问者(Visitor)模式,其主要优点如下】:   ● 扩展性好:能够在不修改对象结构中元素的情况下,为对象结构中的元素添加新功能;   ● 复用性好:可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用功能;   ● 灵活性好:访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由; 【访问者(Visitor)模式,其主要缺点如下】:   ● 增加新的元素类很困难:在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加响应的具体操作,违背了 “开闭原则”。   ● 破坏封装:访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性。   ● 违反了依赖倒置原则:访问模式依赖了具体类,而没有依赖抽象类。   ● 具体元素对访问者公布细节:也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的,这样造成了具体元素变得更比较困难。

三、访问者模式结构类图


访问者模式的关键在于:如何将元素的操作分离出来封装成独立的类,其基本机构如下: 【1】抽象访问者角色(Visitor)定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作,该操作中的参数类型标识了被访问的具体元素。 【2】具体访问者角色(ConcreteVisitor)实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。 【3】抽象元素角色(Element)声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept 方法的参数。 【4】具体元素角色(ConcreteElement)实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this),另外具体元素中可能包含本身业务逻辑的相关操作。 【5】对象结构角色(Object Structure)是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由List、Set、Map 等聚合类实现。

四、访问者模式案例分析


评委评价歌手是否晋级的案例

【1】抽象访问者角色

代码语言:javascript
复制
//访问者接口
public interface Action {
    //得到评委A的评价  JudgesImpl_A 具体实现类
    public void getJudage_A(JudgesImpl_A judageA);
    //得到评委B的评价
    public void getJudage_B(JudgesImpl_B judageB);
}

【2】抽象访问者的具体实现类——晋级

代码语言:javascript
复制
//晋级
public class Promotion implements Action {

    @Override
    public void getJudage_A(JudgesImpl_A judageA) {
        System.out.println("评委A名称:"+judageA.getName());
        System.out.println("给的评价是=========晋级");
    }

    @Override
    public void getJudage_B(JudgesImpl_B judageB) {
        System.out.println("评委B名称:"+judageB.getName());
        System.out.println("给的评价是=========晋级");
    }

}

【3】抽象访问者的具体实现类——淘汰

代码语言:javascript
复制
public class Eleminate implements Action{

    @Override
    public void getJudage_A(JudgesImpl_A judageA) {
        System.out.println("评委A名称:"+judageA.getName());
        System.out.println("给的评价是=========淘汰");
    }

    @Override
    public void getJudage_B(JudgesImpl_B judageB) {
        System.out.println("评委B名称:"+judageB.getName());
        System.out.println("给的评价是=========淘汰");
    }

}

【4】 抽象元素接口,包含访问者方法 accept ——评委接口

代码语言:javascript
复制
//评委接口  被访问者接口
public interface IJudges {
    //提供一个访问方法,出入访问者实例
    public void accept(Action action);
}

【5】抽象元素接口的具体实现类——评委A

代码语言:javascript
复制
//评委A  被访问者
public class JudgesImpl_A implements IJudges{
    //传入一个评委名称
    private String name;
    //构造器
    public JudgesImpl_A(String name) {
        super();
        this.name = name;
    }

    @Override
    public void accept(Action action) {
        System.out.println("具体被访问者(评委A)对象,给出的评价是==");
        action.getJudage_A(this);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

【6】抽象元素接口的具体实现类——评委B

代码语言:javascript
复制
//评委B  被访问者
public class JudgesImpl_B implements IJudges{
    private String name;
    //构造器
    public JudgesImpl_B(String name) {
        super();
        this.name = name;
    }

    @Override
    public void accept(Action action) {
        System.out.println("具体被访问者(评委B)对象,给出的评价是==");
        action.getJudage_B(this);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

【7】对象结构实现类,将被访问类进行封装。

代码语言:javascript
复制
//将评委评论进行统计
public class ObjectStrFactory {
    //维护一个被访问者集合
    private List<IJudges> judage = new LinkedList();

    //添加评委
    public void add(IJudges jud) {
        judage.add(jud);
    }
    //移除评委
    public void remove(IJudges jud) {
        judage.remove(jud);
    }
    //展示评论
    public void disply(Action action) {
        for (IJudges iJudges : judage) {
            iJudges.accept(action);
        }
    }
}

【8】客户端调用

代码语言:javascript
复制
public class Client {
    public static void main(String[] args) {
        //创建结构体工厂
        ObjectStrFactory objectStrFactory = new ObjectStrFactory();
        //添加评委
        objectStrFactory.add(new JudgesImpl_A("周杰伦"));
        objectStrFactory.add(new JudgesImpl_B("蔡徐坤"));
        //展示评价:晋级的评价
        /**
         * 输出:
         * 具体被访问者(评委A)对象,给出的评价是==
         * 评委A名称:周杰伦
         * 给的评价是=========晋级
         * 具体被访问者(评委B)对象,给出的评价是==
         * 评委B名称:蔡徐坤
         * 给的评价是=========晋级
         */
        objectStrFactory.disply(new Promotion());
        //如果评价是 淘汰
        /**
         * 输入:
         * 具体被访问者(评委A)对象,给出的评价是==
         * 评委A名称:周杰伦
         * 给的评价是=========淘汰
         * 具体被访问者(评委B)对象,给出的评价是==
         * 评委B名称:蔡徐坤
         * 给的评价是=========淘汰
         */
        objectStrFactory.disply(new Eleminate());
    }
}

五、访问者模式的优点实操


当需要扩展一个 “待定” 的元素选项时,非常方便,简单两步操作即可完成: 【1】添加 “待定” 元素的实体类,如下:并实现所有评委给的 “待定评价” 即可。

代码语言:javascript
复制
//待定
public class Wait implements Action{

    @Override
    public void getJudage_A(JudgesImpl_A judageA) {
        System.out.println("评委A名称:"+judageA.getName());
        System.out.println("给的评价是=========待定");
    }

    @Override
    public void getJudage_B(JudgesImpl_B judageB) {
        System.out.println("评委B名称:"+judageB.getName());
        System.out.println("给的评价是=========待定");
    }

}

【2】客户端调用时,只需传入待定的实体类,便可获取待定评价。通过扩展我们才看出来访问者模式的强大之处。

代码语言:javascript
复制
public class Client {
    public static void main(String[] args) {
                //输出
        /**
         * 具体被访问者(评委B)对象,给出的评价是==
         * 评委B名称:蔡徐坤
         * 给的评价是=========淘汰
         * 具体被访问者(评委A)对象,给出的评价是==
         * 评委A名称:周杰伦
         * 给的评价是=========待定
         * 具体被访问者(评委B)对象,给出的评价是==
         * 评委B名称:蔡徐坤
         * 给的评价是=========待定
         */
        objectStrFactory.disply(new Wait());
    }
}
所属专题
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、访问者模式基本介绍
  • 二、访问者模式的优缺点
  • 三、访问者模式结构类图
  • 四、访问者模式案例分析
  • 五、访问者模式的优点实操
    • 所属专题
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档