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

目录

        • 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{@Overridepublic void feed(Cat cat) {System.out.println("主人喂食猫");}@Overridepublic void feed(Dog dog) {System.out.println("主人喂食狗");}
}
package com.learning.visitor;/*** 其他人*/
public class Someone implements Person{@Overridepublic void feed(Dog dog) {System.out.println("其他人喂食狗");}@Overridepublic 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{@Overridepublic void accept(Person person) {person.feed(this);System.out.println("汪汪汪");}
}
package com.learning.visitor;/*** 猫*/
public class Cat implements Animal{@Overridepublic 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 {@Overridepublic void checkout(Towel towel) {System.out.println("人工结账毛巾");}@Overridepublic void checkout(Cookie cookie) {System.out.println("人工结账饼干");}@Overridepublic void checkout(Yogurt yogurt) {System.out.println("人工结账酸奶");}
}
package com.learning.visitor.shop;// 自动结账类
public class AutoCheckout implements Checkout {@Overridepublic void checkout(Towel towel) {System.out.println("自动结账毛巾");}@Overridepublic void checkout(Cookie cookie) {System.out.println("自动结账饼干");}@Overridepublic 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{@Overridepublic void accept(Checkout checkout) {checkout.checkout(this);}@Overridepublic double getPrice() {return 5.99;}@Overridepublic String getName() {return "毛巾";}
}
package com.learning.visitor.shop;/*** 饼干*/
public class Cookie implements Item {@Overridepublic void accept(Checkout checkout) {checkout.checkout(this);}@Overridepublic double getPrice() {return 2.99;}@Overridepublic String getName() {return "饼干";}
}
package com.learning.visitor.shop;/*** 酸奶*/
public class Yogurt implements Item {@Overridepublic void accept(Checkout checkout) {checkout.checkout(this);}@Overridepublic double getPrice() {return 1.99;}@Overridepublic 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());  // 在这里执行自动结账的逻辑,比如扫描条形码或使用移动支付  }  
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3.1日学习打卡----初学FastDFS(一)

3.1日学习打卡 目录: 3.1日学习打卡一. 为什么要使用分布式文件系统二. FastDFS简介核心概念上传机制下载机制FastDFS环境搭建_LinuxFastDFS指令 一. 为什么要使用分布式文件系统 单机时代 初创时期由于时间紧迫&#xff0c;在各种资源有限的情况下&#xff0c;通常就直接在项…

深度学习的onnx模型插入新节点构建新模型

import numpy as np import onnx import onnxruntime import onnxruntime.backend as backendmodel onnx.load(test.onnx) node model.graph.node graph model.graph# 1.2搜索目标节点 # for i in range(len(node)): # if node[i].op_type Conv: # node_rise …

JAVA面向对象高级部分—多态

面向对象高级部分—多态 认识多态 对象多态&#xff0c;对象既可以指向老师对象&#xff0c;也可以指向学生对象。 注意事项&#xff1a; 成员变量不谈多态&#xff0c;编译看左边&#xff0c;运行看左边 成员变量编译的是父类People&#xff0c;所以编译的是左边的People&a…

STM32------分析GPIO寄存器

一、初始LED原理图 共阴极led LED发光二极管&#xff0c;需要有电流通过才能点亮&#xff0c;当有电压差就会产生电流 二极管两端的电压差超过2.7v就会有电流通过 电阻的作用 由于公式IV/R 不加电阻容易造成瞬间电流无穷大 发光二极管工作电流为10-20MA 3.3v / 1kΩ 3.…

【风格迁移】URST:解决超高分辨率图像的风格迁移问题

URST&#xff1a;解决超高分辨率图像的风格迁移问题 提出背景URST框架的整体架构 提出背景 论文&#xff1a;https://arxiv.org/pdf/2103.11784.pdf 代码&#xff1a;https://github.com/czczup/URST?v1 有一张高分辨率的风景照片&#xff0c;分辨率为1000010000像素&#…

枚举类、泛型、API

枚举类 枚举类可以实现单例设计模式。 枚举的常见应用场景&#xff1a;用来表示一组信息&#xff0c;然后作为参数进行传输。 泛型 API

Benchmark学习笔记

小记一篇Benchmark的学习笔记 1.什么是benchmark 在维基百科中&#xff0c;是这样子讲的 “As computer architecture advanced, it became more difficult to compare the performance of various computer systems simply by looking at their specifications.Therefore, te…

Onlyfans怎么绑定虚拟卡订阅,视频图文教学!!!

前言 onlyfans软件是一个创立于2016年的订阅式社交媒体平台&#xff0c;创作者可以在自己的账号发布原创的照片或视频&#xff0c;并需要注意的是&#xff0c;网络上可能存在非法或不道德的应用将其设置成付费模式&#xff0c;若用户想查看则需要每月交费订阅。 图文视频教学&a…

steam++加速问题:出现显示443端口被 vmware-hostd(9860)占用的错误。

目录 前言&#xff1a; 正文&#xff1a; 前言&#xff1a; 使用Steam对GitHub进行加速处理时&#xff0c;建议使用2.8.6版本。 下载地址如下&#xff1a;Release 2.8.6 BeyondDimension/SteamTools GitHub 下载时注意自己的系统位数 正文&#xff1a; 使用GitHub时会使…

RocketMQ学习笔记一

课程来源&#xff1a;002-MQ简介_哔哩哔哩_bilibili &#xff08;尚硅谷老雷&#xff0c;时长19h&#xff09; 第1章 RocketMQ概述 1. MQ是什么&#xff1f; 2. MQ用途有哪些&#xff1f; 限流削峰&#xff1b;异步解耦&#xff1b;数据收集。 3. 常见MQ产品有哪些&对比…

如何根据PalWorldSettings.ini重新生成定制的WorldOption.sav文件?

这个过程涉及到将PalWorldSettings.ini 文件中的设置与WorldOption.sav 文件进行匹配和替换。具体的操作步骤可能包括检查PalWorldSettings.ini 文件中的设置是否与WorldOption.sav 文件中的设置相匹配&#xff0c;然后根据这些设置重新生成或修改WorldOption.sav 文件&#xf…

还在用Jenkins?快来试试这款简而轻的自动部署软件!

最近发现了一个比 Jenkins 使用更简单的项目构建和部署工具&#xff0c;完全可以满足个人以及一些小企业的需求&#xff0c;分享一下。 Jpom 是一款 Java 开发的简单轻量的低侵入式在线构建、自动部署、日常运维、项目监控软件。 日常开发中&#xff0c;Jpom 可以解决下面这些…