设计模式之十四之访问者模式

访问者模式介绍

1) 访问者模式(Visitor Pattern),封装一些作用于某种数据结构的各元素的操作, 它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

2) 主要将数据结构与数据操作分离,解决 数据结构和操作耦合性问题

3) 访问者模式的基本工作原理是:在被访问的类里面加一个对外提供接待访问者 的接口

4) 访问者模式主要应用场景是:需要对一个对象结构中的对象进行很多不同操作 (这些操作彼此没有关联),同时需要避免让这些操作"污染"这些对象的类,可以 选用访问者模式解决

uml类图

 

 角色说明:

1) Visitor 是抽象访问者,为该对象结构中的ConcreteElement的每一个类声明一个visit操作

2) ConcreteVisitor :是一个具体的访问值 实现每个有Visitor 声明的操作,是每个操作实现的部分.

3) ObjectStructure 能枚举它的元素, 可以提供一个高层的接口,用来允许访问者访问元素

4) Element 定义一个accept 方法,接收一个访问者对象 5) ConcreteElement 为具体元素,实现了accept 方法

案列,实现男女观众对歌手投票

uml类图

 

 代码实现

package com.hy.visitor;

/**
 * @author hanyong
 * @date 2020/12/1 23:36
 */
public abstract class Action {

    //得到男性 的测评
    public abstract void getManResult(Man man);

    //得到女的 测评
    public abstract void getWomanResult(Woman woman);
}

package com.hy.visitor;

/**
 * @author hanyong
 * @date 2020/12/1 23:36
 */
public abstract class Person {

    //提供一个方法,让访问者可以访问
    public abstract void accept(Action action);
}

package com.hy.visitor;

/**
 * @author hanyong
 * @date 2020/12/1 23:37
 */
public class Man extends Person {

    @Override
    public void accept(Action action) {
        // TODO Auto-generated method stub
        action.getManResult(this);
    }

}

package com.hy.visitor;

/**
 * @author hanyong
 * @date 2020/12/1 23:37
 */
//说明
//1. 这里我们使用到了双分派, 即首先在客户端程序中,将具体状态作为参数传递Woman中(第一次分派)
//2. 然后Woman 类调用作为参数的 "具体方法" 中方法getWomanResult, 同时将自己(this)作为参数
//   传入,完成第二次的分派
public class Woman extends Person{

    @Override
    public void accept(Action action) {
        // TODO Auto-generated method stub
        action.getWomanResult(this);
    }

}

package com.hy.visitor;

/**
 * @author hanyong
 * @date 2020/12/1 23:38
 */
public class Success extends Action {

    @Override
    public void getManResult(Man man) {
        // TODO Auto-generated method stub
        System.out.println(" 男人给的评价该歌手很成功 !");
    }

    @Override
    public void getWomanResult(Woman woman) {
        // TODO Auto-generated method stub
        System.out.println(" 女人给的评价该歌手很成功 !");
    }

}

package com.hy.visitor;

/**
 * @author hanyong
 * @date 2020/12/1 23:38
 */
public class Fail extends Action {

    @Override
    public void getManResult(Man man) {
        // TODO Auto-generated method stub
        System.out.println(" 男人给的评价该歌手失败 !");
    }

    @Override
    public void getWomanResult(Woman woman) {
        // TODO Auto-generated method stub
        System.out.println(" 女人给的评价该歌手失败 !");
    }

}

package com.hy.visitor;

/**
 * @author hanyong
 * @date 2020/12/1 23:39
 */
public class Wait extends Action {

    @Override
    public void getManResult(Man man) {
        // TODO Auto-generated method stub
        System.out.println(" 男人给的评价是该歌手待定 ..");
    }

    @Override
    public void getWomanResult(Woman woman) {
        // TODO Auto-generated method stub
        System.out.println(" 女人给的评价是该歌手待定 ..");
    }

}

package com.hy.visitor;

import java.util.LinkedList;
import java.util.List;

/**
 * @author hanyong
 * @date 2020/12/1 23:38
 */
//数据结构,管理很多人(Man , Woman)
public class ObjectStructure {

    //维护了一个集合
    private List<Person> persons = new LinkedList<>();

    //增加到list
    public void attach(Person p) {
        persons.add(p);
    }
    //移除
    public void detach(Person p) {
        persons.remove(p);
    }

    //显示测评情况
    public void display(Action action) {
        for(Person p: persons) {
            p.accept(action);
        }
    }
}

package com.hy.visitor;

/**
 * @author hanyong
 * @date 2020/12/1 23:40
 */
public class Client {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //创建ObjectStructure
        ObjectStructure objectStructure = new ObjectStructure();

        objectStructure.attach(new Man());
        objectStructure.attach(new Woman());


        //成功
        Success success = new Success();
        objectStructure.display(success);

        System.out.println("===============");
        Fail fail = new Fail();
        objectStructure.display(fail);

        System.out.println("=======给的是待定的测评========");

        Wait wait = new Wait();
        objectStructure.display(wait);
    }

}

输出结果:

 

 访问者模式优缺点:

 优点

1) 访问者模式符合单一职责原则、让程序具有优秀的扩展性、灵活性非常高

2) 访问者模式可以对功能进行统一,可以做报表、UI、拦截器与过滤器,适用于数据 结构相对稳定的系统

 缺点

1) 具体元素对访问者公布细节,也就是说访问者关注了其他类的内部细节,这是迪米 特法则所不建议的, 这样造成了具体元素变更比较困难

2) 违背了依赖倒转原则。访问者依赖的是具体元素,而不是抽象元素

3) 因此,如果一个系统有比较稳定的数据结构,又有经常变化的功能需求,那么访问 者模式就是比较合适的.

 

posted @ 2020-12-01 23:44  yongzhewuwei  阅读(96)  评论(0编辑  收藏  举报