目录 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 具体元素
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 改进
// 结账接口
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()); // 在这里执行自动结账的逻辑,比如扫描条形码或使用移动支付 }
}