行业知识
【软考】设计模式之访问者模式
2026-11-07 16:49:52
来源:互联网转载
目录
- 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 index.php/tags-41973.html" >���进
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 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 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()); // 在这里执行自动结账的逻辑,比如扫描条形码或使用移动支付 } }
- 1.结账接口可以把购物车作为参数进行结账
- 1.实现accept操作,参数是一个访问者即收银台
- 1.假设现在要创建一个简单的超市销售系统,顾客将毛巾、饼干、酸奶等物品(Item)加入购物车(Shopping_Cart),在收银台(Checkout)人工(Manual)或自动(Auto)地将购物车中每个物品的价格汇总到总价格后结账。
- 1.实现accept操作,参数是一个访问者