圖解Java設計模式之訪問者模式
- 測驗系統的需求
- 傳統方式的問題分析
- 訪問者模式基本介紹
- 訪問者模式應用實體
- 訪問者模式的注意事項和細節
測驗系統的需求
1)將人分為男人和女人,對歌手進行測評,看完某個歌手表演后,得到他們對該歌手的不同評價(評價有不同的種類,比如成功、失敗等)
2)傳統方案
傳統方式的問題分析
1)如果系統比較小,沒有問題,但是考慮系統增加越來越多的新的功能時,對代碼改動比較大,違反類ocp原則,不利于維護,
2)擴展性不好,比如增加類新的人員型別,或者管理方法,
訪問者模式基本介紹
1)訪問者模式(Visitor Pattern),封裝一些作用于某種資料結構的各元素的操作,它可以在不改變資料結構的前提下定義作用于這些元素的新的操作,
2)主要將資料結構與資料操作分離,解決資料結構和操作耦合性問題
3)訪問者模式的基本作業原理是 :在被訪問的類里面加一個對外提供接待訪問者的介面
4)訪問者模式主要應用場景是 :需要對一個物件結構中的物件進行很多不同操作(這些操作彼此沒有關聯),同時需要避免讓這些操作“污染”這些物件的類,可以選用訪問者模式解決,
說明 :
1)Visitor 是抽象訪問者,為該物件結構中的ConcreteElement的每一個類宣告一個visit操作,
2)ConcreteVisitor :是一個具體的訪問值,實作每個有Visitor 宣告的操作,是每個操作實作的部分,
3)ObjectStructure 能列舉它的元素,可以提供一個高層的介面,用來允許訪問者訪問元素,
4)Element 定義一個accept方法,接收一個訪問者物件,
5)ConcreteElement 為具體元素,實作類accept方法,
訪問者模式應用實體

package com.example.demo.visitor;
import javax.activation.MailcapCommandMap;
public abstract class Action {
/**
* 得到男性的測評
* @param man
*/
public abstract void getManResult(Man man);
/**
* 得到女的測評
* @param woman
*/
public abstract void getWomanResult(Woman woman);
}
package com.example.demo.visitor;
public class Fail extends Action{
@Override
public void getManResult(Man man) {
// TODO Auto-generated method stub
System.out.println(" 男人給的評價該歌手很失敗 ! ");
}
@Override
public void getWomanResult(Woman woman) {
// TODO Auto-generated method stub
System.out.println(" 女人給的評價該歌手很失敗 ! ");
}
}
package com.example.demo.visitor;
public class Success extends Action{
@Override
public void getManResult(Man man) {
// TODO Auto-generated method stub
System.out.println(" 男人給的評價該歌手很成功 ! ");
}
@Override
public void getWomanResult(Woman woman) {
// TODO Auto-generated method stub
System.out.println(" 女人給的評價該歌手很成功 ! ");
}
}
package com.example.demo.visitor;
public abstract class Person {
public abstract void accept(Action action);
}
package com.example.demo.visitor;
public class Man extends Person {
@Override
public void accept(Action action) {
// TODO Auto-generated method stub
action.getManResult(this);
}
}
package com.example.demo.visitor;
/**
* 說明
* 1. 這里我們使用到了雙分派,即首先在客戶端程式中,將具體狀態作為引數傳遞Woman中(第一次分派)
* 2. 然后Woman 類呼叫作為引數的 “具體方法” 中方法getWomanResult,同時將自己(this)作為引數傳入,完成第二次的分派
* @author zhaozhaohai
*
*/
public class Woman extends Person {
@Override
public void accept(Action action) {
// TODO Auto-generated method stub
action.getWomanResult(this);
}
}
package com.example.demo.visitor;
import java.util.LinkedList;
import java.util.List;
/**
* 資料結構,管理很多人(Man,Woman)
* @author zhaozhaohai
*
*/
public class ObjectStructure {
/**
* 維護一個集合
*/
private List<Person> persons = new LinkedList<Person>();
/**
* 增加到list
* @param person
*/
public void attach(Person person) {
persons.add(person);
}
/**
* 移除
* @param person
*/
public void detach(Person person) {
persons.remove(person);
}
/**
* 顯示測驗情況
* @param action
*/
public void display(Action action) {
for (Person person : persons) {
person.accept(action);
}
}
}
package com.example.demo.visitor;
public class Wait extends Action{
@Override
public void getManResult(Man man) {
// TODO Auto-generated method stub
System.out.println(" 男人給的評價是該歌手待定,, ");
}
@Override
public void getWomanResult(Woman woman) {
// TODO Auto-generated method stub
System.out.println(" 女人給的評價是該歌手待定,, ");
}
}
package com.example.demo.visitor;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 創建ObjectStructure
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.attach(new Man());
objectStructure.attach(new Woman());
// 成功
Success success = new Success();
objectStructure.display(success);
System.out.println("-------------------");
// 失敗
Fail fail = new Fail();
objectStructure.display(fail);
System.out.println("----------給的是待定的測評------------");
Wait wait = new Wait();
objectStructure.display(wait);
}
}
小結 - 雙分派
上面提到雙分派,所謂雙分派是指不管類怎么變化,我們都能找到期望的方法運行,雙分派意味著得到執行的操作取決于請求的種類和兩個接收者的型別,
假設要添加一個Wait的狀態類,考察Man類和Woman類的反應,由于使用了雙分派,只需增加一個Action子類即可在客戶端呼叫即可,不需要改動任何其他類的代碼,
訪問者模式的注意事項和細節
優點 :
1)訪問者模式符合單一職責原則,讓程式具有優秀的擴展性和靈活性非常高,
2)訪問者模式可以對功能進行統一,可以做報表、UI、攔截器與過濾器,適用于資料結構相對穩定的系統,
缺點 :
1)具體元素對訪問者公布細節,也就是說訪問者關注類其他類的內部細節,這是迪米特法則所不建議的,這樣造成類具體元素變更比較困難,
2)違背類依賴導致原則,訪問者依賴的是具體元素,而不是抽象元素,
3)因此,如果一個系統有比較穩定的資料結構,又有經常變化的功能需求,那么訪問者模式就是比較合適的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/16298.html
標籤:設計模式
下一篇:圖解Java設計模式之迭代器模式
