設(shè)計(jì)模式之禪-訪問(wèn)者模式

在前面組合模式和迭代器模式中,講了如何把公司組織架構(gòu)樹搭建起來(lái),并且遍歷它。現(xiàn)在有這樣一個(gè)需求,要把公司的所有人員信息打印匯報(bào)。

這個(gè)類圖還是比較簡(jiǎn)單的,使用了一個(gè)模版方法模式,把所要的信息都打印出來(lái),我們先來(lái)看一下抽象類:

public abstract class Employee {

? ? public finial static int MAL = 0;? ? //男性

? ? public finial static int FEMAL = 1;? ? //女性

? ? // 姓名

? ? private String name;

? ? // 薪水

? ? private int salary;

? ? // 性別

? ? private int sex;

? ? get、set...

? ? // 打印員工信息

? ? 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();

}

普通員工:

public class CommonEmployee extends Employee {

????//工作內(nèi)容,這個(gè)非常重要,以后的職業(yè)規(guī)劃就是靠這個(gè)了

????private String job;

????public String getJob() {

????????return job;

????}

????public void setJob(String job) {

????????this.job = job;

????}

????protected String getOtherInfo(){

????????return "工作:"+ this.job + "\t";

????}

}

經(jīng)理級(jí)人物:

public class Manager extends Employee {

????//這類人物的職責(zé)非常明確:業(yè)績(jī)

????private String performance;

????public String getPerformance() {

????????return performance;

????}

????public void setPerformance(String performance) {

????????this.performance = performance;

????}

????protected String getOtherInfo(){

????????return "業(yè)績(jī):"+ this.performance + "\t";

????}

}

invoker 類:

public class Client {

????public static void main(String[] args) {

????????for(Employee emp:mockEmployee()){

????????????emp.report();

????????}

????}

????//模擬出公司的人員情況,我們可以想象這個(gè)數(shù)據(jù)室通過(guò)持久層傳遞過(guò)來(lái)的

????public static List<Employee> mockEmployee(){

????????????List<Employee> empList = new ArrayList<Employee>();

????????????//產(chǎn)生張三這個(gè)員工

????????????CommonEmployee zhangSan = new CommonEmployee();

????????????zhangSan.setJob("編寫Java程序,絕對(duì)的藍(lán)領(lǐng)、苦工加搬運(yùn)工");

????????????zhangSan.setName("張三");

????????????zhangSan.setSalary(1800);

????????????zhangSan.setSex(Employee.MALE);

????????????empList.add(zhangSan);

????????????//產(chǎn)生李四這個(gè)員工

????????????CommonEmployee liSi = new CommonEmployee();

????????????liSi.setJob("頁(yè)面美工,審美素質(zhì)太不流行了!");

????????????liSi.setName("李四");

????????????liSi.setSalary(1900);

????????????liSi.setSex(Employee.FEMALE);

????????????empList.add(liSi);

? ??????????//再產(chǎn)生一個(gè)經(jīng)理

????????????Manager wangWu = new Manager();

????????????wangWu.setName("王五");

????????????wangWu.setPerformance("基本上是負(fù)值,但是我會(huì)拍馬屁呀");

????????????wangWu.setSalary(18750);

????????????wangWu.setSex(Employee.MALE);

????????????empList.add(wangWu);

????????????return empList;

? ? ? ? }

? ? }

運(yùn)行結(jié)果:

姓名:張三 性別:男 薪水:1800 工作:編寫Java程序,絕對(duì)的藍(lán)領(lǐng)、苦工加搬運(yùn)工

姓名:李四 性別:女 薪水:1900 工作:頁(yè)面美工,審美素質(zhì)太不流行了!

姓名:王五 性別:男 薪水:18750 業(yè)績(jī):基本上是負(fù)值,但是我會(huì)拍馬屁呀

結(jié)果出來(lái)了,也非常正確。我們來(lái)想一想這個(gè)實(shí)際的情況,人力資源部門拿這這份表格會(huì)給誰(shuí)看呢?那當(dāng)然是大老板了,大老板關(guān)心的是什么?關(guān)心部門經(jīng)理的業(yè)績(jī)!小兵的情況不是他要了解的。

?大老板就看部門經(jīng)理的報(bào)表,小兵的報(bào)表可看可不看;

? 多個(gè)大老板,“嗜好”是不同的,主管銷售的,則主要關(guān)心的營(yíng)銷情況;主管會(huì)計(jì)的,則主要關(guān)心企業(yè)的整體財(cái)務(wù)運(yùn)行狀態(tài);主管技術(shù)的,則主要看技術(shù)的研發(fā)情況;

綜合成一句話,這個(gè)報(bào)表會(huì)有修改:數(shù)據(jù)的修改以及報(bào)表的展現(xiàn)修改,按照開(kāi)閉原則,項(xiàng)目分析的時(shí)候已經(jīng)考慮到這些可能引起變更的隱私,就需要在設(shè)計(jì)時(shí)考慮通過(guò)擴(kuò)展來(lái)來(lái)避開(kāi)未來(lái)需求變更而引起的代碼修改風(fēng)險(xiǎn)。我們來(lái)想一想,每個(gè)普通員工類和經(jīng)理類都一個(gè)方法 report,那是否可以把這個(gè)方法提取到另外一個(gè)類中來(lái)實(shí)現(xiàn)呢?

原有的示意圖如下:

這兩個(gè)類都一個(gè)相同的方法 report(),但是要實(shí)現(xiàn)的內(nèi)容不相同,而且還有可能會(huì)發(fā)生變動(dòng),那我們就讓其他類來(lái)實(shí)現(xiàn)這個(gè) report 方法,好,看示意圖圖的變更:

兩個(gè)類的 report 方法都不需要了,只有 Visitor 類來(lái)實(shí)現(xiàn)了 report 的方法

在抽象類 Employee 中增加了 accept 方法,這個(gè)方法是定義我這個(gè)類可以允許被誰(shuí)來(lái)訪問(wèn),也就定義一類訪問(wèn)者,在具體的實(shí)現(xiàn)類中調(diào)用訪問(wèn)者的方法。我們先看訪問(wèn)者接口 IVisitor 程序:

public interface IVisitor {?

????//首先定義我可以訪問(wèn)普通員工

????public void visit(CommonEmployee commonEmployee);

????//其次定義,我還可以訪問(wèn)部門經(jīng)理

????public void visit(Manager manager);

}

訪問(wèn)者的實(shí)現(xiàn)類:?

public class Visitor implements IVisitor {

????//訪問(wèn)普通員工,打印出報(bào)表

????public void visit(CommonEmployee commonEmployee) {

????????System.out.println(this.getCommonEmployee(commonEmployee));

????}

????//訪問(wèn)部門經(jīng)理,打印出報(bào)表

????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;

????}

????//組裝出部門經(jīng)理的信息

????private String getManagerInfo(Manager manager){

????????String basicInfo = this.getBasicInfo(manager);

????????String otherInfo = "業(yè)績(jī):"+manager.getPerformance() + "\t";

????????return basicInfo + otherInfo;

????}

????//組裝出普通員工信息

????private String getCommonEmployee(CommonEmployee commonEmployee){

????????String basicInfo = this.getBasicInfo(commonEmployee);

????????String otherInfo = "工作:"+commonEmployee.getJob()+"\t";

????????return basicInfo + otherInfo;

????}

}

在具體的實(shí)現(xiàn)類中,定義了兩個(gè)私有方法,作用就是產(chǎn)生需要打印的數(shù)據(jù)和格式,然后在訪問(wèn)者訪問(wèn)相關(guān)的對(duì)象時(shí),產(chǎn)生這個(gè)報(bào)表。繼續(xù)看 Employee 抽象類:

public abstract class Employee {

????public final static int MALE = 0; //0代表是男性

????public final static int FEMALE = 1; //1代表是女性

????//甭管是誰(shuí),都有工資

????private String name;

????//只要是員工那就有薪水

????private int salary;

????//性別很重要

????private int sex;

? ? get、set...

? ??//我允許一個(gè)訪問(wèn)者過(guò)來(lái)訪問(wèn)

????public abstract void accept(IVisitor visitor);

}

刪除了 report 方法,增加了 accept 方法,需要實(shí)現(xiàn)類來(lái)實(shí)現(xiàn)。繼續(xù)看實(shí)現(xiàn)類:

普通員工:

public class CommonEmployee extends Employee {

????//工作內(nèi)容,這個(gè)非常重要,以后的職業(yè)規(guī)劃就是靠這個(gè)了

????private String job;

????public String getJob() {

????????return job;

????}

????public void setJob(String job) {

????????this.job = job;

????}

????//我允許訪問(wèn)者過(guò)來(lái)訪問(wèn)

????@Override

????public void accept(IVisitor visitor){

????????visitor.visit(this);

????}

}

經(jīng)理級(jí)人物:

public class Manager extends Employee {

????//這類人物的職責(zé)非常明確:業(yè)績(jī)

????private String performance;

????public String getPerformance() {

????????return performance;

????}

????public void setPerformance(String performance) {

????????this.performance = performance;

????}

????//部門經(jīng)理允許訪問(wèn)者訪問(wèn)

????@Override

????public void accept(IVisitor visitor){

????????visitor.visit(this);

????}

}

public class Client {

????public static void main(String[] args) {

????????for(Employee emp:mockEmployee()){

????????????emp.accept(new Visitor());

????????}

????}

????//模擬出公司的人員情況,我們可以想象這個(gè)數(shù)據(jù)室通過(guò)持久層傳遞過(guò)來(lái)的

????public static List<Employee> mockEmployee(){

????????List<Employee> empList = new ArrayList<Employee>();

????????//產(chǎn)生張三這個(gè)員工

????????CommonEmployee zhangSan = new CommonEmployee();

????????zhangSan.setJob("編寫Java程序,絕對(duì)的藍(lán)領(lǐng)、苦工加搬運(yùn)工");

????????zhangSan.setName("張三");

????????zhangSan.setSalary(1800);

????????zhangSan.setSex(Employee.MALE);

????????empList.add(zhangSan);

????????//產(chǎn)生李四這個(gè)員工

????????CommonEmployee liSi = new CommonEmployee();

????????liSi.setJob("頁(yè)面美工,審美素質(zhì)太不流行了!");

????????liSi.setName("李四");

????????liSi.setSalary(1900);

????????liSi.setSex(Employee.FEMALE);

????????empList.add(liSi);

????????//再產(chǎn)生一個(gè)經(jīng)理

????????Manager wangWu = new Manager();

????????wangWu.setName("王五");

????????wangWu.setPerformance("基本上是負(fù)值,但是我會(huì)拍馬屁呀");

????????wangWu.setSalary(18750);

????????wangWu.setSex(Employee.MALE);

????????empList.add(wangWu);


????????return empList;

? ? }

}

看運(yùn)行結(jié)果:

姓名:張三 性別:男 薪水:1800 工作:編寫Java程序,絕對(duì)的藍(lán)領(lǐng)、苦工加搬運(yùn)工

姓名:李四 性別:女 薪水:1900 工作:頁(yè)面美工,審美素質(zhì)太不流行了!

姓名:王五 性別:男 薪水:18750 業(yè)績(jī):基本上是負(fù)值,但是我會(huì)拍馬屁呀

? 首先通過(guò)循環(huán)遍歷所有元素;

? 其次,每個(gè)員工對(duì)象都定義了一個(gè)訪問(wèn)者;

? 再其次,員工對(duì)象把自己做為一個(gè)參數(shù)調(diào)用訪問(wèn)者 visit 方法;

? 然后,訪問(wèn)者調(diào)用自己內(nèi)部的計(jì)算邏輯,計(jì)算出相應(yīng)的數(shù)據(jù)和表格元素;

? 最后,訪問(wèn)者打印出報(bào)表和數(shù)據(jù);

訪問(wèn)者模式通用類圖:


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容