设计模式—访问者模式

简介

访问者模式是一种将数据操作与数据结构分离的设计模式,基本思想是软件系统中拥有一个由许多对象构成的、比较稳定的对象结构,这些对象都拥有一个accept方法用来接受访问者对象的访问。访问者是一个接口,拥有一个visit方法,这个方法对访问到的对象结构中不同类型的元素做出不同的处理。

定义

封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义这些元素的新的操作。

使用场景

对象结构稳定,但经常需要在此对象上定义新的操作

需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免这些操作污这些对象的类,也不希望在怎加新类操作时修改这些类

关键点

一个抽象访问者,接口或抽象类,定义了对每一个元素访问的行为,它的参数就是可以访问的元素,它的方法个数理论上与元素个数是一样的,因此,访问者模式要求元素的类族要稳定,如果经常添加、移除元素类,则说明不适合使用访问者模式

具体的访问者,需要给出对每一个元素类访问时产生的具体行为

一个抽象元素类,定义一个接受访问者的方法,其意义是指每个元素都可以被访问者访问

多个具体的元素类。提供接受访问方法的具体实现,通常是使用访问者提供的访问该元素类的方法

一个上下文,定义类族稳定的对象结构,是一个抽象表述,内部管理元素集合,并且可以迭代这些元素提供访问者访问

实现

以年底绩效考核为例:

/**
 * 抽象元素
 */
public abstract class AbsStaff {

    public String name;
    public int kpi;

    public AbsStaff(String name) {
        this.name = name;
        this.kpi = new Random().nextInt(10);
    }

    /**
     * 定义一个抽象访问——子类具体实现其具体功能
     */
    public abstract void accept(AbsVisitor visitor);
}
/**
 * 抽象访问者结构
 */
public interface AbsVisitor {

    void visit(Coder coder);

    void visit(Manager manager);
}
/**
 * 程序员_被访问者
 */
public class Coder extends AbsStaff {

    public Coder(String name) {
        super(name);
    }

    @Override
    public void accept(AbsVisitor visitor) {
        visitor.visit(this);
    }
}
/**
 * 经理_被访问者
 */
public class Manager extends AbsStaff {

    public Manager(String name) {
        super(name);
    }

    @Override
    public void accept(AbsVisitor visitor) {
        visitor.visit(this);
    }
}
/**
 * 具体的访问者_对不同元素进行具体访问
 */
public class CEOVisitor implements AbsVisitor {

    @Override
    public void visit(Coder coder) {
        Log.i(getClass().getSimpleName(), "CEO 对程序员的考核");
    }

    @Override
    public void visit(Manager manager) {
        Log.i(getClass().getSimpleName(), "CEO 对经理的考核");
    }
}
/**
 * 具体的访问者_对不同元素进行具体访问
 */
public class CTOVisitor implements AbsVisitor {

    @Override
    public void visit(Coder coder) {
        Log.i(getClass().getSimpleName(), "CTO 对程序员的考核");
    }

    @Override
    public void visit(Manager manager) {
        Log.i(getClass().getSimpleName(), "CTO 对经理的考核");
    }

}
/**
 * 访问者上下文_对访问者统一访问
 */
public class StaffContext {

    public List<AbsStaff> staffList = new ArrayList<>();

    public StaffContext() {
        staffList.add(new Coder("LBJFAN_1"));
        staffList.add(new Coder("LBJFAN_2"));
        staffList.add(new Manager("LBJFAN_1"));
        staffList.add(new Manager("LBJFAN_2"));
    }

    /**
     * 使用一种类型的访问者对所有的被访问者进行访问
     */
    public void visit(AbsVisitor absVisitor) {
        for (AbsStaff staff : staffList) {
            staff.accept(absVisitor);
        }
    }
}

小结

1.各角色职责分离,符合单一职责原则

2.具有很强的扩展性

3.使得数据结构和数据操作解耦,因此操作集合可以独立变化

缺点

1.具体元素对访问者公布细节,违反了迪米特原则

2.具体元素变更时导致修改成本过大

3.违法了依赖倒置原则,依赖了具体类,没有依赖抽象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值