8.8访问者模式
8.8.1概念
访问者模式是一种将操作逻辑与对象结构分离的方法,使得操作可以独立变化,操作逻辑被封装在独立的访问者类中,并在被访问的元素类中提供接受访问者的方法,而不是直接嵌入到数据结构中的对象中。
8.8.2场景
我们可以将一个购物商场中的商品类作为元素类,不同的销售人员可以作为访问者类。当销售人员需要对商品进行销售操作时,可以创建一个具体的访问者对象,然后通过商品类的接受访问者的方法将访问者对象传入。然后商品类再根据传入的访问者对象调用相应的访问者方法,从而实现对商品的不同销售策略,如打折、促销等。
8.8.3优势 / 劣势
- 操作逻辑更加独立:将操作逻辑从对象结构中分离出来,使得操作逻辑更加独立和可复用
- 提高代码的可维护性:将操作逻辑封装在独立的访问者类中,使得代码更加清晰易懂
- 不宜测试和维护:访问者模式涉及到多个类的交互,使得测试和维护变得更加困难
- 增加系统复杂性:引入了访问者类和被访问的元素类之间的依赖关系,增加了系统的复杂性
8.8.4访问者模式可分为
- 抽象访问者Visitor:声明了访问者可以访问哪些元素,以及如何访问它们的方法visit
- 具体访问者ConcreteVisitor:实现了抽象访问者定义的方法,不同的元素类型可能有不同的访问行为
- 抽象元素Element:定义了一个accept方法,用于接受访问者的访问
- 具体元素ConcreteElement:实现了accept方法,是访问者访问的目标
- 对象结构Object Structure:包含元素的集合,可以是一个列表、一个集合或其他数据结构,负责遍历元素,并调用元素的接受方法
8.8.5访问者模式
8.8.6实战
8.8.6.1题目描述
小明家有一些圆形和长方形面积的土地,请你帮他实现一个访问者模式,使得可以通过访问者计算每块土地的面积。
图形的面积计算规则如下:
- 圆形的面积计算公式为:3.14 * 半径 * 半径
- 矩形的面积计算公式为:长 * 宽
8.8.6.2输入描述
第一行是一个整数 n(1 <= n <= 1000),表示图形的数量。
接下来的 n 行,每行描述一个图形,格式为 “Circle r” 或 “Rectangle width height”,其中 r、width、height 是正整数。文章来源:https://www.toymoban.com/news/detail-818971.html
8.8.6.3输出描述
对于每个图形,输出一行,表示该图形的面积。文章来源地址https://www.toymoban.com/news/detail-818971.html
8.8.6.4代码
package com.technologystatck.designpattern.mode.visitor;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int nums = scanner.nextInt();
scanner.nextLine();
//创建数组来存储图形对象
Shape[] shapes = new Shape[nums];
//根据用户输入来创建不同类型的图形对象
for (int i = 0; i < nums; i++) {
String[] inputs = scanner.nextLine().split(" ");
if (inputs[0].equals("Circle")) {
int radius = Integer.parseInt(inputs[1]);
shapes[i] = new Circle(radius);
} else if (inputs[0].equals("Rectangle")) {
int width = Integer.parseInt(inputs[1]);
int height = Integer.parseInt(inputs[2]);
shapes[i] = new Rectangle(width, height);
} else {
System.out.println("Invalid input");
return;
}
}
//创建图形集合
Drawing drawing = new Drawing(shapes);
//创建面积计算访问者
ConcreteAreaCalc concreteAreaCalc = new ConcreteAreaCalc();
drawing.accept(concreteAreaCalc);
}
}
//访问者接口
interface Visitor {
//圆形的访问者方法
void visit(Circle circle);
//矩形的访问者方法
void visit(Rectangle rectangle);
}
//实现具体访问者,相当于计算圆形/矩形
class ConcreteAreaCalc implements Visitor {
@Override
public void visit(Circle circle) {
double area = 3.14 * Math.pow(circle.getRadius(), 2);
System.out.println(area);
}
@Override
public void visit(Rectangle rectangle) {
double area = rectangle.getHeight() * rectangle.getWidth();
System.out.println(area);
}
}
//定义元素接口
interface Shape {
void accept(Visitor visitor);
}
//实现圆形具体元素
class Circle implements Shape {
private int radius;
public Circle(int radius) {
this.radius = radius;
}
public int getRadius() {
return radius;
}
@Override
public void accept(Visitor visitor) {
//调用访问者的方法,访问当前对象,并将当前对象传递给访问者。
visitor.visit(this);
}
}
//实现矩形具体元素
class Rectangle implements Shape {
private int width;
private int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
//创造对象结构,用于让访问者访问它的元素
class Drawing {
private Shape[] shapes;
public Drawing(Shape[] shapes) {
this.shapes = shapes;
}
//循环遍历访问者接口
public void accept(Visitor visitor) {
for (Shape shape : shapes) {
shape.accept(visitor);
}
}
}
8.8.7总结
- 优点:操作逻辑与对象结构分离,以及增加新的操作无需修改原有的代码
- 总结:通过将操作逻辑与对象结构分离,使用抽象访问者用于声明访问者可以访问哪些元素、具体访问者实现了抽象访问者定义的方法,创建具体的访问对象、抽象元素用于接收访问者的访问、具体元素用于被访问者进行访问、对象结构用于存储和遍历元素的集合
- 场景:常用于对象结构比较稳定,但经常需要在此对象结构上定义新的操作
到了这里,关于笨蛋学设计模式行为型模式-访问者模式【21】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!