设计模式第19篇:访问者模式
一.訪問者模式介紹
定義:封裝一些作用于某種數據結構中的各元素的操作,它可以在不改變這個數據結構的前提下定義作用于這些元素的新的操作。
二.訪問者模式代碼用例
此處以購物車為例來說明,比如不同的商品有不同的結算方式,如果將商品的結算邏輯方法放在商品對象內部,則商品參加打折活動時又需要更改商品類,并且商品種類時非常多的,此時程序將變得不可維護。訪問者模式就是解決這個問題,將每個商品的結算邏輯抽取出來,放在訪問者(Visitor)類中,商品類中只需有接收訪問者的方法accept(Visitor visitor)即可。
1.商品類接口(抽象類也行,此處用接口)
interface ItemElement {int accept(ShoppingCartVisitor visitor); }2.商品類實例Book、Fruit
class Book implements ItemElement {private int price;private String isbnNumber;public Book(int cost, String isbn){this.price=cost;this.isbnNumber=isbn;}public int getPrice() {return price;}public String getIsbnNumber() {return isbnNumber;}@Overridepublic int accept(ShoppingCartVisitor visitor) {return visitor.visit(this);}}class Fruit implements ItemElement {private int pricePerKg;private int weight;private String name;public Fruit(int priceKg, int wt, String nm){this.pricePerKg=priceKg;this.weight=wt;this.name = nm;}public int getPricePerKg() {return pricePerKg;}public int getWeight() {return weight;}public String getName(){return this.name;}@Overridepublic int accept(ShoppingCartVisitor visitor) {return visitor.visit(this);}}3.訪問者接口ShoppingCarVisitor
interface ShoppingCartVisitor {int visit(Book book);int visit(Fruit fruit); }4.訪問者接口實現ShoppingCarVisitorImpl
class ShoppingCartVisitorImpl implements ShoppingCartVisitor {@Overridepublic int visit(Book book) {int cost=0;//apply 5$ discount if book price is greater than 50if(book.getPrice() > 50){cost = book.getPrice()-5;}else cost = book.getPrice();System.out.println("Book ISBN::"+book.getIsbnNumber() + " cost ="+cost);return cost;}@Overridepublic int visit(Fruit fruit) {int cost = fruit.getPricePerKg()*fruit.getWeight();System.out.println(fruit.getName() + " cost = "+cost);return cost;}}5.測試
public class ShoppingCartClient {public static void main(String[] args) {ItemElement[] items = new ItemElement[]{new Book(20, "1234"),new Book(100, "5678"),new Fruit(10, 2, "Banana"), new Fruit(5, 5, "Apple")};int total = calculatePrice(items);System.out.println("Total Cost = "+total);}private static int calculatePrice(ItemElement[] items) {ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl();int sum=0;for(ItemElement item : items){sum = sum + item.accept(visitor);}return sum;}}三.訪問者模式使用場景及優缺點
場景:1.對象結構比較穩定,但經常需要在此對象結構上定義新的操作。
2.需要對一個對象結構中的對象進行很多不同的且不相關的操作,而需要避免這些操作“污染”這些對象的類,也不希望在增加新操作時修改這些類。
優點:
1.使得數據結構和作用于結構上的操作解耦,使得操作集合可以獨立變化。
??? 2.添加新的操作或者說訪問者會非常容易。
??? 3.將對各個元素的一組操作集中在一個訪問者類當中。
??? 4.使得類層次結構不改變的情況下,可以針對各個層次做出不同的操作,而不影響類層次結構的完整性。
??? 5.可以跨越類層次結構,訪問不同層次的元素類,做出相應的操作。
缺點:
??? 1.增加新的元素會非常困難。
2.實現起來比較復雜,會增加系統的復雜性。
3.破壞封裝,如果將訪問行為放在各個元素中,則可以不暴露元素的內部結構和狀態,但使用訪問者模式的時候,為了讓訪問者能獲取到所關心的信息,元素類不得不暴露出一些內部的狀態和結構。
適用性:
?? 1.數據結構穩定,作用于數據結構的操作經常變化的時候。
?? 2.當一個數據結構中,一些元素類需要負責與其不相關的操作的時候,為了將這些操作分離出去,以減少這些元素類的職責時,可以使用訪問者模式。
?? 3.有時在對數據結構上的元素進行操作的時候,需要區分具體的類型,這時使用訪問者模式可以針對不同的類型,在訪問者類中定義不同的操作,從而去除掉類型判斷。
轉載于:https://www.cnblogs.com/quxiangxiangtiange/p/10305500.html
總結
以上是生活随笔為你收集整理的设计模式第19篇:访问者模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux日志 系统日志及分析
- 下一篇: Dynamics CRM - 如何修复