【软考】设计模式之访问者模式

目录

        • 1. 说明
        • 2. 应用场景
        • 3. 结构图
        • 4. 构成
        • 5. java示例
          • 5.1 喂动物
            • 5.1.1 抽象访问者
            • 5.1.2 具体访问者
            • 5.1.3 抽象元素
            • 5.1.4 具体元素
            • 5.1.5 对象结构
            • 5.1.6 客户端类
            • 5.1.7 结果示例
          • 5.2 超市销售系统
            • 5.2.1 业务场景
            • 5.2.2 业务需求类图
            • 5.2.3 抽象访问者
            • 5.2.4 具体访问者
            • 5.2.5 抽象元素
            • 5.2.6 具体元素
            • 5.2.7 对象结构
            • 5.2.8 客户端类
            • 5.2.9 结果示例
            • 5.2.10 改进

1. 说明
  • 1.访问者设计模式(Visitor Design Pattern)是一种常见的软件设计模式
  • 2.属于行为型设计模式,行为型对象模式
  • 3.目的:分离数据结构与数据操作,在不改变元素数据结构的情况下,进行添加元素操作
2. 应用场景
  • 1.类的结构改变较少,但经常要增加新的基于该结构的操作
  • 2.需要对某一对象结构的对象进行很多不同的并且不相关的操作,而需要避免让这些操作污染这些对象的类,也不希望在新增操作时修改这些类
3. 结构图

在这里插入图片描述

4. 构成
  • 1.访问者模式由抽象访问者、具体访问者、抽象元素、具体元素、对象结构等角色构成
  • 2.抽象访问者(Visitor):定义访问具体元素的接口,为每个具体元素类声明一个Visit操作,该操作的参数类型标识了被访问的具体元素
  • 3.具体访问者(ConcreteVisitor):实现抽象访问者中声明的各个Visit操作
  • 4.抽象元素(Element):声明一个包含接受操作Accept()的接口,Accept()参数为被接受访问者
  • 5.具体元素(ConcreteElement):实现一个访问者为参数的Accept操作
  • 6.对象结构(ObjectStructure):包含抽象元素的容器,提供让访问者对象遍历容器中所有元素的方法(List、Set、Map等)
5. java示例
5.1 喂动物
5.1.1 抽象访问者
  • 1.一个抽象访问者接口
  • 2.定义访问具体元素的方法feed,为每个具体元素类声明一个喂养的方法,喂狗和喂猫,喂养操作的参数类型标识了被访问的具体元素为狗和猫
package com.learning.visitor;
/**
* 抽象访问者
*/
public interface Person {
    public void feed(Dog dog);

    public void feed(Cat cat);
}

5.1.2 具体访问者
  • 1.具体访问者(ConcreteVisitor):实现抽象访问者中声明的各个Visit操作
  • 2.自家主人实现抽象访问者中声明的喂狗、喂猫操作
  • 3.其他人实现抽象访问者中声明的喂狗、喂猫操作
package com.learning.visitor;

/**
 *  自家主人
 */
public class Owner implements Person{
    @Override
    public void feed(Cat cat) {
        System.out.println("主人喂食猫");
    }

    @Override
    public void feed(Dog dog) {
        System.out.println("主人喂食狗");
    }
}
package com.learning.visitor;

/**
 * 其他人
 */
public class Someone implements Person{

    @Override
    public void feed(Dog dog) {
        System.out.println("其他人喂食狗");
    }

    @Override
    public void feed(Cat cat) {
        System.out.println("其他人喂食猫");
    }
}
5.1.3 抽象元素
  • 1.定一个动物接口,声明一个接收一个人的方法
  • 2.表明是谁喂,参数人为被接受访问者
package com.learning.visitor;
/**
* 抽象元素  动物
*/
public interface Animal {
    void accept(Person person);
}
5.1.4 具体元素
  • 1.实现accept操作,参数是一个访问者
package com.learning.visitor;
/**
* 狗
*/
public class Dog implements Animal{
    @Override
    public void accept(Person person) {
        person.feed(this);
        System.out.println("汪汪汪");
    }
}
package com.learning.visitor;

/**
 * 猫
 */
public class Cat implements Animal{
    @Override
    public void accept(Person person) {
        person.feed(this);
        System.out.println("喵喵喵");
    }
}
5.1.5 对象结构
  • 1.包含抽象元素的容器,提供让访问者对象遍历容器中所有元素的方法(List、Set、Map等)
  • 2.通过add方法,将具体的元素狗和猫放进List中
  • 3.提供遍历List中所有元素的方法action
package com.learning.visitor;

import java.util.ArrayList;
import java.util.List;

/**
 * 家
 */
public class Home {
    // 声明一个集合对象,用来存储元素对象
    private List<Animal> animalList = new ArrayList<>();

    // 添加元素功能
    public void add(Animal animal){
        animalList.add(animal);
    }

    public void action(Person person){
        //遍历集合,获取每一个元素,让访问者访问每一个元素
        for(Animal animal : animalList){
            animal.accept(person);
        }
    }
}

5.1.6 客户端类
package com.learning.visitor;

/**
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        //创建home对象
        Home home = new Home();
        // 添加元素到home对象中
        home.add(new Dog());
        home.add(new Cat());

        //创建主人对象
        Owner owner = new Owner();
        // 主人喂猫
        home.action(owner);

        //创建其他人对象
        Someone someone = new Someone();
        //其他人喂食
        home.action(someone);
    }
}
5.1.7 结果示例

在这里插入图片描述

5.2 超市销售系统
5.2.1 业务场景
  • 1.假设现在要创建一个简单的超市销售系统,顾客将毛巾、饼干、酸奶等物品(Item)加入购物车(Shopping_Cart),在收银台(Checkout)人工(Manual)或自动(Auto)地将购物车中每个物品的价格汇总到总价格后结账。
5.2.2 业务需求类图

在这里插入图片描述

5.2.3 抽象访问者
  • 1.该场景下,抽象访问者为收银台Checkout
  • 2.定义访问具体元素的方法checkout,为每个具体元素类声明一个结账的方法,结账操作的参数类型标识了被访问的具体元素为毛巾、饼干和酸奶等
package com.learning.visitor.shop;

// 结账接口
interface Checkout {
    // 结账毛巾
    void checkout(Towel towel);

    // 结账饼干
    void checkout(Cookie cookie);

    // 结账酸奶
    void checkout(Yogurt yogurt);
}  
5.2.4 具体访问者
  • 1.具体访问者(ConcreteVisitor):实现抽象访问者中声明的各个结账操作
  • 2.人工结账实现抽象访问者中声明的结账毛巾、饼干、酸奶操作
  • 3.自动结账实现抽象访问者中声明的结账毛巾、饼干、酸奶操作
package com.learning.visitor.shop;

// 人工结账类
public class ManualCheckout implements Checkout {

    @Override
    public void checkout(Towel towel) {
        System.out.println("人工结账毛巾");
    }

    @Override
    public void checkout(Cookie cookie) {
        System.out.println("人工结账饼干");
    }

    @Override
    public void checkout(Yogurt yogurt) {
        System.out.println("人工结账酸奶");
    }
}
package com.learning.visitor.shop;

// 自动结账类
public class AutoCheckout implements Checkout {
    @Override
    public void checkout(Towel towel) {
        System.out.println("自动结账毛巾");
    }

    @Override
    public void checkout(Cookie cookie) {
        System.out.println("自动结账饼干");
    }

    @Override
    public void checkout(Yogurt yogurt) {
        System.out.println("自动结账酸奶");
    }
}
5.2.5 抽象元素
  • 1.定一个物品接口,声明一个接收一个结账方式的方法
  • 2.表明是哪种方式结账,其中方法的参数即收银台为被接受访问者
 package com.learning.visitor.shop;

// 物品接口
public interface Item {

    void accept(Checkout checkout);
    double getPrice();
    String getName();
}  
5.2.6 具体元素
  • 1.实现accept操作,参数是一个访问者即收银台
package com.learning.visitor.shop;

/**
 * 毛巾类
 */
public class Towel implements Item{

    @Override
    public void accept(Checkout checkout) {
        checkout.checkout(this);
    }

    @Override
    public double getPrice() {
        return 5.99;
    }

    @Override
    public String getName() {
        return "毛巾";
    }
}

package com.learning.visitor.shop;

/**
 * 饼干
 */
public class Cookie implements Item {
    @Override
    public void accept(Checkout checkout) {
        checkout.checkout(this);
    }

    @Override
    public double getPrice() {
        return 2.99;
    }

    @Override
    public String getName() {
        return "饼干";
    }
}

package com.learning.visitor.shop;

/**
 * 酸奶
 */
public class Yogurt implements Item {
    @Override
    public void accept(Checkout checkout) {
        checkout.checkout(this);
    }

    @Override
    public double getPrice() {
        return 1.99;
    }

    @Override
    public String getName() {
        return "酸奶";
    }
}

5.2.7 对象结构
  • 1.包含抽象元素的容器,提供让访问者对象遍历容器中所有元素的方法(List、Set、Map等)
  • 2.通过add方法,将具体的元素毛巾、饼干、酸奶放进List中
  • 3.提供遍历List中所有元素的方法action
package com.learning.visitor.shop;

import java.util.ArrayList;
import java.util.List;  
  
// 购物车类  
public class ShoppingCart {
    private List<Item> items = new ArrayList<>();  
  
    public void addItem(Item item) {  
        items.add(item);  
    }

    /**
     * 结账action
     * @param checkout
     */
    public void action(Checkout checkout) {
        for (Item item : items) {
            item.accept(checkout);
        }
    }  
}
5.2.8 客户端类
package com.learning.visitor.shop;

/**
 * 超市销售系统
 */
public class SupermarketSystem {
    public static void main(String[] args) {  
        // 创建物品  
        Item towel = new Towel();  
        Item cookie = new Cookie();
        Item yogurt = new Yogurt();  
  
        // 创建购物车并添加物品  
        ShoppingCart cart = new ShoppingCart();  
        cart.addItem(towel);  
        cart.addItem(cookie);
        cart.addItem(yogurt);  
  
        // 使用人工结账  
        ManualCheckout manualCheckout = new ManualCheckout();
        cart.action(manualCheckout);
  
        // 使用自动结账  
        AutoCheckout autoCheckout = new AutoCheckout();  
        cart.action(autoCheckout);
    }  
}
5.2.9 结果示例

在这里插入图片描述

5.2.10 改进
  • 1.结账接口可以把购物车作为参数进行结账
// 结账接口  
interface Checkout {  
    void checkout(ShoppingCart cart);  
}  
// 人工结账类  
class ManualCheckout implements Checkout {  
    @Override  
    public void checkout(ShoppingCart cart) {  
        System.out.println("Manual Checkout");  
        System.out.println("Total price: " + cart.getTotalPrice());  
        // 在这里执行人工结账的逻辑,比如接收现金或刷卡  
    }  
}  
// 自动结账类  
class AutoCheckout implements Checkout {  
    @Override  
    public void checkout(ShoppingCart cart) {  
        System.out.println("Auto Checkout");  
        System.out.println("Total price: " + cart.getTotalPrice());  
        // 在这里执行自动结账的逻辑,比如扫描条形码或使用移动支付  
    }  
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实战:Oracle Weblogic 11g配置无密码启动,启动关闭脚本,修改节点内存

导读 上篇博文介绍了Oracle Weblogic 11g的安装部署&#xff0c;本文介绍Weblogic安装后的基本配置 包括&#xff1a;设置weblogic启动关闭的无密码验证&#xff0c;启动关闭脚本&#xff0c;修改默认的节点内存。 1、配置无密码启动 [weblogicw1 base_domain]$ cd servers/ […

C#,无监督的K-Medoid聚类算法(K-Medoid Algorithm)与源代码

1 K-Medoid算法 K-Medoid&#xff08;也称为围绕Medoid的划分&#xff09;算法是由Kaufman和Rousseeuw于1987年提出的。中间点可以定义为簇中的点&#xff0c;其与簇中所有其他点的相似度最小。 K-medoids聚类是一种无监督的聚类算法&#xff0c;它对未标记数据中的对象进行聚…

计算机网络|Socket

文章目录 Socket并发socket Socket Socket是一种工作在TCP/IP协议栈上的API。 端口用于区分不同应用&#xff0c;IP地址用于区分不同主机。 以下是某一个服务器的socket代码。 其中with是python中的一个语法糖&#xff0c;代表当代码块离开with时&#xff0c;自动对s进行销毁…

Java 石头剪刀布小游戏

一、任务 编写一个剪刀石头布游戏的程序。程序启动后会随机生成1~3的随机数&#xff0c;分别代表剪刀、石头和布&#xff0c;玩家通过键盘输入剪刀、石头和布与电脑进行5轮的游戏&#xff0c;赢的次数多的一方为赢家。若五局皆为平局&#xff0c;则最终结果判为平局。 二、实…

chrome选项页面options page配置

options 页面用以定制Chrome浏览器扩展程序的运行参数。 通过Chrome 浏览器的“工具 ->更多工具->扩展程序”&#xff0c;打开chrome://extensions页面&#xff0c;可以看到有的Google Chrome扩展程序有“选项Options”链接&#xff0c;如下图所示。单击“选项Options”…

Redis 命令全解析之 List类型

文章目录 命令RedisTemplate API使用场景 Redis 的 List 是一种有序、可重复、可变动的数据结构&#xff0c;它基于双向链表实现。在Redis中&#xff0c;List可以存储多个相同或不同类型的元素&#xff0c;每个元素在List中都有一个对应的索引位置。这使得List可以用来实现队列…

Java中线程安全的集合类

在先前的文章中我们已经讲过了原子类(线程安全的基本类型&#xff0c;基于CAS实现)&#xff0c;详见常见锁策略&#xff0c;synchronized内部原理以及CAS-CSDN博客 &#xff0c;我们在来讲一下集合类&#xff0c;在原来的集合类&#xff0c;大多数是线程不安全的&#xff0c;虽…

ABAP - SALV教程11 红黄绿灯

SALV通过某列设置成异常列&#xff0c;SALV就会根据某列的值自动映射成红黄绿灯注意事项 该列的类型为CHAR1,即是结构的字段类型为CHAR1该字段的值赋值为 (space,1,2,3) space&#xff1a;灰灯、1&#xff1a;红灯、2&#xff1a;黄灯、3&#xff1a;绿灯 案例代码 CLASS lcl…

一份简单的前端开发指南

文章目录 一、HTML1、表格2、常见标签3、行内、块级4、行内块级元素 二、CSS1、三种样式2、链接样式3、浮动4、清除浮动5、伪类&#xff0c;伪元素6、position7、后代选择器8、弹性布局 三、JavaScripts1、null和undefined的区别2、var let const3、原生数据类型4、双等和三等5…

Qt 简约美观的加载动画 文本风格 第八季

今天和大家分享一个文本风格的加载动画, 有两类,其中一个可以设置文本内容和文本颜色,演示了两份. 共三个动画, 效果如下: 一共三个文件,可以直接编译 , 如果对您有所帮助的话 , 不要忘了点赞呢. //main.cpp #include "LoadingAnimWidget.h" #include <QApplic…

Github 2024-03-03 开源项目日报Top9

根据Github Trendings的统计&#xff0c;今日(2024-03-03统计)共有9个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量非开发语言项目4Rust项目1C项目1Jupyter Notebook项目1Python项目1Shell项目1 任天堂Switch模拟器yuzu&#x…

13-微服务初探-自研微服务框架

微服务初探 1. 架构变迁之路 1.1 单体架构 互联网早期&#xff0c;一般的网站应用流量较小&#xff0c;只需要一个应用&#xff0c;将所有的功能代码都部署在一起就可以&#xff0c;这样可以减少开发&#xff0c;部署和维护的成本。 比如说一个电商系统&#xff0c;里面包含…

【每日刷题】数组-LC56、LC238、随想录1、LC560

1. LC56 合并区间 题目链接 Arrays.sort先让intervals里的子数组按照子数组的第一个数字值从小到大排列。开一个新数组&#xff0c;newInterval&#xff0c;存放合并好的子数组让intervals的当前子数组i的第一个数字与newInterval的当前子数组index的最后一个数字比较大小&am…

2024 年适用于电脑的十大录制屏幕软件

录制屏幕软件的设计和开发旨在让您的工作流程更轻松、更高效。这些漂亮的工具有助于为教育目的捕获图像快照或记录屏幕以与客户共享模型。无论您寻找桌面屏幕录像机的原因是什么&#xff0c;这里都有最好的付费和免费实用程序。该类别中我们最喜欢的一些选择是 奇客录屏助手和 …

docker 转为docker-compose(composerize 命令)

可以使用Composerize将Docker命令转换为Docker Compose文件。 例如&#xff1a;将docker run命令转换为Docker Compose格式&#xff0c;只需用Composerize运行它&#xff0c;如下所示&#xff1a; composerize docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/…

IDEA的安装教程

1、下载软件安装包 官网下载&#xff1a;https://www.jetbrains.com/idea/ 2、开始安装IDEA软件 解压安装包&#xff0c;找到对应的idea可执行文件&#xff0c;右键选择以管理员身份运行&#xff0c;执行安装操作 3、运行之后&#xff0c;点击NEXT&#xff0c;进入下一步 4、…

美团分布式 ID 框架 Leaf 介绍和使用

一、Leaf 在当今日益数字化的世界里&#xff0c;软件系统的开发已经成为了几乎所有行业的核心。然而&#xff0c;随着应用程序的规模不断扩大&#xff0c;以及对性能和可扩展性的需求不断增加&#xff0c;传统的软件架构和设计模式也在不断地面临挑战。其中一个主要挑战就是如…

凌特杯,第二届,数字音频传输。simulink matlab

终于比赛进入了尾声&#xff0c;最为指导老师也是非常的激动。接下来进入了论文写作阶段和视频拍摄阶段。 第二届凌特杯规定的硬件是ADI的Pluto&#xff0c;成本在2k以内&#xff0c;能支持MATLAB&#xff0c;它能够流畅的实时播放接收到的音乐数据&#xff0c;并把数据保存成…

图论例题解析

1.图论基础概念 概念 &#xff08;注意连通非连通情况&#xff0c;1节点&#xff09; 无向图&#xff1a; 度是边的两倍&#xff08;没有入度和出度的概念&#xff09; 1.完全图&#xff1a; 假设一个图有n个节点&#xff0c;那么任意两个节点都有边则为完全图 2.连通图&…

Mysql列子查询

目录 列子查询数据准备 列子查询 子查询返回的结果是一列(可以是多行)&#xff0c;这种子查询称为列子查询。 常用的操作符&#xff1a; 操作符描述IN在指定的集合范围之内&#xff0c;多选一NOT IN不在指定的集合范围之内 案例&#xff1a;查询"教研部"和"…