前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【设计模式】访问者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

【设计模式】访问者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

作者头像
韩曙亮
发布2023-03-29 15:27:42
3220
发布2023-03-29 15:27:42
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

一、访问者模式简介


访问者模式 : 封装 作用于 某种 数据结构 的 各元素 操作 , 数据结构指的是 List , Set , Map 等 ;

在 不改变 元素类 的前提下 , 定义 作用于 元素 的操作 ;

访问者模式类型 : 行为型 ;

二、访问者模式 适用场景


访问者模式 适用场景 :

  • List , Set , Map 等 数据结构 中 , 包含 很多类型的对象 ;
  • 数据结构 与 数据操作 分离 ;

三、访问者模式 优缺点


访问者模式 优点 : 访问者模式 增加新的操作 很容易 , 只需要增加一个新的 访问者 即可 ; 将相关的行为 , 封装到一个 访问者 中 ;

访问者模式 缺点 :

  • 增加 新 数据结构 比较困难 ;
  • 元素变更 比较困难 ; 如 为 被访问 的对象 增加 / 减少 一些属性 , 相应的 访问者 也需要进行修改 ;

四、访问者模式 与 迭代器模式


访问者模式 与 迭代器模式 都是在 某种 数据结构 ( List / Set / Map ) 上进行处理 ;

访问者模式 主要用于 对 保存在 数据结构 中元素 , 进行某种特定处理 , 重点是 处理 ;

迭代器模式 主要作用就是 遍历 数据结构 中的元素 , 重点是 遍历 ;

五、代码示例


游戏 分为 免费游戏 和 收费游戏 , 玩家 分为 免费玩家 和 付费玩家 ;

不同的玩家 , 访问不同的游戏 , 各自有不同的效果 ;

被访问者 , 都继承自同一个父类 , 可以放在一个集合中 ;

访问者 , 都实现同一个接口 , 针对每个类型的被访问者 , 都有一个对应的重载方法 ;

如 : 玩家访问者 , 对免费游戏有一个方法 , 对收费游戏也有一个方法 ;

该设计模式不常用 , 如果遇到 数据加载 与 数据操作 分离的情况 , 可以考虑使用 访问者模式 ;

大部分情况下 , 用不到 , 但是一旦需要用到的时候 , 访问者模式是唯一的解决方案 ;

1、Game 父类 ( 被访问者 )

代码语言:javascript
复制
package visitor;

/**
 * 游戏父类 , 所有的游戏都要继承该类
 *      VipGame 和 FreeGame 都继承 Game , 这两个都是 Game
 *
 */
public abstract class Game {
    /**
     * 游戏名称
     */
    private String mGameName;

    public String getGameName() {
        return mGameName;
    }

    public void setGameName(String gameName) {
        this.mGameName = gameName;
    }

    /**
     * 当有访问者要访问游戏时 , 将访问者传入该方法
     *      用于判定访问者是否有权限访问游戏
     * @param visitor
     */
    public abstract void accept(IVisitor visitor);
}

2、VipGame 收费游戏 ( 被访问者 )

代码语言:javascript
复制
package visitor;

public class VipVisitor implements IVisitor {

    /**
     * 访问免费游戏 , 打印游戏名称
     * @param freeGame
     */
    @Override
    public void visit(FreeGame freeGame) {
        System.out.println("我是 VIP , 可以访问免费游戏 : " + freeGame.getGameName());
    }

    /**
     * 访问收费游戏 , 打印游戏名称和价格
     * @param vipGame
     */
    @Override
    public void visit(VipGame vipGame) {
        System.out.println("我是 VIP , 可以访问收费游戏 : " + vipGame.getGameName() + " , 价格 : " + vipGame.getmVipPrice());
    }
}

3、FreeGame 免费游戏 ( 被访问者 )

代码语言:javascript
复制
package visitor;

/**
 * 免费游戏
 */
public class FreeGame extends Game {
    @Override
    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }
}

4、IVisitor 访问者接口

代码语言:javascript
复制
package visitor;

/**
 * 该接口中声明了两个重载方法
 *      访问 FreeGame 的 visit 方法
 *      访问 VipGame 的 visit 方法
 *
 * 在 Game 中调用 visit 方法 , 将自身传递到 visit 方法作为参数
 *      分别调用不同的重载方法
 *
 * 访问者可以扩展很多了 , 可以定义若干实现了 IVisitor 接口的访问者
 *      每个 Visistor 访问者 , 访问不同的游戏 , 有不同的表现 , 如 :
 *          白嫖访问者 , 不花钱 , 只能玩免费游戏 , 不能玩收费游戏
 *          付费访问者 , 购买 VIP , 可以同时玩免费和收费游戏
 *
 *  对于免费游戏来说 , 传入任何访问者都可以访问 ;
 *  对于收费游戏来说 , 传入付费访问者, 才可以访问 ;
 *
 *  相同的 Visitor 对不同的数据产生不同的行为
 *  不同的 Visitor 对相同的数据产生不同的行为
 */
public interface IVisitor {

    /**
     * 访问免费游戏
     * @param freeGame
     */
    void visit(FreeGame freeGame);

    /**
     * 访问收费游戏
     * @param vipGame
     */
    void visit(VipGame vipGame);
}

5、VipVisitor 付费玩家

代码语言:javascript
复制
package visitor;

public class VipVisitor implements IVisitor {

    /**
     * 访问免费游戏 , 打印游戏名称
     * @param freeGame
     */
    @Override
    public void visit(FreeGame freeGame) {
        System.out.println("我是 VIP , 可以访问免费游戏 : " + freeGame.getGameName());
    }

    /**
     * 访问收费游戏 , 打印游戏名称和价格
     * @param vipGame
     */
    @Override
    public void visit(VipGame vipGame) {
        System.out.println("我是 VIP , 可以访问收费游戏 : " + vipGame.getGameName() + " , 价格 : " + vipGame.getmVipPrice());
    }
}

6、测试类

代码语言:javascript
复制
package visitor;

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        // 创建存放 Game 的集合
        ArrayList<Game> games = new ArrayList<>();

        // 创建免费游戏
        FreeGame freeGame = new FreeGame();
        freeGame.setGameName("超级马里奥");
        games.add(freeGame);

        // 创建收费游戏
        VipGame vipGame = new VipGame();
        vipGame.setGameName("绝地求生");
        vipGame.setmVipPrice(88);
        games.add(vipGame);

        // Vip 访问者访问免费和收费游戏
        for (Game game : games) {
            game.accept(new VipVisitor());
        }
    }
}

运行结果 :

在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-08-13,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、访问者模式简介
  • 二、访问者模式 适用场景
  • 三、访问者模式 优缺点
  • 四、访问者模式 与 迭代器模式
  • 五、代码示例
    • 1、Game 父类 ( 被访问者 )
      • 2、VipGame 收费游戏 ( 被访问者 )
        • 3、FreeGame 免费游戏 ( 被访问者 )
          • 4、IVisitor 访问者接口
            • 5、VipVisitor 付费玩家
              • 6、测试类
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档