访问者模式-操作复杂对象结构

news2024/11/27 0:44:54

 商场里有许多的店铺,大致分为服装区、饮食区及休闲区,每天都会有络绎不绝的不同角色(打工人、学生、有钱人)的人来逛商场。商场想开发个系统用来模拟这些人的在这些店铺的行为。

public class SuperMarket {

    public static void main(String[] args) {
        List<PeopleRole> peopleRoles = new ArrayList<>();
        statisticsPeople(peopleRoles);
        Random random = new Random();
        for (PeopleRole peopleRole : peopleRoles) {
            peopleRole.showRole();
            int nextInt = random.nextInt();
            if (nextInt % 3 == 0) peopleRole.shopping(ShopPlace.food);
            else if (nextInt % 2 == 0) peopleRole.shopping(ShopPlace.clothing);
            else peopleRole.shopping(ShopPlace.relax);
            System.out.println("........................");
        }
    }

    static void statisticsPeople(List<PeopleRole> peopleRoles) {
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
            int nextInt = random.nextInt();
            if (nextInt % 2 == 0) peopleRoles.add(PeopleRole.worker);
            else if (nextInt % 3 == 0) peopleRoles.add(PeopleRole.student);
            else peopleRoles.add(PeopleRole.rich);
        }
    }

    interface SuperMarketShopping {

        void showRole();
        void shopping(ShopPlace shopPlace);
    }

    enum PeopleRole implements SuperMarketShopping{
        worker { // 打工人

            @Override
            public void showRole() {
                System.out.print("打工人:");
            }

            @Override
            public void shopping(ShopPlace shopPlace) {
                switch (shopPlace) {
                    case food:
                        System.out.println("兰州拉面");
                        break;
                    case relax:
                        System.out.println("看场电影");
                        break;
                    case clothing:
                        System.out.println("去优衣库买T恤");
                        break;
                }
            }
        },
        student { // 学生

            @Override
            public void showRole() {
                System.out.print("学生:");
            }

            @Override
            public void shopping(ShopPlace shopPlace) {
                switch (shopPlace) {
                    case food:
                        System.out.println("吃麻辣烫");
                        break;
                    case relax:
                        System.out.println("去电玩城");
                        break;
                    case clothing:
                        System.out.println("不买衣服,看一下");
                        break;
                }
            }
        },
        rich { // 有钱人

            @Override
            public void showRole() {
                System.out.print("有钱人:");
            }

            @Override
            public void shopping(ShopPlace shopPlace) {
                switch (shopPlace) {
                    case food:
                        System.out.println("鱼子酱配佛跳墙");
                        break;
                    case relax:
                        System.out.println("私人SPA");
                        break;
                    case clothing:
                        System.out.println("去Prada买衣服");
                        break;
                }
            }
        }
    }

    enum ShopPlace {
        clothing,
        food,
        relax
    }

}

上面代码存在以下问题:

1)所有业务都集中在一个类中,类功能繁多,违背单一原则。

2)条件判断语句过多。

3)如果新增一个角色或者店铺地区,那么将增加更多的条件判断语句。也违背了开闭原则。

1 访问者模式

访问者模式提供一个作用于某对象结构中的各元素的操作表示。它包含访问者(打工人、学生及有钱人)和被访问元素(服装区、饮食区及休闲区)两个主要组成部分。这些被访问的元素通常具有不同的类型,且不同的访问者对它们进行不同的访问操作。

图 访问者模式UML

Visitor,抽象访问者。为对象中每个具体元素类ConcreteElement声明一个访问操作,从这个操作的参数类型可以清楚知道访问的具体元素的类型。

ConcreteVisitor,具体访问者。实现了每个由抽象访问者声明的操作,每个操作用于访问对象结构中一种类型的元素。

Element,抽象元素。定义了一个accept方法,该方法通常以一个抽象访问者作为参数。

ConcreteElement,具体元素,实现了accept方法,在accept方法中调用访问者的访问方法以便完成对一个元素的操作。

ObjectStructure,对象结构是一个元素的集合,用于存放元素对象,并且提供了遍历其内部元素的方法。

public interface RoleVisitor {

    void visit(ClothingSpaceElement element);

    void visit(FoodSpaceElement element);

    void visit(RelaxSpaceElement element);

}

public interface SpaceElement {

    void accept(RoleVisitor visitor);

}

public class WorkVisitor implements RoleVisitor{

    @Override
    public void visit(ClothingSpaceElement element) {
        System.out.println("打工人:去优衣库买件衣服");
    }

    @Override
    public void visit(FoodSpaceElement element) {
        System.out.println("打工人:吃兰州拉面");
    }

    @Override
    public void visit(RelaxSpaceElement element) {
        System.out.println("打工人:去看场电影");
    }

}

public class StudentVisitor implements RoleVisitor{
    @Override
    public void visit(ClothingSpaceElement element) {
        System.out.println("学生:只逛逛");
    }

    @Override
    public void visit(FoodSpaceElement element) {
        System.out.println("学生:吃麻辣烫");
    }

    @Override
    public void visit(RelaxSpaceElement element) {
        System.out.println("学生:去游戏厅打游戏");
    }
}

public class RicherManVisitor implements RoleVisitor{
    @Override
    public void visit(ClothingSpaceElement element) {
        System.out.println("有钱人:买Prada的衣服");
    }

    @Override
    public void visit(FoodSpaceElement element) {
        System.out.println("有钱人:吃鱼子酱配佛跳墙");
    }

    @Override
    public void visit(RelaxSpaceElement element) {
        System.out.println("有钱人:私人SPA");
    }
}

public class ClothingSpaceElement implements SpaceElement{
    @Override
    public void accept(RoleVisitor visitor) {
        visitor.visit(this);
    }
}

public class FoodSpaceElement implements SpaceElement{
    @Override
    public void accept(RoleVisitor visitor) {
        visitor.visit(this);
    }
}

public class RelaxSpaceElement implements SpaceElement{
    @Override
    public void accept(RoleVisitor visitor) {
        visitor.visit(this);
    }
}

2 优缺点

优点:

1)增加新的访问操作很方便。只需要增加一个新的具体访问者类,实现简单,无须修改源代码,符合开闭原则。

2)将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中,类的职责更加清晰,有利于对象结构中元素对象的复用,相同的对象结构可以供多个不同的访问者访问。

缺点:

1)增加新的元素类很困难,每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每个具体访问者类中增加相应的具体操作,这违背了开闭原则。

2)破坏封装,访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态。

3 适用场景

1)一个对象结构包含多种类型的对象,希望对这些对象实施一些依赖其具体类型的操作。

2)需要对一个对象结构中的对象进行很多不同且不相关的操作,而且需要避免让这些操作“污染”这些对象的类,也不需要在增加新操作时修改这些类。

3)对象结构中元素对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1178888.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Bi-TTCOF-Zn助力CO2还原制CO

精确调控氧化还原单元的组分、空间取向或连接模式对于深入了解高效的人工光合整体反应至关重要&#xff0c;但对于异质结构光催化剂而言&#xff0c;还很难实现。 基于此&#xff0c;华南师范大学兰亚乾教授和陈宜法教授等人报道了一系列用于人工光合综合反应的氧化还原分子结…

从零入门Chrome插件开发

什么是 Chrome 插件 谷歌浏览器在推出时就以其快速、安全和简洁的特点受到了广大用户的欢迎。随着浏览器的不断发展&#xff0c;谷歌为用户提供了插件开发平台&#xff0c;使开发者能够为浏览器添加各种功能和定制化选项。从此&#xff0c;插件成为了提升用户体验和个性化的重…

02|LangChain | 从入门到实战 -六大组件之Models IO

by&#xff1a;wenwenC9 上一篇文章 01&#xff5c;LangChain | 从入门到实战-介绍 一、Models IO 组成及其说明 与语言模型的交互&#xff0c;比如在线GPT系列&#xff0c;或各种离线模型 任何语言模型应用程序的核心元素都是XXX模型。LangChain 提供了与任何语言模型交互的…

[第二章—Spring MVC的高级技术] 2.1Spring MVC配置的替代方案

7.1.1 自定义DispatcherServlet配置 例如&#xff0c;在本章稍后的内容中&#xff08;7.2节&#xff09;&#xff0c;我们将会看到如何在Spring MVC中处理multipart请求和文件上传。 如果计划使用Servlet 3.0对multipart配置的支持&#xff0c;那么需要使用DispatcherServlet的…

​软考-高级-信息系统项目管理师教程 第四版【第16章-项目采购管理-思维导图】​

软考-高级-信息系统项目管理师教程 第四版【第16章-项目采购管理-思维导图】 课本里章节里所有蓝色字体的思维导图

内窥镜项目

★ 手持pad内窥镜项目 项目描述&#xff1a;3D电子内窥镜软件项目是一个基于BS&#xff08;浏览器服务器&#xff09;架构的项目&#xff0c;旨在实现对内窥镜设备的远程控制和高级功能操作。该项目允许操作员使用平板电脑手动触摸屏上的按钮、外部按键或脚踏板 来控制内窥镜设…

[移动通讯]【Carrier Aggregation-11】【5G NR Carrier Aggregation (CA) basics 】

前言&#xff1a; 参考&#xff1a; RF Wireless world 里面的 《5G/NR - Carrier Aggregation》 《5G NR Carrier Aggregation (CA) basics | Carrier Aggregation frequency bands》 This page describes 5G NR Carrier Aggregation (CA) basics. It mentions Carrier Aggre…

Redis 的几种集群对比

文章目录 一、对比分析二、优缺点对比三、总结 如果您对Redis的了解不够深入请关注本栏目&#xff0c;本栏目包括Redis安装&#xff0c;Redis配置文件说明&#xff0c;Redis命令和数据类型说明&#xff0c;Redis持久化配置&#xff0c;Redis主从复制和哨兵机制&#xff0c;Redi…

一些常规的报错和解决方法(持续更新)

一些常规的报错和解决方法&#xff1a; 1、vue创建项目后&#xff0c;项目启动时报错You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included bu…

【JavaEE】实现简单博客系统-前端部分

文件目录&#xff1a; 展示&#xff1a; blog_list.html: <!DOCTYPE html> <html lang"cn"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><t…

05-SpringBoot中yaml文件的语法格式,在程序中读取yaml文件中数据的方式,yaml文件中引用数据的方式

yaml文件格式 语法格式 YAML(YAML Aint Markup Language)是一种数据序列化格式 , 具有容易阅读、容易与脚本语言交互、以数据为核心即重数据轻格式的特点 YAML数据常见的文件扩展名有yml格式(主流)和yaml格式两种 YAML文件的语法格式: 属性层级关系使用多行和缩进描述(同层…

第十一章《搞懂算法:聚类是怎么回事》笔记

聚类是机器学习中一种重要的无监督算法&#xff0c;可以将数据点归结为一系列的特定组合。归为一类的数据点具有相同的特性&#xff0c;而不同类别的数据点则具有各不相同的属性。 11.1 聚类算法介绍 人们将物理或抽象对象的集合分成由类似 的对象组成的多个类的过程被称为聚…

使用IDEA让文本对比不在变的困难

文章目录 前言操作1、IDEA与电脑磁盘任意文件的比较2、项目内部的文件比较3、剪切板比较4、IDEA本地历史比较5、IDEA版本历史对比 前言 在日常实际开发当中我们常常会对一些代码或内容进行比对查看是否有差异&#xff0c;这个时候不需要借用第三方比对插件&#xff0c;在IDEA中…

ubuntu 20.04 server安装

ubuntu 20.04 server安装 ubuntu-20.04.6-live-server-amd64.iso 安装 安装ubuntu20.04 TLS系统后&#xff0c;开机卡在“A start job is running for wait for network to be Configured”等待连接两分多钟。 cd /etc/systemd/system/network-online.target.wants/在[Servi…

【UE4】UE编辑器乱码问题

环境&#xff1a;UE4.27、vs2019 如何解决 问题原因&#xff0c;UE的编码默认是UTF-8&#xff0c;VS的默认编码是GBK 通过"高级保存选项" 直接修改VS的 .h头文件 的 编码 为 UTF-8 步骤1. 步骤2. 修改编码后&#xff0c;从新编译&#xff0c;然后就可以解决编辑器…

Linux基础环境开发工具的使用(二):动静态库的理解,make,makefile

Linux基础环境开发工具的使用[二] 一.动静态库的初步理解1.库的作用2.Linux和Windows中库的后缀名3.如何在Linux中看一个的库名字4.Linux中和Windows平台怎样支持开发的?5.动静态库的概念6.动静态库的优缺点与补充7.代码验证 二.make,makefile1.功能2.基本语法1.快速使用2.依赖…

SV-704LW 无线WIFI网络音柱

SV-704LW 无线WIFI网络音柱(工业级) 一、描述 SV-704LW是深圳锐科达电子有限公司的一款壁挂式WIFI无线网络音柱&#xff0c;通过WIFI无线接入到WIFI覆盖的网络中&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;其采用防水设计&#xff0c;功率可以从30W到6…

品牌如何长期占领小红书市场,小红书投放复盘怎么规划?

想要实现产品种草与品牌营销&#xff0c;达人投放成了很多品牌的选择。然而随着达人协助成本的水涨船高&#xff0c;提高达人投放结果&#xff0c;就变得迫在眉睫。今天我们将为大家分享下&#xff0c;品牌如何长期占领小红书市场&#xff0c;小红书投放复盘怎么规划&#xff1…

找不到x3daudio1_7.dll的解决方法,快速修复x3daudio1_7.dll缺失问题

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“找不到x3daudio1_7.dll”。这个错误提示通常出现在运行某些程序或游戏时&#xff0c;这个文件是与音频设备相关的动态链接库文件&#xff0c;如果缺失或损坏&#xff0c;可能会导致软件游戏…

RabbitMQ(高级特性):限流

消费端限流 在rabbitmq中&#xff0c;使用消费端限流必须开启手动签收信息 过MQ可以对请求进行“削峰填谷”&#xff0c;即通过消费端限流的方式限制消息的拉取速度&#xff0c;达到保护消费端的目的。 生产者批量发送消息&#xff1a; Test public void testSendBatch() {…