图解设计模式 -- 访问数据结构

代码Github连接 :https://github.com/tangbi123/Tab-Design-Pattern

Visitor模式

Visitor模式中,数据结构与处理被分离开来。
我们编写“访问者”的类来访问数据结构中的元素,并把对各元素的处理交给访问者类。这样,当需要增加新的处理时,我们只需要修改或编写新的访问者,然后让数据结构可以接受访问者的访问即可。

1、示例

在这里插入图片描述
在这里插入图片描述

代码清单

1)Visitor

public abstract class Visitor {
    public abstract void visit(File file);
    public abstract void visit(Directory directory);
}

2)Element

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

3)FileThredmentException

public class FileTreatmemtException extends RuntimeException {
    public FileTreatmemtException() {
    }
    public FileTreatmemtException(String message) {
        super(message);
    }
}

4)Entry

public abstract class Entry implements Element{
    public abstract String getName();
    public abstract int getSize();
    public Entry add(Entry entry) throws FileTreatmemtException
    {
        throw new FileTreatmemtException();
    }
    public Iterator iterator() throws FileTreatmemtException{
        throw new FileTreatmemtException();
    }
    public String toString(){
        return getName() + "(" + getSize() + ")";
    }
}

5)File

public class File extends Entry{
    private String name;
    private int size;

    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getSize() {
        return size;
    }
    @Override
    public void accept(Visitor v) {
        v.visit(this);
    }
}

6)Directory

public class Directory extends Entry {
    private String name;
    private ArrayList directory = new ArrayList();
    public Directory(String name){
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getSize() {
        int size = 0;
        Iterator it = directory.iterator();
        while(it.hasNext()){
            Entry entry = (Entry) it.next();
            size += entry.getSize();
        }
        return size;
    }

    public Entry add(Entry entry){
        directory.add(entry);
        return this;
    }

    public Iterator iterator(){
        return directory.iterator();
    }
    @Override
    public void accept(Visitor v) {
        v.visit(this);
    }
}

7)ListVisitor

public class ListVisitor extends Visitor{
    private String currentDir = "";
    @Override
    public void visit(File file) {
        System.out.println(currentDir + "/" + file);
    }

    @Override
    public void visit(Directory directory) {
        System.out.println(currentDir + "/" + directory);
        String saveDir = currentDir;
        currentDir = currentDir + "/" + directory.getName();
        Iterator it = directory.iterator();
        while(it.hasNext()){
            Entry entry = (Entry)it.next();
            //用 本visitor访问 entry
            entry.accept(this);
        }
        currentDir = saveDir;
    }
}

8)Main

public class VisitorMain {
    public static void main(String[] args) {
        System.out.println("Making root entries...");
        Directory rootDir = new Directory("root");
        Directory binDir = new Directory("bin");
        Directory tmpDir = new Directory("tmp");
        Directory userDir = new Directory("user");
        rootDir.add(binDir);
        rootDir.add(tmpDir);
        rootDir.add(userDir);
        binDir.add(new File("vi", 10000));
        binDir.add(new File("latex", 20000));
        rootDir.accept(new ListVisitor());
    }
}

时序图
在这里插入图片描述

2、角色

在这里插入图片描述
1)Visitor(访问者) =》 visitor
负责对数据结构中的每个具体元素, 声明一个用于访问 xxxx的visit(xxxx)的方法。 visit(xxxx)用于处理xxxx的方法,负责实现该方法的是ConcretVisitor。
2)ConcreteVisitor(具体访问者) =》 ListVisitor
负责实现Visitor角色所定义的接口(API)。实现所有的visit(xxxx)方法,即实现处理每个ConcreteElement角色。
3)Element(元素)
Element角色表示Visitor角色访问的对象。声明了接受访问者accept方法,参数是Visitor角色。
4)ConcreteElement =》 File、Directory
负责实现Element角色所定义的接口(API)。
5)ObjectStructure(对象结构) =》Directory
负责处理Element角色的集合,ConcreteVisistor角色为美俄个Element角色都准备了处理方法。

3、思路要点

双重分发

element.accept(Visitor);
visitor.visit(element);
他们是相反的关系,element接受visitor,而visitor又访问element。
ConcreteElement和ConcreteVisitor这两个角色共同决定了实际进行的处理。

为什么要弄得这么复杂

Visitor是将处理从数据结构中分离开来。

开闭原则–对扩展开放,对修改关闭

开闭原则:在不修改现有代码的前提下进行扩展。

易于增加ConcreteVisitor角色

难以增加ConcreteElement角色

Visitor工作所需的条件

visitor只有从数据结构中获取了足够多的信息后才能工作(Directory的Iterator),不然无法工作。
缺点是,如果公开了不应当被公开的信息,将来对数据结构的改良就会变得非常困难。

Chain of Resposibility模式

推卸责任
我们考虑将多个对象组成一条职责链,然后按照他们呢在职责链上的顺序一个一个地找出到底应该谁来负责处理。
可以弱化为 “请求方” 和 “处理方”之间地关联关系,让双方各自都可以成为可独立复用地组件。

1、示例

在这里插入图片描述
在这里插入图片描述

代码清单

1)Trouble

public class Trouble {
    private int number;
    public Trouble(int number){
        this.number = number;
    }
    public int getNumber(){
        return number;
    }
    public String toString(){
        return "[Touble" + number + "]";
    }
}

2)Support

public abstract class Support {
    private String name;
    private Support next;
    public Support(String name){
        this.name = name;
    }
    public Support setNext(Support next){
        this.next = next;
        return next;
    }
    public final void support(Trouble trouble){
        if(resolve(trouble)){
            done(trouble);
        }
        else if(next != null){
            next.support(trouble);
        }
        else fail(trouble);
    }
    public String toString(){
        return "[" + name  + "]";
    }
    protected abstract boolean resolve(Trouble touble);
    protected void done(Trouble trouble){
        System.out.println(trouble + " is resolved by " + this + ".");
    }
    protected void fail(Trouble trouble){
        System.out.println(trouble + " cannot be resolved");
    }
}

3)NoSupport

public class NoSupport extends Support{
    public NoSupport(String name) {
        super(name);
    }

    @Override
    protected boolean resolve(Trouble touble) {
        return false;
    }
}

4)LimitSupport

public class LimitSupport extends Support{
    private int limit;
    public LimitSupport(String name, int limit) {
        super(name);
        this.limit = limit;
    }

    @Override
    protected boolean resolve(Trouble touble) {
        if(touble.getNumber() < limit){
            return true;
        }
        return false;
    }
}

5)SpecialSupport

public class SpecialSupport extends Support{
    private int number;

    public SpecialSupport(String name, int number) {
        super(name);
        this.number = number;
    }

    @Override
    protected boolean resolve(Trouble touble) {
        if(touble.getNumber() == number){
            return true;
        }
        return false;
    }
}

6)OddSupport

public class OddSupport extends Support{
    public OddSupport(String name) {
        super(name);
    }

    @Override
    protected boolean resolve(Trouble touble) {
        if(touble.getNumber() % 2 == 1){
            return true;
        }
        return false;
    }
}

7)Main

public class ChainMain {
    public static void main(String[] args) {
        Support alice = new NoSupport("Alice");
        Support bob = new LimitSupport("Bob", 100);
        Support charlie = new SpecialSupport("Charlie", 429);
        Support diana = new LimitSupport("Diana", 200);
        Support elmo = new OddSupport("Elmo");
        Support fred = new LimitSupport("Fred", 300);

        alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred);

        for(int i = 0; i < 500; i+= 33){
            alice.support(new Trouble(i));
        }
    }
}

在这里插入图片描述

时序图

在这里插入图片描述

2、角色

在这里插入图片描述
1)Handler(处理着) =》Support
定义了处理请求地接口(API).Handler角色知道“下一个处理者”是谁,如果自己无法处理请求,它会将请求转给下一个处理者。 当然 下一个处理者也是 Handler角色。
2)ConcreteHandler(具体的处理者) =》NoSupport、LimitSupport、OddSupport、SpecialSupport
是处理请求地具体角色。
3)Client(请求者)
向第一个ConcreteHandler角色发送请求地角色。

3、思路要点

弱化了发出请求地人和处理请求的人之间的关系

可以动态地改变职责链

专注于自己的工作

推卸请求会导致处理延迟吗

确实如此。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值