Swift設計模式 – 訪問者模式(Visitor Pattern)

今天Stone City的市長帶著Stone Mall的店長來找我們,他們希望也可以做一個像WoodMall一樣的系統,可以很快地計算出每個Shop帶給Mall的營收狀況。

目前Stone Mall與Wood Mall是合作關係,所以可以直接拿到Wood Mall的Source Code來參考:

我們看到每一個店家都會有一個專有的類別,可以用來存放各自的Revenue狀況。

而WoodMall本身也會有一個類別,可以用來加入店家以及計算各店家帶給自己的收入。

其中WoodMall會向各店家抽取利潤的比例為:

  • WoodComputerShop  5%
  • WoodBicycleShop       15%
  • WoodFurnitureShop  25%

WoodMall通過shops來管理店家,calculateRevenue方法來計算從各店家抽成的費用。

我們發現這樣的系統雖然目前來看是可以使用的,但如果有shop推出或者加入WoodMall時,這時候calculateRevenue方法又要做不少修改,
而且這一堆條件語句也會有越來越長的可能。

那麼有什麼更好的辦法呢?


訪問者模式(Visitor Pattern)

  • 使用訪問者模式可以在不修改類的source code和不創建新的子類情況下進行擴展類的行為。
  • 和「策略模式」不同的是,訪問者模式的使用對象是「各類對象的集合」。

訪問者模式通過「將操作對象的算法分離到一個單獨的對象」,並在該對象中定義能夠處理集合中各類對象的方法來解決上面我們提到的問題。

首先我們在Visitor.swift中定義兩個協議

StoneShop協議定義了accept方法,Visitor協議定義了幾個visit方法,每個方法對應一種商店。這幾個方法是實現「雙分派」的關鍵。

StoneShop協議

我們讓所有的店家都遵循StoneShop協議,他們都會根據協議實現accept方法

StoneMall新增一個accept方法

accept方法用來接收一個visitor對象,並調用對象集合中的每個對象的accept方法。

創建訪問者類

訪問者類負責處理shop對象集合。

使用了「雙分派」之後,就可以直接訪問某個類型對象的屬性了,不用在做類型的判斷。

最後組件調用的方式是這樣的:

輸出的結果:


如果有需要,可以到github上看上面提到的「訪問者模式例子

 

 

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *