首页 > 其他分享 >访问者模式(十八)

访问者模式(十八)

时间:2023-06-17 21:07:42浏览次数:35  
标签:十八 元素 模式 public accept new void 访问者


相信自己,请一定要相信自己

上一章简单介绍了命令模式(十七), 如果没有看过, 请观看上一章

一. 访问者模式

引用 菜鸟教程里面访问者模式介绍: https://www.runoob.com/design-pattern/visitor-pattern.html

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。

通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。

根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作

一.一 介绍

意图: 主要将数据结构与数据操作分离。

主要解决: 稳定的数据结构和易变的操作耦合问题。

何时使用: 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。

如何解决: 在被访问的类里面加一个对外提供接待访问者的接口。

关键代码: 在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。

应用实例: 您在朋友家做客,您是访问者,朋友接受您的访问,您通过朋友的描述,然后对朋友的描述做出一个判断,这就是访问者模式。

优点: 1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。

缺点: 1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

使用场景: 1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

注意事项: 访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。



组成角色

具体

关系

抽象访问者(Visitor)角色

Action

一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素

具体访问者(ConcreteVisitor)角色

FailAction, SuccessAction

实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么

抽象元素(Element)角色

Person

声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数

具体元素(ConcreteElement)角色

Man WoMan

实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作

对象结构(Object Structure)角色

ObjectStructure

是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现

访问者模式(十八)_ide

二. 访问者实例

二. 一 抽象访问者 Action

public abstract class Action {

    public abstract void getManResult (Man man);

    public abstract void getWomanResult(WoMan woMan);
}

二.二 具体访问者实现

二.二.一 差

@Slf4j
public class FailAction extends Action{

    @Override
    public void getManResult(Man man) {
        log.info("男生{}评价差",man.getName());
    }

    @Override
    public void getWomanResult(WoMan woMan) {
        log.info("女生评价{}差",woMan.getName());
    }
}

二.二.二 优

@Slf4j
public class SuccessAction extends Action{

    @Override
    public void getManResult(Man man) {
        log.info("男生{}评价优秀",man.getName());
    }

    @Override
    public void getWomanResult(WoMan woMan) {
        log.info("女生评价{}优秀",woMan.getName());
    }
}

二.二.三 待评价

@Slf4j
public class WaitAction extends Action{

    @Override
    public void getManResult(Man man) {
        log.info("男生{} 待评价",man.getName());
    }

    @Override
    public void getWomanResult(WoMan woMan) {
        log.info("女生{}待评价",woMan.getName());
    }
}

二.三 抽象元素 Person

@EqualsAndHashCode(of = {"name"})
public abstract class Person {
    private String name;

    public abstract  void accept(Action action);

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

二.四 具体元素

二.四.一 男人

public class Man extends Person{
    public Man (String name) {
        super.setName(name);
    }
    @Override
    public void accept(Action action) {
        action.getManResult(this);
    }
}

二.四.二 女人

public class WoMan extends Person{
    public WoMan (String name) {
       super.setName(name);
    }
    @Override
    public void accept(Action action) {
        action.getWomanResult(this);
    }
}

二.五 对象结构 ObjectStructure

public class ObjectStructure {

    private List<Person> personList = new ArrayList<>();

    public void accept( Person person) {
        personList.add(person);
    }

    public void remove(Person person) {
        personList.remove(person);
    }

    public void display (Action action) {
        for (Person person : personList) {
            person.accept(action);
        }
    }
}

二.六 测试

@Test
    public void oneTest() {
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.accept(new Man("张三"));
        // 是成功的
        objectStructure.display(new SuccessAction());

        objectStructure.remove(new Man("张三"));
        objectStructure.accept(new Man("李四"));

        objectStructure.display(new FailAction());

        objectStructure.remove(new Man("李四"));
        objectStructure.accept(new WoMan("王二"));
        objectStructure.accept(new WoMan("麻子"));

        objectStructure.display(new WaitAction());

    }

访问者模式(十八)_ide_02

优点:

  1. 访问者模式符合单一职责原则、让程序具有优秀的扩展性、灵活性非常高
  2. 访问者模式可以对功能进行统一,可以做报表、UI、拦截器与过滤器,适用于数据结构相对稳定的系统

缺点:

  1. 具体元素对访问者公布细节,也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的, 这样造 成了具体元素变更比较困难
  2. 违背了依赖倒转原则。访问者依赖的是具体元素,而不是抽象元素
  3. 因此,如果一个系统有比较稳定的数据结构,又有经常变化的功能需求,那么访问者模式就是比较合适的.



标签:十八,元素,模式,public,accept,new,void,访问者
From: https://blog.51cto.com/yueshushu/6506183

相关文章

  • 单例模式(三)
    过气的,终究是过气了上一章简单介绍了UML类图(二),如果没有看过,请观看上一章一.单例模式所谓的单例设计模式,就是采用一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)一.一单例模式介绍引用菜鸟教程里面的......
  • 抽象工厂模式(六)
    过气的,终究是过气了上一章简单介绍了工厂方法模式(五),如果没有看过,请观看上一章一.抽象工厂模式引用菜鸟教程里面的单例模式介绍:https://www.runoob.com/design-pattern/abstract-factory-pattern.html抽象工厂模式(AbstractFactoryPattern)是围绕一个超级工厂创建其他工厂......
  • 工厂模式(四)
    过气的,终究是过气了上一章简单介绍了单例模式(三),如果没有看过,请观看上一章一.工厂模式引用菜鸟教程里面的单例模式介绍:https://www.runoob.com/design-pattern/factory-pattern.html工厂模式(FactoryPattern)是Java中最常用的设计模式之一。这种类型的设计模式属于创建型......
  • 工厂方法模式(五)
    过气的,终究是过气了上一章简单介绍了工厂模式(四),如果没有看过,请观看上一章一.工厂方法模式工厂方法模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一......
  • 设计模式的原则(一)
    相信自己,无论自己到了什么局面,请一定要继续相信自己。新的世界开始了,接下来,老蝴蝶带领大家学习一下设计模式。我们先了解一下设计原则一.设计模式一.一设计原则设计模式常用的七大原则:单一职责原则接口隔离原则依赖倒转(倒置)原则里氏替换原则开闭原则迪米特法则合成复用原则一.......
  • 策略模式(二十五)
    相信自己,请一定要相信自己上一章简单介绍了状态模式(二十四),如果没有看过,请观看上一章一.策略模式引用菜鸟教程里面策略模式介绍:https://www.runoob.com/design-pattern/strategy-pattern.html在策略模式(StrategyPattern)中,一个类的行为或其算法可以在运行时更改。这种类......
  • PHP开发:代码风格、重构和设计模式的实践
    一、代码风格和规范:采用一致的代码风格和规范有助于提高代码的可读性和可维护性。我们将介绍一些常见的PHP代码风格指南,如PSR-12(PHPStandardRecommendation),以及一些静态代码分析工具,如PHPCodeSniffer,可以帮助您自动检测代码规范问题。示例代码风格(使用PSR-12):<?phpnamespaceV......
  • 迭代器模式(Iterator Pattern)
    迭代器模式(IteratorPattern)一、定义提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示。二、优缺点优点: 1、它支持以不同的方式遍历一个聚合对象。2、迭代器简化了聚合类。3、在同一个聚合上可以有多个遍历。4、在迭代器模式中,增加新的聚合类和......
  • 设计模式:适配器模式(论如何把鼠头适配成鸭脖)
    适配器模式(AdapterPattern)有时候也称包装样式或者包装,是一种结构型设计模式,它可以将一个类的接口转换成客户端所期望的另一个接口。适配器模式可以让原本由于接口不兼容而不能一起工作的那些类可以一起工作。适配器模式有三种类型:类适配器模式、对象适配器模式和接口适配器模式......
  • Go设计模式实战--用状态模式实现系统工作流和状态机
    大家好,这里是每周都在陪你进步的网管~!本节我们讲一个行为型的设计模式--状态模式,并通过Golang示例进行实战演示。状态模式(StatePattern)也叫作状态机模式(StateMachinePattern)状态模式允许对象的内部状态发生改变时,改变它的行为,就好像对象看起来修改了它实例化的类,状态模式是一种......