1.?訪問者模式介紹
訪問者模式(Visitor Pattern)是一種行為型設計模式,它允許你在不改變對象結構的前提下,定義作用于這些對象的新操作。訪問者模式將操作的邏輯從對象結構中分離出來,使得你可以在運行時動態地添加新的操作。
類比場景:想象一下,你有一個博物館,里面有不同的展品(對象結構):繪畫、雕塑等。當有不同的訪客(訪問者,比如藝術愛好者、學生等)來參觀時,他們可能希望對展品進行不同的處理或觀察(操作)。訪問者模式就像是讓這些訪客帶著自己的需求來參觀博物館,而博物館本身無需改變展品的展示方式。當有新的訪問者要進行新的操作時,只需要新增一個訪問者即可。
結構組成:
- Visitor(訪問者接口):定義訪問者可以執行的操作;對每種元素類型都有一個方法。
- ConcreteVisitor(具體訪問者):實現Visitor接口,定義每個元素的具體訪問行為。
- Element(元素接口):被訪問者接口,定義接受訪問者的方法。
- ConcreteElement(具體元素):實現Element接口,具體定義接受訪問者的行為。
- Object Structure:包含元素的集合,提供一個可以遍歷這些元素的高層接口,并讓訪問者訪問它們。
優缺點分析:
- 優點:
- 新增操作方便:可以在不修改對象結構的情況下增加新的操作(通過新增visitor實現)。
- 符合單一職責原則:將不同的操作分離到不同的訪問者中。
- 擴展性好:可以很方便地增加新的訪問者。
- 缺點:
- 對象結構必須穩定:如果對象結構經常改變,維護成本會很高(每個visitor里定義了對所有元素的訪問,如果元素發生改變,需要修改所有visitor)。
- 具體元素更復雜:每個具體元素都需要實現接受訪問者的方法。
- 可能導致類爆炸:如果元素和訪問者種類很多,會導致類數量激增。
適用場景:
- 當對象結構較為穩定,且需要在此結構上定義新的操作時。
- 當需要對一個對象結構中的對象進行很多不同且不相關的操作時。
2. 代碼演示
場景:學生和藝術愛好者(visitor)去博物館(objectStructure)參觀繪畫和雕像(element),各類人行為不同。
Visitor(訪問者接口):
// Visitor接口:定義一個訪問者可以執行的操作
// 包含了對所有具體元素的訪問方法
public interface Visitor {void visit(Painting painting);void visit(Sculpture sculpture);
}
ConcreteVisitor(具體訪問者):
//具體訪問者: 實現Visitor接口,用于定義某種操作
//藝術愛好者的行為
public class ArtLoverVisitor implements Visitor {@Overridepublic void visit(Painting painting) {System.out.println("ArtLoverVisitor visit painting: " + painting.getName());}@Overridepublic void visit(Sculpture sculpture) {System.out.println("ArtLoverVisitor visit sculpture: " + sculpture.getName());}
}//學生的行為
public class StudentVisitor implements Visitor {@Overridepublic void visit(Painting painting) {System.out.println("StudentVisitor visit painting: " + painting.getName());}@Overridepublic void visit(Sculpture sculpture) {System.out.println("StudentVisitor visit sculpture: " + sculpture.getName());}
}
Element(元素接口):
// Element接口:被訪問對象,定義接受訪問者的接口
public interface Exhibit {void accept(Visitor visitor);
}
ConcreteElement(具體元素):
// 具體元素: 實現Element接口,定義接受訪問者的操作
// 繪畫
public class Painting implements Exhibit {private String name;public Painting(String name) {this.name = name;}public String getName() {return name;}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}//雕像
public class Sculpture implements Exhibit {private String name;public Sculpture(String name) {this.name = name;}public String getName() {return name;}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}
Object Structure:
// ObjectStructure:維護元素對象列表,并提供高層方法來遍歷操作這些對象
public class Museum {private List<Exhibit> exhibits = new ArrayList<>();public void addExhibit(Exhibit exhibit) {exhibits.add(exhibit);}public void showExhibits(Visitor visitor) {for (Exhibit exhibit : exhibits) {exhibit.accept(visitor);}}
}
客戶端:
public class VisitorClientDemo {public static void main(String[] args) {Museum museum = new Museum();museum.addExhibit(new Sculpture("The Thinker"));museum.addExhibit(new Painting("Starry Night"));Visitor visitor1 = new ArtLoverVisitor();museum.showExhibits(visitor1);Visitor visitor2 = new StudentVisitor();museum.showExhibits(visitor2);}
}
對應的類圖:
擴展:
上述示例中,將操作(學生/藝術愛好者的行為) 從對象結構(繪畫/雕塑等展覽)中分離出來了,后續若需添加新的操作(歷史專家的行為),只需要新增對應的visitor(HistorianVisitor) 即可。