訪問者模式
《Android原始碼設計模式解析與實戰》讀書筆記(十六)
《Android原始碼設計模式解析與實戰》PDF資料下載一、訪問者模式簡介
訪問者模式是一種將資料操作與資料結構分離的設計模式。
訪問者模式的基本想法是,軟體系統中擁有一個由許多物件構成的、比較穩定的物件結構,這些物件的類都擁有一個accept方法用來接受訪問者物件的訪問。
1.1、定義
封裝一些作用於某種資料結構中的各元素的操作,它可以在不改變這個資料結構的前提下定義作用於這些元素的新的操作。
1.2、使用場景
- 物件結構比較穩定,但經常需要在此物件結構上定義新的操作。
- 需要對一個物件結構中的物件進行很多不同的並且不相關的操作,而需要避免這些操作“汙染”這些物件的類,也不希望在增加新操作時修改這些類。
二、訪問者模式的簡單示例
public abstract class Staff { public String name; //員工kpi public int kpi; public Staff(String name) { this.name = name; kpi = new Random().nextInt(10); } //接受Visitor的訪問 public abstract void accept(Visitor visitor); }
public class Engineer extends Staff { public Engineer(String name) { super(name); } @Override public void accept(Visitor visitor) { visitor.visit(this); } //工程師這一年寫的程式碼數量 public int getCodeLines() { return new Random().nextInt(10 * 10000); } }
public class Manager extends Staff { private int products;//產品數量 public Manager(String name) { super(name); products = new Random().nextInt(10); } @Override public void accept(Visitor visitor) { visitor.visit(this); } //一年內做的產品數量 public int getProducts() { return products; } }
public interface Visitor { //訪問工程師型別 public void visit(Engineer engineer); //訪問經理型別 public void visit(Manager manager); }
//員工業務報表1類 public class BusinessReport { List<Staff> mStaffs = new LinkedList<>(); public BusinessReport() { mStaffs.add(new Manager("王經理")); mStaffs.add(new Engineer("工程師—Shawn.Xiong")); mStaffs.add(new Engineer("工程師——Kael")); mStaffs.add(new Engineer("工程師-Chaosssss")); mStaffs.add(new Engineer("工程師-Tiiime")); } /** * 為訪問者展示報表 */ public void showReport(Visitor visitor) { for (Staff staff : mStaffs) { staff.accept(visitor); } } }
//CEO訪問者,只關注業績 public class CEOVisitor implements Visitor { @Override public void visit(Engineer engineer) { System.out.println("工程師:" + engineer.name + ",KPI:" + engineer.kpi); } @Override public void visit(Manager manager) { System.out.println("經理:" + manager.name + ",KPI:" + manager.kpi + ",新產品數量:" + manager.getProducts()); } }
public class CTOVisitor implements Visitor { @Override public void visit(Engineer engineer) { System.out.println("工程師:" + engineer.name + ",程式碼函式:" + engineer.getCodeLines()); } @Override public void visit(Manager manager) { System.out.println("經理:" + manager.name + ",產品數量:" + manager.getProducts()); } }
public class Client { public static void main(String[] args) { //構建報表 BusinessReport report = new BusinessReport(); System.out.println("============給CEO看的報表==========="); //設定訪問者,這裡是CEO report.showReport(new CEOVisitor()); System.out.println("\n==================給CTO看的報表========================="); //注入另一個訪問者,CTO report.showReport(new CTOVisitor()); } }
輸出結果:

訪問者模式.png
三、總結
3.1、優點
- 各角色職責分離,符合單一職責原則;
- 具有優秀的擴充套件性;
- 使得資料結構和作用於結構上的操作解耦,使得操作集合可以獨立變化;
- 靈活性。
3.2、缺點
- 具體元素對訪問者公佈細節,違反了迪米特原則;
- 具體元素變更時導致修改成本大;
- 違反了依賴倒置原則,為了達到“區別對待”而依賴了具體類,沒有依賴抽象。
學海無涯苦作舟

我的微信公眾號