《设计模式》16.访问者模式(行为型)

把数据结构和作用于数据结构上的操作之间的耦合解脱开,把处理从数据结构中分离出来。适用于有比较稳定的数据结构,又有比较易于变化的算法的场景。
优点:增加新的操作很容易,增加新的操作就意味着增加一个新的访问者,访问者模式将相关行为集中到一个访问者对象中。
缺点:增加新的数据结构比较困难,破坏了封装,违反了依赖倒置原则。

角色

抽象访问者(Visitor):为每个具体元素类声明一个(参数类型为具体元素)访问接口,接口数量理论上与具体元素个数相同,访问者模式要求元素的类族要稳定,如果经常添加、移除元素类,必然会导致频繁地修改 Visitor 接口,这种情况不适合使用访问者模式
具体访问者(ConcreteVisitor):实现抽象访问者角色中声明的各个接口
抽象元素(Element):声明一个接受访问者的操作接口(accept)
具体元素(ConcreteElement):实现抽象元素声明的接口(如:visitor.visit(this))
对象结构(ObjectStructure):元素容器(集合),提供一个接口,在接口中遍历各元素供访问者调用

抽象访问者 Visitor

public interface Visitor {
    void visit(ConcreteElementA e);
    void visit(ConcreteElementB e);
    void visit(ConcreteElementC e);
}

具体访问者 ConcreteVisitorA / ConcreteVisitorB

public class ConcreteVisitorA implements Visitor {
    @Override
    public void visit(ConcreteElementA e) {
        System.out.println(String.format("%s visit %s", getClass().getSimpleName(), e.getClass().getSimpleName()));
    }

    @Override
    public void visit(ConcreteElementB e) {
        System.out.println(String.format("%s visit %s", getClass().getSimpleName(), e.getClass().getSimpleName()));
    }

    @Override
    public void visit(ConcreteElementC e) {
        System.out.println(String.format("%s visit %s", getClass().getSimpleName(), e.getClass().getSimpleName()));
    }
}

public class ConcreteVisitorB implements Visitor {
    @Override
    public void visit(ConcreteElementA e) {
        System.out.println(String.format("%s visit %s", getClass().getSimpleName(), e.getClass().getSimpleName()));
    }

    @Override
    public void visit(ConcreteElementB e) {
        System.out.println(String.format("%s visit %s", getClass().getSimpleName(), e.getClass().getSimpleName()));
    }

    @Override
    public void visit(ConcreteElementC e) {
        System.out.println(String.format("%s visit %s", getClass().getSimpleName(), e.getClass().getSimpleName()));
    }
}

抽象元素 Element

public interface Element {
    void accept(Visitor v);
}

具体元素 ConcreteElementA / ConcreteElementB / ConcreteElementC

public class ConcreteElementA implements Element {
    @Override
    public void accept(Visitor v) {
        v.visit(this);
    }

    public void operateA() {
        System.out.println(String.format("operate %s", getClass().getSimpleName()));
    }
}

public class ConcreteElementB implements Element {
    @Override
    public void accept(Visitor v) {
        v.visit(this);
    }

    public void operateB() {
        System.out.println(String.format("operate %s", getClass().getSimpleName()));
    }
}

public class ConcreteElementC implements Element {
    @Override
    public void accept(Visitor v) {
        v.visit(this);
    }

    public void operateC() {
        System.out.println(String.format("operate %s", getClass().getSimpleName()));
    }
}

对象结构 ObjectStructure

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

public class ObjectStructure {
    private List<Element> elements = new ArrayList<>();

    public boolean add(Element e) {
        return elements.add(e);
    }

    public void accept(Visitor v) {
        for (Element e : elements) {
            e.accept(v);
        }
        System.out.println();
    }
}

测试类 VisitorPattern

public class VisitorPattern {
    public static void main(String args[]) {
        ObjectStructure structure = new ObjectStructure();
        structure.add(new ConcreteElementA());
        structure.add(new ConcreteElementB());
        structure.add(new ConcreteElementC());

        structure.accept(new ConcreteVisitorA());
        structure.accept(new ConcreteVisitorB());
    }
}
ConcreteVisitorA visit ConcreteElementA
ConcreteVisitorA visit ConcreteElementB
ConcreteVisitorA visit ConcreteElementC

ConcreteVisitorB visit ConcreteElementA
ConcreteVisitorB visit ConcreteElementB
ConcreteVisitorB visit ConcreteElementC

举例1:铁人三项

铁人三项包含:天然水域游泳、公路自行车、公路长跑 三个项目,项目固定作为元素;参赛运动员作为访问者

public interface Athlete {
    void conduct(NaturalWaterSwimming swimming);
    void conduct(RoadCycling cycling);
    void conduct(RoadRunning running);
}
public class MatthewHauser implements Athlete {
    @Override
    public void conduct(NaturalWaterSwimming swimming) {
        System.out.println("Matthew Hauser conduct natural water swimming");
    }

    @Override
    public void conduct(RoadCycling cycling) {
        System.out.println("Matthew Hauser conduct natural water swimming");
    }

    @Override
    public void conduct(RoadRunning running) {
        System.out.println("Matthew Hauser conduct road running");
    }
}

public class LauraLindemann implements Athlete {
    @Override
    public void conduct(NaturalWaterSwimming swimming) {
        System.out.println("Laura Lindemann conduct natural water swimming");
    }

    @Override
    public void conduct(RoadCycling cycling) {
        System.out.println("Laura Lindemann conduct natural water swimming");
    }

    @Override
    public void conduct(RoadRunning running) {
        System.out.println("Laura Lindemann conduct road running");
    }
}

public class ZhongMengYing implements Athlete {
    @Override
    public void conduct(NaturalWaterSwimming swimming) {
        System.out.println("Zhong Meng Ying conduct natural water swimming");
    }

    @Override
    public void conduct(RoadCycling cycling) {
        System.out.println("Zhong Meng Ying conduct natural water swimming");
    }

    @Override
    public void conduct(RoadRunning running) {
        System.out.println("Zhong Meng Ying conduct road running");
    }
}
public interface Event {
    void apply(Athlete a);
}
public class NaturalWaterSwimming implements Event {
    @Override
    public void apply(Athlete a) {
        a.conduct(this);
    }
}

public class RoadCycling implements Event {
    @Override
    public void apply(Athlete a) {
        a.conduct(this);
    }
}

public class RoadRunning implements Event {
    @Override
    public void apply(Athlete a) {
        a.conduct(this);
    }
}
import java.util.ArrayList;
import java.util.List;

public class Triathlon {
    private List<Event> events = new ArrayList<>();

    public void add(Event e) {
        events.add(e);
    }

    public void conduct(Athlete a) {
        for (Event e : events) {
            e.apply(a);
        }
        System.out.println();
    }
}
public class VisitorPattern {
    public static void main(String args[]) {
        Triathlon triathlon = new Triathlon();
        triathlon.add(new NaturalWaterSwimming());
        triathlon.add(new RoadCycling());
        triathlon.add(new RoadRunning());

        triathlon.conduct(new MatthewHauser());
        triathlon.conduct(new LauraLindemann());
        triathlon.conduct(new ZhongMengYing());
    }
}
Matthew Hauser conduct natural water swimming
Matthew Hauser conduct natural water swimming
Matthew Hauser conduct road running

Laura Lindemann conduct natural water swimming
Laura Lindemann conduct natural water swimming
Laura Lindemann conduct road running

Zhong Meng Ying conduct natural water swimming
Zhong Meng Ying conduct natural water swimming
Zhong Meng Ying conduct road running

举例2:Linux 文件权限

Linux文件具有三种权限:rwx 作为元素;用户(组)作为访问者

public abstract class User {
    private String name;
    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public abstract String getAbbr();

    public void grant(Read r) {
        System.out.println(String.format("grant %s (%s) \"%s\" permission", getName(), getAbbr(), r.getAbbr()));
    }

    public void grant(Write w) {
        System.out.println(String.format("grant %s (%s) \"%s\" permission", getName(), getAbbr(), w.getAbbr()));
    }

    public void grant(Execution x) {
        System.out.println(String.format("grant %s (%s) \"%s\" permission", getName(), getAbbr(), x.getAbbr()));
    }

    public void revoke(Read r) {
        System.out.println(String.format("revoke %s (%s)\"%s\" permission", getName(), getAbbr(), r.getAbbr()));
    }

    public void revoke(Write w) {
        System.out.println(String.format("revoke %s (%s) \"%s\" permission", getName(), getAbbr(), w.getAbbr()));
    }

    public void revoke(Execution x) {
        System.out.println(String.format("revoke %s (%s) \"%s\" permission", getName(), getAbbr(), x.getAbbr()));
    }
}
public class Owner extends User {
    public Owner(String name) {
        super(name);
    }

    @Override
    public String getAbbr() {
        return "u";
    }
}

public class Group extends User {
    public Group(String name) {
        super(name);
    }

    @Override
    public String getAbbr() {
        return "g";
    }
}

public class Other extends User {
    public Other(String name) {
        super(name);
    }

    @Override
    public String getAbbr() {
        return "o";
    }
}
public interface Permission {
    int getValue();
    String getAbbr();
    void accept(User u);
    void refuse(User u);
}
public class Read implements Permission {
    private static final int value = 4;

    @Override
    public int getValue() {
        return value;
    }

    @Override
    public String getAbbr() {
        return "r";
    }

    @Override
    public void accept(User u) {
        u.grant(this);
    }

    @Override
    public void refuse(User u) {
        u.revoke(this);
    }
}

public class Write implements Permission {
    private static final int value = 2;

    @Override
    public int getValue() {
        return value;
    }

    @Override
    public String getAbbr() {
        return "w";
    }

    @Override
    public void accept(User u) {
        u.grant(this);
    }

    @Override
    public void refuse(User u) {
        u.revoke(this);
    }
}

public class Execution implements Permission {
    private static final int value = 1;

    @Override
    public int getValue() {
        return value;
    }

    @Override
    public String getAbbr() {
        return "x";
    }

    @Override
    public void accept(User u) {
        u.grant(this);
    }

    @Override
    public void refuse(User u) {
        u.revoke(this);
    }
}
import java.util.ArrayList;
import java.util.List;

public class PermissionGroup {
    private int total;
    private List<Permission> permissions = new ArrayList<>();
    public void add(Permission p) {
        permissions.add(p);
    }

    public void grant(User u) {
        for (Permission p : permissions) {
            p.accept(u);
            total += p.getValue();
        }
        System.out.println(String.format("updated permission value: +%d\n", total));
    }

    public void revoke(User u) {
        for (Permission p : permissions) {
            p.refuse(u);
            total -= p.getValue();
        }
        System.out.println(String.format("updated permission value: %d\n", total));
    }
}
public class VisitorPattern {
    public static void main(String args[]) {
        PermissionGroup ownerPermission = new PermissionGroup();
        ownerPermission.add(new Read());
        ownerPermission.add(new Write());
        ownerPermission.add(new Execution());
        ownerPermission.grant(new Owner("john"));

        PermissionGroup groupPermission = new PermissionGroup();
        groupPermission.add(new Read());
        groupPermission.add(new Write());
        groupPermission.grant(new Group("root"));

        PermissionGroup otherPermission = new PermissionGroup();
        otherPermission.add(new Write());
        otherPermission.add(new Execution());
        otherPermission.revoke(new Other("tim"));
    }
}
grant john (u) "r" permission
grant john (u) "w" permission
grant john (u) "x" permission
updated permission value: +7

grant root (g) "r" permission
grant root (g) "w" permission
updated permission value: +6

revoke tim (o) "w" permission
revoke tim (o) "x" permission
updated permission value: -3
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值