設計模式(十八)---訪問者模式

來源:互聯網
上載者:User

設計模式(十八)---訪問者模式

定義:封裝一些作用於某種資料結構中的各元素的操作,它可以在不改變資料結構的前提下定義作用於這些元素的新的操作。

一般模式


Visitor----抽象訪問者
--"抽象類別或介面,聲明訪問者可以訪問那些元素,具體到程式中的就是visit的參數定義那些對象是可以被訪問的。
ConcreteVisotor---抽象元素
---|他影響訪問者訪問到類後,該怎麼做,要做什麼事情。
Element---抽象元素
--|介面或者抽象類別,聲明接受哪一類訪問者訪問,程式上通過accept方法中的參數定義
ConcreteElement---具體元素
--|實現accept方法,通常是visitor.visit(this),基本上都形成了一種模式了。
ObjectStruture---結構對象

--|元素產生者,一般容納在多個不同類、不同介面的容器,如List、Set、Map等,在項目中,一般很少抽象出這個角色。

public class VisitorTest {public static void main(String[] args) {//產生10個具體元素對象for(int i=0;i<10;i++){Element e = ObjectStruture.createElement();//接收訪問者訪問e.accept(new ConcreteVisitor());}}}/** * 抽象元素類 * 除了有自己的商務邏輯外, * 定義哪一類的訪問者,可以訪問。 * @author admin * */abstract class Element{//執行自身的商務邏輯public abstract void doSomenthing();//定義訪問者都有哪些public abstract void accept(IVisitor visitor);}/** * 具體的實現元素類。 * 1、實現自身的具體商務邏輯 * 2、設定哪個訪問者可以訪問 * @author admin * */class ConcreteElement1 extends Element{@Overridepublic void doSomenthing() {System.out.println("我是元素1的具體實現者...");}@Overridepublic void accept(IVisitor visitor) {visitor.visit(this);}}/** * 具體的實現元素類。 * 1、實現自身的具體商務邏輯 * 2、設定哪個訪問者可以訪問 * @author admin * */class ConcreteElement2 extends Element{@Overridepublic void doSomenthing() {System.out.println("我是元素2的具體實現者...");}@Overridepublic void accept(IVisitor visitor) {visitor.visit(this);}}/** * 抽象訪問者, * 聲明訪問者可以訪問哪些類。具體的執行方法有子類去實現 * @author admin * */interface IVisitor{//定義訪問ConcreteElement1類的具體實現public void visit(ConcreteElement1 con1);//定義訪問ConcreteElement2類的具體實現public void visit(ConcreteElement2 con2);}/** * 訪問者的具體實作類別, * 訪問者訪問到類以後,做什麼事情,有該類來具體實現 * @author admin * */class ConcreteVisitor implements IVisitor{@Overridepublic void visit(ConcreteElement1 con1) {con1.doSomenthing();System.out.println("----訪問者1號,執行任務");}@Overridepublic void visit(ConcreteElement2 con2) {con2.doSomenthing();System.out.println("----訪問者2號,執行任務");}}/** * 元素的產生者,用於產生被訪問者類型的對象。 * @author admin * */class ObjectStruture{//利用一個隨機數,產生實作類別1和2的對象public static Element createElement(){Random random = new Random();if(random.nextInt(100)>50){return new ConcreteElement1();}return new ConcreteElement2();}}

一個例子

一個公司有普通員工和經理,他們都有:姓名、性別、薪水。
私人屬性:員工:job(工作),經理:performance(業績)。
這裡需要列印一堆報表,要求員工和經理的相互區分。如何設計合理呢?

public class VisitorT {public static void main(String[] args) {//列印公司員工的報表for(Emploee e : mockEmploy()){e.accept(new EmployeeVisitor());}}//類比公司所有的人員。public static List mockEmploy(){List employeeList = new ArrayList();//建立一些普通員工Employer common1 = new Employer();common1.setName("lz");common1.setJob("APP應用上市..");common1.setSalary(12000);common1.setSex(1);Employer common2 = new Employer();common2.setName("ly");common2.setJob("APP應用上市..");common2.setSalary(11000);common2.setSex(1);Employer common3 = new Employer();common3.setName("ht");common3.setJob("美工做好..");common3.setSalary(10000);common3.setSex(2);//定義一個經理Manager m = new Manager();m.setName("lzl");m.setPerformence("今天晚上一定加班...");m.setSalary(1000000);m.setSex(1);//添加employeeList.add(common3);employeeList.add(common1);employeeList.add(common2);employeeList.add(m);return employeeList;}}/** * 抽象的員工報表類, * 定義共有的屬性方法。 * 並提供一個觀察者類的介面 * @author admin * */abstract class Emploee{private String name;private int sex;private double salary;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getSex() {return sex;}public void setSex(int sex) {this.sex = sex;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public abstract void accept(IEmployeeVisitor visitor);}/** * 經理類的具體實作類別。 * @author admin * */class Manager extends Emploee{//經理關注的是公司業績private String performence;public String getPerformence() {return performence;}public void setPerformence(String performence) {this.performence = performence;}@Overridepublic void accept(IEmployeeVisitor visitor) {visitor.visit(this);}}/** * 普通員工的具體實作類別。 * @author admin */class Employer extends Emploee{//普工關注的是工作private String job;public String getJob() {return job;}public void setJob(String job) {this.job = job;}@Overridepublic void accept(IEmployeeVisitor visitor) {visitor.visit(this);}}/** * 報表觀察者介面類, * 設定觀察者觀察具體的實作類別。 * 具體的實現方法,由實作類別來完成 * @author admin * */interface IEmployeeVisitor{//設定觀察普通員工public void visit(Employer employer);//設定觀察經理public void visit(Manager manager);}/** * 具體的觀察者實作類別, * 實作類別中觀察到被觀察者,之後需要列印報表。 * @author admin * */class EmployeeVisitor implements IEmployeeVisitor{@Overridepublic void visit(Employer employer) {System.out.println(this.getEmployerInfo(employer));}@Overridepublic void visit(Manager manager) {System.out.println(this.getManageInfo(manager));}//擷取員工的基本共有資訊private String getBaseInfo(Emploee e){String info = "姓名:"+e.getName()+"\t性別:"+(e.getSex()==1 ? "男" : "女")+"\t薪水:"+e.getSalary();return info;}//擷取經理的所有資訊private String getManageInfo(Manager m){String info = m.getPerformence();return info+"\t"+getBaseInfo(m);}//擷取普通員工的全部資訊private String getEmployerInfo(Employer e){String info = e.getJob();return info+"\t"+getBaseInfo(e);}}
訪問者模式的擴充

---|統計功能

interface IEmployeeVisitor{//設定觀察普通員工public void visit(Employer employer);//設定觀察經理public void visit(Manager manager);//統計薪水功能public void totalSalary();}/** * 具體的觀察者實作類別, * 實作類別中觀察到被觀察者,之後需要列印報表。 * @author admin * */class EmployeeVisitor implements IEmployeeVisitor{//經理總共薪資private double totalManager=0;//普通員工薪資private double totalEmployer=0;@Overridepublic void visit(Employer employer) {this.getEmployer(employer);}@Overridepublic void visit(Manager manager) {this.getManagerSalary(manager);}//統計總共的薪水@Overridepublic void totalSalary() {System.out.println( "公司一年支付的薪水是:"+this.totalEmployer + this.totalManager);}//統計經理的薪水private void getManagerSalary(Manager m){this.totalManager = this.totalManager + m.getSalary();}//統計員工的薪水private void getEmployer(Employer e){this.totalEmployer = this.totalEmployer + e.getSalary();}}

訪問者模式的優點:
符合單一職責原則
優秀的擴充性
靈活性非常高
訪問者模式的缺點:
具體元素對訪問者公布細節
具體元素變更比較困難
違背了依賴倒置原則

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.