笨蛋学设计模式行为型模式-访问者模式【21】

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 是正整数。

8.8.6.3输出描述

对于每个图形,输出一行,表示该图形的面积。

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总结

  • 优点:操作逻辑与对象结构分离,以及增加新的操作无需修改原有的代码
  • 总结:通过将操作逻辑与对象结构分离,使用抽象访问者用于声明访问者可以访问哪些元素、具体访问者实现了抽象访问者定义的方法,创建具体的访问对象、抽象元素用于接收访问者的访问、具体元素用于被访问者进行访问、对象结构用于存储和遍历元素的集合
  • 场景:常用于对象结构比较稳定,但经常需要在此对象结构上定义新的操作
  • 24
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值