设计模式之访问者模式

访问者模式

行为型模式

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

介绍

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

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

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

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

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

具体实现

设计模式之访问者模式_第1张图片

将观众分为男人和女人,对歌手进行测评,当看完某个歌手表演后,得到他们不同的评价。

第一步:创建抽象Person

public abstract class Person {

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

}

第二步:具体实现男人和女人类

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

    @Override
    public void accept(Action action) {
        action.getWomanResult(this);
    }
}
public class Man extends Person {

    @Override
    public void accept(Action action) {
        action.getManResult(this);
    }
}

第三步:创建抽象的行为

public abstract class Action {

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

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

}

第四步:创建具体行为的实现

public class Success extends Action{


    @Override
    public void getManResult(Man man) {
        System.out.println("男人给的评价是:成功");
    }

    @Override
    public void getWomanResult(Woman woman) {
        System.out.println("女人给的评价是:成功");
    }
}
public class Fail extends Action {

    @Override
    public void getManResult(Man man) {
        System.out.println("男人给的评价是:失败");
    }

    @Override
    public void getWomanResult(Woman woman) {
        System.out.println("女人给的评价是:失败");
    }
}

第五步:创建对象结构类

public class ObjectStructure {

    //维护了一个集合
    private List 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 person : persons) {
            person.accept(action);
        }
    }

}

第六步:创建测试类

public class Client {

    public static void main(String[] args) {
        //创建ObjectStructure
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.attach(new Man());
        objectStructure.attach(new Man());
        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);
    }
}

运行如下:

男人给的评价是:成功
男人给的评价是:成功
男人给的评价是:成功
女人给的评价是:成功
====================
男人给的评价是:失败
男人给的评价是:失败
男人给的评价是:失败
女人给的评价是:失败

优点:

    1、如果想增加一种评价,只需要继承Action即可,无需改动别的类

     2、符合单一职责原则。

    3、优秀的扩展性。

    4、灵活性。

缺点:

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

    2、具体元素变更比较困难。

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

你可能感兴趣的:(java,设计模式)