DesignPattern_訪問者模式_19
訪問者模式
定義
Represent anoperation to be performed on the elements of an object structure. Visitor lets you define a newoperation without changing the classes of the elements on which it operates.
封裝一些作用於某種資料結構中的各元素的操作,它可以在不改變資料結構的前提下定義作用於這些元素的新的操作。
- Visitor——抽象訪問者
抽象類或者介面,宣告訪問者可以訪問哪些元素,具體到程式中就是visit方法的引數定義哪些物件是可以被訪問的。 - ConcreteVisitor——具體訪問者
它影響訪問者訪問到一個類後該怎麼幹,要做什麼事情 - Element——抽象元素
介面或者抽象類,宣告接受哪一類訪問者訪問,程式上是通過accept方法中的引數來定義的。 - ConcreteElement——具體元素
實現accept方法,通常是visitor.visit(this),基本上都形成了一種模式了。 - ObjectStruture——結構物件
元素產生者,一般容納在多個不同類、不同介面的容器,如List、Set、Map等,在專案中,一般很少抽象出這個角色。
優點
- 符合單一職責原則
具體元素角色也就是Employee抽象類的兩個子類負責資料的載入,而Visitor類則負責報表的展現,兩個不同的職責非常明確地分離開來,各自演繹變化 - 優秀的擴充套件性
由於職責分開,繼續增加對資料的操作是非常快捷的,例如,現在要增加一份給大老闆的報表,這份報表格式又有所不同,直接在Visitor中增加一個方法,傳遞資料後進行整理列印 - 靈活性非常高
缺點
- 具體元素對訪問者公佈細節
訪問者要訪問一個類就必然要求這個類公佈一些方法和資料,也就是說訪問者關注了其他類的內部細節,這是迪米特法則所不建議的。 - 具體元素變更比較困難
具體元素角色的增加、刪除、修改都是比較困難的,就上面那個例子,你想想,你要是想增加一個成員變數,如年齡age,Visitor就需要修改,如果Visitor是一個還好辦,多個呢?業務邏輯再複雜點呢? - 違背了依賴倒置轉原則
問者依賴的是具體元素,而不是抽象元素,這破壞了依賴倒置原則,特別是在物件導向的程式設計中,拋棄了對介面的依賴,而直接依賴實現類,擴充套件比較難。
程式碼實現
/**
* @author huangqh
* @create 2020/12/21 17:55
* @Notes 訪問者模式
*/
public class VisitorModel {
}
/**
* 抽象員工
*/
@Data
abstract class Employee {
public final static int MALE = 0; //0代表是男性
public final static int FEMALE = 1; //1代表是女性
private String name;
private int salary;
private int sex;
public final void report() {
String info = "姓名:" + this.name + "\t";
info = info + "性別:" + (this.sex == FEMALE ? "女" : "男") + "\t";
info = info + "薪水:" + this.salary + "\t";
//獲得員工的其他資訊
info = info + this.getOtherInfo();
System.out.println(info);
}
//拼裝員工的其他資訊
protected abstract String getOtherInfo();
}
/**
* 普通員工
*/
@Data
class CommonEmployee extends Employee {
private String job;
@Override
protected String getOtherInfo() {
return "工作:" + this.job + "\t";
}
}
/**
* 管理階層
*/
@Data
class Manager extends Employee {
//這類人物的職責非常明確:業績
private String performance;
@Override
protected String getOtherInfo() {
return "業績:" + this.performance + "\t";
}
}
class Clien {
public static void main(String[] args) {
for (Employee emp : mockEmployee()) {
emp.report();
}
}
public static List<Employee> mockEmployee() {
List<Employee> empList = new ArrayList<Employee>();
//產生張三這個員工
CommonEmployee zhangSan = new CommonEmployee();
zhangSan.setJob("編寫Java程式,絕對的藍領、苦工加搬運工");
zhangSan.setName("張三");
zhangSan.setSalary(1800);
zhangSan.setSex(Employee.MALE);
empList.add(zhangSan);
//產生李四這個員工
CommonEmployee liSi = new CommonEmployee();
liSi.setJob("頁面美工,審美素質太不流行了!");
liSi.setName("李四");
liSi.setSalary(1900);
liSi.setSex(Employee.FEMALE);
empList.add(liSi);
//再產生一個經理
Manager wangWu = new Manager();
wangWu.setName("王五");
wangWu.setPerformance("基本上是負值,但是我會拍馬屁呀");
wangWu.setSalary(18750);
wangWu.setSex(Employee.MALE);
empList.add(wangWu);
return empList;
}
}
訪問者模式
/**
* @author huangqh
* @create 2020/12/21 17:55
* @Notes 訪問者模式
*/
public class VisitorModel {
}
/**
* 抽象員工
*/
@Data
abstract class Employee {
public final static int MALE = 0; //0代表是男性
public final static int FEMALE = 1; //1代表是女性
private String name;
private int salary;
private int sex;
//我允許一個訪問者訪問
public abstract void accept(IVisitor visitor);
}
/**
* 普通員工
*/
@Data
class CommonEmployee extends Employee {
private String job;
//我允許訪問者訪問
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
/**
* 管理階層
*/
@Data
class Manager extends Employee {
//這類人物的職責非常明確:業績
private String performance;
//部門經理允許訪問者訪問
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
/**
* 訪問者介面
*/
interface IVisitor {
//首先,定義我可以訪問普通員工
public void visit(CommonEmployee commonEmployee);
//其次,定義我還可以訪問部門經理
public void visit(Manager manager);
}
/**
*
*/
class Visitor implements IVisitor {
//訪問普通員工,列印出報表
@Override
public void visit(CommonEmployee commonEmployee) {
System.out.println(this.getCommonEmployee(commonEmployee));
}
//訪問部門經理,列印出報表
@Override
public void visit(Manager manager) {
System.out.println(this.getManagerInfo(manager));
}
//組裝出基本資訊
private String getBasicInfo(Employee employee) {
String info = "姓名:" + employee.getName() + "\t";
info = info + "性別:" + (employee.getSex() == Employee.FEMALE ? "女" : "男") + "\t";
info = info + "薪水:" + employee.getSalary() + "\t";
return info;
}
//組裝出部門經理的資訊
private String getManagerInfo(Manager manager) {
String basicInfo = this.getBasicInfo(manager);
String otherInfo = "業績:" + manager.getPerformance() + "\t";
return basicInfo + otherInfo;
}
//組裝出普通員工資訊
private String getCommonEmployee(CommonEmployee commonEmployee) {
String basicInfo = this.getBasicInfo(commonEmployee);
String otherInfo = "工作:" + commonEmployee.getJob() + "\t";
return basicInfo + otherInfo;
}
}
class Clien {
public static void main(String[] args) {
for (Employee emp : mockEmployee()) {
emp.accept(new Visitor());
}
}
public static List<Employee> mockEmployee() {
List<Employee> empList = new ArrayList<Employee>();
//產生張三這個員工
CommonEmployee zhangSan = new CommonEmployee();
zhangSan.setJob("編寫Java程式,絕對的藍領、苦工加搬運工");
zhangSan.setName("張三");
zhangSan.setSalary(1800);
zhangSan.setSex(Employee.MALE);
empList.add(zhangSan);
//產生李四這個員工
CommonEmployee liSi = new CommonEmployee();
liSi.setJob("頁面美工,審美素質太不流行了!");
liSi.setName("李四");
liSi.setSalary(1900);
liSi.setSex(Employee.FEMALE);
empList.add(liSi);
//再產生一個經理
Manager wangWu = new Manager();
wangWu.setName("王五");
wangWu.setPerformance("基本上是負值,但是我會拍馬屁呀");
wangWu.setSalary(18750);
wangWu.setSex(Employee.MALE);
empList.add(wangWu);
return empList;
}
}
相關文章
- 訪問者模式模式
- 行為模式-訪問者模式模式
- python-訪問者模式Python模式
- 設計模式(十六)——訪問者模式設計模式
- 極簡設計模式-訪問者模式設計模式
- 深入淺出訪問者模式模式
- 設計模式 - ASM 中的訪問者模式設計模式ASM
- 設計模式學習之訪問者模式設計模式
- C#設計模式之訪問者模式C#設計模式
- 【趣味設計模式系列】之【訪問者模式】設計模式
- 15.java設計模式之訪問者模式Java設計模式
- 設計模式(二十三)訪問者設計模式
- Java進階篇設計模式之十 ---- 訪問者模式和中介者模式Java設計模式
- Android理解設計模式之組合模式、迭代器模式、訪問者模式Android設計模式
- 設計模式學習-使用go實現訪問者模式設計模式Go
- 「補課」進行時:設計模式(18)——訪問者模式設計模式
- 軟體設計模式系列之二十五——訪問者模式設計模式
- 軟體設計模式學習(二十七)訪問者模式設計模式
- 聊聊OOP中的設計原則以及訪問者模式OOP模式
- 【設計模式】詳解訪問者(Visitor)模式-有多段程式碼出沒設計模式
- 設計模式學習筆記(二十一)訪問者模式及其實現設計模式筆記
- C++設計模式 - 訪問器模式(Visitor)C++設計模式
- 極簡架構模式-資料訪問物件模式架構模式物件
- tour cpp: std::variant 實現無繼承層次的訪問者模式繼承模式
- 徹底搞懂訪問者模式的靜態、動態和偽動態分派模式
- Kubernetes API訪問鑑權之Basic模式API模式
- 代理模式-訪問物件的代理而非其本身模式物件
- 重學 Java 設計模式:實戰訪問者模式「模擬家長與校長,對學生和老師的不同視角資訊的訪問場景」Java設計模式
- PHP設計模式-DAO (Data Access Objects) 資料訪問物件模式PHP設計模式Object物件
- 設計模式系列之代理模式(Proxy Pattern)——物件的間接訪問設計模式物件
- 3.2.4 開啟資料庫到限制訪問模式資料庫模式
- win10怎麼設定ftp為主動訪問模式_win10設定ftp為主動訪問模式教程Win10FTP模式
- 訪問使用者中心實現認證
- GoLang設計模式19 - 橋接模式Golang設計模式橋接
- 宿主機無法訪問VM中的linux(NAT模式)Linux模式
- derby 資料庫 伺服器模式 無法訪問資料庫伺服器模式
- oralce 跨使用者訪問表 同義詞
- redis設計統計使用者訪問量Redis