白话-23种设计模式21-访客者模式

举报
object 发表于 2022/07/13 22:12:16 2022/07/13
2.1k+ 0 0
【摘要】 一、白话  访客者模式就是,访客和被访者以及组合角色三者之间的一个封装。访客者需要有访问接口,被访客者需要有被访问接口,组合角色需要有所有访客访问被访者的组合。还是比较绕,我看过最形象的比喻就是:人喂动物。人就是访客,动物是被访者。人可以有丈夫,妻子,动物可以有猫、狗。这里就能形成四种组合,这四种方式封装起来就是组合角色(结构角色)。这样就完成了访客者模式,丈夫去喂动物或者妻子喂动物的时候,...

一、白话

  访客者模式就是,访客和被访者以及组合角色三者之间的一个封装。访客者需要有访问接口,被访客者需要有被访问接口,组合角色需要有所有访客访问被访者的组合。还是比较绕,我看过最形象的比喻就是:人喂动物。人就是访客,动物是被访者。人可以有丈夫,妻子,动物可以有猫、狗。这里就能形成四种组合,这四种方式封装起来就是组合角色(结构角色)。这样就完成了访客者模式,丈夫去喂动物或者妻子喂动物的时候,就能有不同的表现。而不用去改内部结构。

二、定义

  元素的执行算法可以随着访问者改变而改变。

  • Visitor是抽象访问者:为该对象结构中的ConcreteElement的每一个类声明一个visit操作
  • ConcreteVisitor具体访问者:是一个具体的访问值实现每个有Visitor声明的操作,是每个操作实现的部分
  • ObjectStructure结构对象:能枚举它的元素,可以提供一个高层的接口,用来允许访问者访问元素
  • Element抽象元素:定义一个accept 方法,接收一个访问者对象
  • ConcreteElement具体元素:实现了accept方法

三、示例

// 抽象元素-定义被访问接口
public interface Animal {
    public void accept(Person person);
}
// 具体元素-实现被访问细节
public class Cat implements Animal {
    @Override
    public void accept(Person person) {
        // 重点:具体细节交给了访问者,被访问者接受了访客访问,把自己交给了访客,访客来访问被访者
        person.visit(this);
    }
}
// 具体元素-实现被访问细节
public class Dog implements Animal {
    @Override
    public void accept(Person person) {
        // 重点:具体细节交给了访问者,被访问者接受了访客访问,把自己交给了访客,访客来访问被访者
        person.visit(this);
    }
}
// 抽象访问者-定义访问接口
public interface Person {
    public void visit(Animal animal);
}
// 具体访问者-实现访问细节
public class Husband implements Person {
    // 这里就是定义细节,实现不同访客访问出现不同的细节
    @Override
    public void visit(Animal animal) {
        System.out.println("丈夫,总是会给很多食物");
        if (animal instanceof Cat) {
            System.out.println("猫咪很开心,喵喵");
        } else {
            System.out.println("小狗很开心,旺旺");
        }
    }
// 具体访问者-实现访问细节
public class Wife implements Person {
    // 这里就是定义细节,实现不同访客访问出现不同的细节
    @Override
    public void visit(Animal animal) {
        System.out.println("妻子,总是会给很少食物");
        if (animal instanceof Cat) {
            System.out.println("猫咪很难过,呜呜");
        } else {
            System.out.println("小狗很难过,呜呜");
        }
    }
}
// 结构对象-拥有所有元素,实现所有元素被访问的场景
public class Home {
    // 定义所有对象, 不一定非得是集合,多个单独存在的对象也是可以的
    private List<Animal> animals = new ArrayList<>();

    // 结构对象-定义访问者访问被访者 接口
    public void action(Person person) {
        for (Animal animal : animals) {
            animal.accept(person);
        }
    }

    // 新增元素
    public void add(Animal animal) {
        animals.add(animal);
    }
}
public class VisitorApplication {
    // 客户端调用
    public static void main(String[] args) {
        // 新增结构对象
        Home home = new Home();
        // 添加元素
        home.add(new Dog());
        home.add(new Cat());

        // 定义访问者
        Person husband = new Husband();
        Person wife = new Wife();

        // 开启访问
        home.action(husband);
        home.action(wife);
    }
}

  输出示例:

丈夫,总是会给很多食物
小狗很开心,旺旺
丈夫,总是会给很多食物
猫咪很开心,喵喵
妻子,总是会给很少食物
小狗很难过,呜呜
妻子,总是会给很少食物
猫咪很难过,呜呜

四、总结

  特点:1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。4、具体元素变更比较困难。 5、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。