设计模式之访问者模式笔记

说明

记录下学习设计模式-访问者模式的写法。JDK使用版本为1.8版本。

Iterator(访问者)

意图:表示一个作用于某对象结构中的各元素的操作。它允许在不改变各元素的类的前提下定义这些元素的新操作。
结构:
在这里插入图片描述

其中:

  • Visitor(访问者)为该对象结构中 ConcreteElement 的每一个类声明一个 Visit操作。该操作的名字和特征标识了发送 Visit 请求给该访问者的那个类,这使得访问者可以确定正被访问元素的具体的类。这样访问者就可以通过该元素的特定接口直接访问它。
  • ConcreteVisitor (具体访间者)实现每个有 Visitor 声明的操作,每个操作实现本算法的一部分,而该算法片段乃是对应于结构中对象的类。ConcreteVisitor 为该算法提供了上下文并存储它的局部状态。这一状态常常在遍历该结构的过程中累积结果。
  • Element(元素)定义以一个访间者为参数的 Accept 操作。
  • ConcreteElement (具体元素)实现以一个访问者为参数的Accept 操作。
  • ObjcctStructure (对象结构)能枚举它的元素,可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个组合或者一个集合,如一个列表或一个无序集合。

适用性:

  • 对象结构相对稳定,但其操作算法经常变化的程序。
  • 对象结构中的对象需要提供多种不同且不相关的操作,而且要避免让这些操作的变化影响对象的结构。

目录

在这里插入图片描述

访问者模式示例类图

在这里插入图片描述在这里插入图片描述
以该UML类图实现访问者模式示例。

抽象访问者角色类

package com.example.deesign_patterns.visitor;

//抽象访问者角色类
public interface Person {
    
    

    //喂食宠物猫
    void feed(Cat cat);

    //喂食宠物狗
    void feed(Dog dog);
}

抽象元素角色类

package com.example.deesign_patterns.visitor;

//抽象元素角色类
public interface Animal {
    
    

    //接受访问者访问的功能
    void accept(Person person);
}

宠物猫类

package com.example.deesign_patterns.visitor;

//宠物猫类,具体元素角色类
public class Cat implements Animal{
    
    

    @Override
    public void accept(Person person) {
    
    
        person.feed(this);//访问者给宠物猫喂食
        System.out.println("好好吃,喵喵喵。。。");
    }
}

宠物狗类

package com.example.deesign_patterns.visitor;

//宠物狗类,具体元素角色类
public class Dog implements Animal{
    
    

    @Override
    public void accept(Person person) {
    
    
        person.feed(this);//访问者给宠物狗喂食
        System.out.println("好好吃,汪汪汪。。。");
    }
}

自己类

package com.example.deesign_patterns.visitor;

//自己类,具体访问者角色类
public class Owner implements Person{
    
    

    @Override
    public void feed(Cat cat) {
    
    
        System.out.println("主人喂食猫");
    }

    @Override
    public void feed(Dog dog) {
    
    
        System.out.println("主人喂食狗");
    }
}

其他人类

package com.example.deesign_patterns.visitor;

//其他人类,具体访问者角色类
public class Someone implements Person{
    
    

    @Override
    public void feed(Cat cat) {
    
    
        System.out.println("其他人喂食猫");
    }

    @Override
    public void feed(Dog dog) {
    
    
        System.out.println("其他人喂食狗");
    }
}

家类

package com.example.deesign_patterns.visitor;

import java.util.ArrayList;
import java.util.List;

//家类,对象结构类
public class Home {
    
    

    //声明一个集合对象,用来存储元素对象
    private List<Animal> nodeList=new ArrayList<Animal>();

    //添加元素功能
    public void add(Animal animal){
    
    
        nodeList.add(animal);
    }

    public void action(Person person){
    
    
        //遍历集合,获取每一个元素,让访问者访问每一个元素
        for(Animal animal:nodeList){
    
    
            animal.accept(person);
        }
    }
}

测试类

package com.example.deesign_patterns.visitor;

//测试类
public class Client {
    
    

    public static void main(String[] args) {
    
    
        //创建Home对象
        Home home=new Home();
        //添加元素到Home对象中
        home.add(new Cat());
        home.add(new Dog());
        //创建主人对象
        Owner owner=new Owner();
        //让主人喂食所有宠物
        home.action(owner);
        //创建其他人对象
        Someone someone=new Someone();
        //让其他人喂食所有宠物
        home.action(someone);
    }
}

在这里插入图片描述

好处:

  • 扩展性好。在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
  • 复用性好。通过访问者来定义整个对象结构通用的功能,从而提高复用程度。
  • 分离无关行为。通过访问者来分离无关的行为,把相关的行为封装在一起,构成一个访问者,这样每一个访问者的功能都比较单一。

缺点:

  • 对象结构变化很困难。在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”。
  • 违反了依赖倒置原则。访问者模式依赖了具体类,而没有依赖抽象类。

猜你喜欢

转载自blog.csdn.net/weixin_48040732/article/details/131365578