訪問者模式原理分析
- 設計模式系列總覽
- 前言
- 什么是訪問者模式
- 訪問者模式示例
- 訪問者模式角色
- 訪問者模式適用場景
- 訪問者模式優缺點
- 總結
設計模式系列總覽
| 設計模式 | 飛機票 |
|---|---|
| 三大工廠模式 | 登機入口 |
| 策略模式 | 登機入口 |
| 委派模式 | 登機入口 |
| 模板方法模式 | 登機入口 |
| 觀察者模式 | 登機入口 |
| 單例模式 | 登機入口 |
| 原型模式 | 登機入口 |
| 代理模式 | 登機入口 |
| 裝飾者模式 | 登機入口 |
| 配接器模式 | 登機入口 |
| 建造者模式 | 登機入口 |
| 責任鏈模式 | 登機入口 |
| 享元模式 | 登機入口 |
| 組合模式 | 登機入口 |
| 門面模式 | 登機入口 |
| 橋接模式 | 登機入口 |
| 中介者模式 | 登機入口 |
| 迭代器模式 | 登機入口 |
| 狀態模式 | 登機入口 |
| 解釋器模式 | 登機入口 |
| 備忘錄模式 | 登機入口 |
| 命令模式 | 登機入口 |
| 訪問者模式 | 登機入口 |
| 軟體設計7大原則和設計模式總結 | 登機入口 |
前言
設計模式系列到這里已經是23種設計模式的最后一個設計模式了,訪問者模式也可以說是所有設計模式中最難的一種設計模式了,當然我們平常也很少會用到它,設計模式的作者是這么評價訪問者模式的:大多情況下,你并不需要使用訪問者模式,但是一旦需要使用它時,那就真的需要使用了,
什么是訪問者模式
訪問者模式(Vistor Pattern)是一種將資料結構與資料操作分離的的設計模式,是指封裝一些作用于某種資料結構中的各種元素的操作,它可以在不改變資料結構的前提下定義作用于這些元素的新操作,訪問者模式屬于行為型模式,
訪問者模式的基本思想是針對系統中擁有的某些固定型別的物件結構(元素),在其內提供一個accept()方法用來接受訪問者物件的訪問,不同的訪問者對同一元素的訪問內容不同,使得相同的元素集合可以產生不同的元素結果,accept()方法可以接受不同的訪問者物件,然后在內部將自己轉發到訪問者物件visit()方法內,
訪問者模式的核心思想是解耦資料結構與資料操作,使得對元素的操作具備優秀的擴展性,我們可以通過擴展不同的資料操作型別(訪問者)實作對相同元素的不同操作,
看了這一大堆的理論概念,是不是感覺有點暈,這個聽起來確實是有點抽象,別急,繼續往下看:
裝逼時刻又到了:Talk is cheap,Show you the code,我們通過一個例子來看看訪問者模式的寫法,
訪問者模式示例
我們以餐廳點菜的時候,顧客需要通過選單查看點菜為例子,在這個例子里面顧客就是訪問者,而菜品就是訪問者需要訪問的資訊,
1、首先建立一個菜品(食譜)介面,只定義一個接受訪問者來訪問的方法:
package com.zwx.design.pattern.visitor;
public interface IRecipe {
void accept(ICustomer customer);
}
接下來我們只列舉兩種視頻,一種紅燒肉,一種時蔬,所以需要兩個類:
package com.zwx.design.pattern.visitor;
public class Meat implements IRecipe {
@Override
public void accept(ICustomer customer) {
customer.visit(this);
}
public String getPrice(){
return "88元/份";
}
}
package com.zwx.design.pattern.visitor;
public class Cabbage implements IRecipe {
@Override
public void accept(ICustomer customer) {
customer.visit(this);
}
public String getPrice(){
return "44元/份";
}
}
這兩個類里面除了實作了accept方法,另外都提供了一個查看價格的方法,
3、這時候我們需要建立一個抽象的訪問者:
package com.zwx.design.pattern.visitor;
public interface ICustomer {
void visit(Meat meat);
void visit(Cabbage cabbage);
}
里面定義兩個方法名相同的方法,但是引數不同,引數對應元素,理論上我們上面有幾個菜品這里就需要定義幾個方法,也就是方法個數和要訪問元素的個數要相等,
4、接下來再建立一個顧客A的具體訪問者角色來實作抽象訪問者:
package com.zwx.design.pattern.visitor;
public class CustomerA implements ICustomer{
@Override
public void visit(Meat meat) {
System.out.println("肉類:" + meat.getPrice());
}
@Override
public void visit(Cabbage cabbage) {
System.out.println("時蔬:" + cabbage.getPrice());
}
}
現在訪問者有了,菜品也有了,那么還少一個選單,因為顧客需要通過選單去查看菜品資訊,然后點菜,所以我們還需要選單類來管理所有菜品,
5、新建一個選單類:
package com.zwx.design.pattern.visitor;
import java.util.ArrayList;
import java.util.List;
public class RestaurantMenu {
private List<IRecipe> recipeList = new ArrayList<>();
public RestaurantMenu(IRecipe recipe) {
recipeList.add(recipe);
}
public void addRecipe(IRecipe recipe){
recipeList.add(recipe);
}
public void display(ICustomer customer){
for (IRecipe recipe : recipeList){
recipe.accept(customer);
}
}
}
選單類里面通過一個list維護了所有菜品,然后通過display方法來展示所有菜品資訊,
6、接下來我們建立一個測驗類來測驗一下:
package com.zwx.design.pattern.visitor;
public class TestVistor {
public static void main(String[] args) {
IRecipe recipe = new Meat();
RestaurantMenu menu = new RestaurantMenu(recipe);
menu.addRecipe(new Cabbage());
menu.display(new CustomerA());
}
}
輸出如下資訊:
肉類:88元/份
時蔬:44元/份
這就是一個訪問者模式,上面因為訪問者肯定是經常變化的,但是我們只需要再增加顧客類就行了,非常方便,
如果大家是第一次接觸訪問者模式,可能會覺得示例還是有點抽象,那么我建議大家是對照例子自己多寫幾遍,慢慢就會找到感覺,
訪問者模式角色
從上面示例中,我們可以得出訪問者模式主要有5個角色:
- 抽象訪問者(Vistor):介面或者抽象類都可以(如示例中的ICustomer),這個角色主要是定義對具體元素的visit方法,引數就是具體元素,理論上來說方法數等于元素個數,所以說如果元素不穩定經常變化的話,那么訪問者是要一直修改的,并不適合使用訪問者模式,所以訪問者模式適用于元素結構比較穩定的場景,
- 具體訪問者(ConcreteVistor):實作對具體元素的訪問(如示例中的CustomerA),
- 抽象元素(Element):介面或者抽象類,定義了一個接受訪問者訪問的方法accept(如示例中的IRecipe),
- 具體元素(ConcreteElement):提供接受訪問者訪問的具體實作,通常都是采用visitor.visit()來實作(如示例中的Cabbage和Meat),
- 結構物件(ObjectStruture):用來維護元素,并提供一個方法來接受訪問者訪問所有的元素(如示例中的RestaurantMenu),
訪問者模式適用場景
訪問者模式適用于以下場景:
- 1、資料結構要穩定,但是作用于資料結構上的操作經常變化(如上面示例中如果菜譜經常發生變化,那么每次變化都要修改訪問者物件),
- 2、需要對不同資料型別(元素)進行操作,而不使用分支判斷具體型別的場景,
訪問者模式優缺點
優點:
- 1、解耦了資料結構和資料操作,使得操作集合可以獨立變化,
- 2、訪問者角色非常易于擴展,
- 3、每種角色各司其職,符合單一職責原則,
缺點 - 1、增加元素型別困難,如果元素型別變化就需要修改訪問者原始碼,違反了開閉原則,也不利于維護,
- 2、違背了依賴倒置原則,比如我們示例中的訪問者介面,定義的方法依賴的是具體元素而不是抽象元素,
總結
本文主要介紹了GoF23種設計模式中的最后一種設計模式,也是最難的一種設計模式,堪稱為設計模式的終極BOSS,通過了一個示例來示范了訪問者模式的寫法,最后歸納總結了訪問者模式的角色及其優缺點,
請關注我,和孤狼一起學習進步,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/199243.html
標籤:其他
