图解设计模式
来源:互联网 发布:神仙淘宝店txt下载 编辑:程序博客网 时间:2024/06/02 05:35
读书笔记 仅供参考
简述
通常将数据结构和处理数据的代码放到同一个类中,但是如果有多种处理方式,增加处理方式就会多次修改数据类。Visitor 模式(访问者模式)将数据结构与处理分离开来,增加新的处理时,只需要编写新的访问者就可以了。
UML 和角色
Visitor
负责对数据结构中每个具体的元素(ConcreteElement 角色)声明一个用于访问的 visit 方法。
ConcreteVisitor
负责实现 Visitor 角色定义的接口(API),要实现所有的 visit 方法。
Element
表示 Visitor 觉得访问对象,声明了接收访问者的 accept 方法。accept 方法的参数是 Visitor 角色。
ConcreteElement
负责实现 Element 角色定义的接口(API)。
ObjectStructure
负责处理 Element 角色的集合。
UML
例子
例程是一个访问文件夹和文件,显示文件名和大小的程序。ListVisitor 作为访问者,拥有两个方法,visit(File) 和 visit(Directory),将 ListVisitor 比作一个寻求帮助的人,那么 FIle 和 Directory 就是两个家庭(他们都属于家庭,虽然不一样)。当他们选择接收(accept 方法)访问者时,访问者就根据家庭的不同干不同的事(visit 方法)。
//表示访问者的抽象类,依赖于访问的数据结构public abstract class Visitor { //根据不同的参数调用不同的访问方法 public abstract void visit(File file); public abstract void visit(Directory directory);}
//访问数据结构并显示数据一览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<Entry> it = directory.iterator(); while (it.hasNext()) { Entry entry = it.next(); entry.accept(this); } currentDir = saveDir; }}
public interface Element { void accept(Visitor visitor);}
//相当于 Composite 模式的父类,在 Visitor 模式中使用并不是必须的//真正作为被访问者的是它的子类public abstract class Entry implements Element { public abstract String getName(); public abstract int getSize(); public Entry add(Entry entry) throws FileTreatmentException { throw new FileTreatmentException(); } public String toString() { return getName() + " (" + getSize() + ")"; }}
// 作为被访问的元素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 //告诉 Visitor 正在访问的对象是 File 的实例 public void accept(Visitor visitor) { visitor.visit(this); }}
public class Directory extends Entry { private String name; private List<Entry> dir = new ArrayList<>(); public Directory(String name) { this.name = name; } @Override public String getName() { return name; } @Override public int getSize() { int size = 0; Iterator<Entry> it = dir.iterator(); while (it.hasNext()) { Entry entry = it.next(); size += entry.getSize(); } return size; } @Override public Entry add(Entry entry) throws FileTreatmentException { dir.add(entry); return this; } public Iterator<Entry> iterator() { return dir.iterator(); } @Override public void accept(Visitor visitor) { visitor.visit(this); }}
public class Main { public static void main(String[] args) { try { System.out.println("Making root entries"); Directory rootDir = new Directory("root"); Directory binDir = new Directory("bin"); Directory tmpDir = new Directory("tmp"); Directory usrDir = new Directory("usr"); rootDir.add(binDir); rootDir.add(tmpDir); rootDir.add(usrDir); binDir.add(new File("vi", 10000)); binDir.add(new File("latex", 20000)); rootDir.accept(new ListVisitor()); System.out.println(""); System.out.println("Making user entries"); Directory yuki = new Directory("yuki"); Directory hanako = new Directory("hanako"); Directory tomura = new Directory("tomura"); usrDir.add(yuki); usrDir.add(hanako); usrDir.add(tomura); yuki.add(new File("diary.html", 100)); yuki.add(new File("Composite.java", 200)); hanako.add(new File("memo.tex", 300)); tomura.add(new File("game.doc", 400)); tomura.add(new File("junk.mail", 500)); rootDir.accept(new ListVisitor()); } catch (FileTreatmentException e) { e.printStackTrace(); } }}
运行结果
UML
要点
双重分发
像在 Visitor 模式中两个角色共同决定了实际进行的处理的消息分发的方式被称为双重分发。
开闭原则
Visitor 符合开闭原则:对扩展开发,对修改关闭。
阅读全文
0 0
- 设计模式图解
- gof23设计模式图解
- 图解设计模式
- 图解基础设施设计模式
- 设计模式图解
- 图解设计模式
- 图解设计模式
- 图解设计模式
- 图解设计模式
- 图解设计模式
- 图解设计模式
- 图解设计模式
- 图解设计模式
- 图解设计模式
- 图解设计模式
- 图解设计模式
- 图解设计模式
- 图解设计模式
- RXjava的见解
- jQuery:选择器小结
- java多线程交替打印0-100的奇偶数
- 文章标题
- sql
- 图解设计模式
- Python 的 six模块简介
- Android使用Activity用作弹出式对话框
- 详细解释CNN卷积神经网络各层的参数和链接个数的计算
- 以太坊开发文档08
- 用HttpURLConnection进行Post请求应答结果为null的原因分析
- 五种大数据处理架构
- ionic实现下拉刷新
- logrotate日志分割流程分析