程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 詳解Java設計形式編程中的拜訪者形式

詳解Java設計形式編程中的拜訪者形式

編輯:關於JAVA

詳解Java設計形式編程中的拜訪者形式。本站提示廣大學習愛好者:(詳解Java設計形式編程中的拜訪者形式)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解Java設計形式編程中的拜訪者形式正文


界說:封裝某些感化於某種數據構造中各元素的操作,它可以在不轉變數據構造的條件下界說感化於這些元素的新的操作。
類型:行動類形式
類圖:

例子:
例如,思慮一下添加分歧類型商品的購物車,當點擊結算的時刻,它盤算出一切分歧商品需付的費用。如今,盤算邏輯即為盤算這些分歧類型商品的價錢。或許說經由過程拜訪者形式我們把此邏輯轉移到了別的一個類下面。讓我們完成這個拜訪者形式的例子。

為了完成拜訪者形式,最早須要做的是創立可以或許被添加到購物車中代表分歧類型商品(itemElement)的類。

ItemElement.java

package com.journaldev.design.visitor;

public interface ItemElement {

 public int accept(ShoppingCartVisitor visitor);
}

留意,accept辦法接收拜訪者作為參數。固然這兒還有其他的一些辦法來指定具體的商品,但為了簡化,此處沒用過量的斟酌細節,只存眷拜訪者形式。

如今創立一些分歧商品的實體類。

Book.java

package com.journaldev.design.visitor;

public 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;
 }

 @Override
 public int accept(ShoppingCartVisitor visitor) {
 return visitor.visit(this);
 }

}

Fruit.java

package com.journaldev.design.visitor;

public 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;
 }

 @Override
 public int accept(ShoppingCartVisitor visitor) {
 return visitor.visit(this);
 }

}

留意,accept()辦法的完成是在實體類中,它挪用拜訪者的visit()辦法傳遞以後類對象作為本身的參數。
此處針對分歧類型的商品所應用的visit()辦法將會在拜訪者接口的實體類中被完成。

ShoppingCartVisitor.java

package com.journaldev.design.visitor;

public interface ShoppingCartVisitor {

 int visit(Book book);
 int visit(Fruit fruit);
}

如今將完成拜訪者接口和每種商品本身盤算本身費用的邏輯。

ShoppingCartVisitorImpl.java

package com.journaldev.design.visitor;

public class ShoppingCartVisitorImpl implements ShoppingCartVisitor {

 @Override
 public int visit(Book book) {
 int cost=0;
 //apply 5$ discount if book price is greater than 50
 if(book.getPrice() > 50){
  cost = book.getPrice()-5;
 }else cost = book.getPrice();
 System.out.println("Book ISBN::"+book.getIsbnNumber() + " cost ="+cost);
 return cost;
 }

 @Override
 public int visit(Fruit fruit) {
 int cost = fruit.getPricePerKg()*fruit.getWeight();
 System.out.println(fruit.getName() + " cost = "+cost);
 return cost;
 }

}

如今看一看在法式中若何應用它。

ShoppingCartClient.java

package com.journaldev.design.visitor;

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;
 }

}

當運轉上述法式是,我們獲得以下輸入。

Book ISBN::1234 cost =20
Book ISBN::5678 cost =95
Banana cost = 20
Apple cost = 25
Total Cost = 160

請留意,此處的完成,似乎accept()辦法關於一切商品是雷同的,然則他也能夠分歧。例如,假如商品為空它能停止邏輯檢討其實不再挪用visit()辦法。
拜訪者形式的長處:
相符單一職責准繩:但凡實用拜訪者形式的場景中,元素類中須要封裝在拜訪者中的操作一定是與元素類自己關系不年夜且是易變的操作,應用拜訪者形式一方面相符單一職責准繩,另外一方面,由於被封裝的操作平日來講都是易變的,所以當產生變更時,便可以在不轉變元素類自己的條件下,完成對變更部門的擴大。
擴大性優越:元素類可以經由過程接收分歧的拜訪者來完成對分歧操作的擴大。
 拜訪者形式的實用場景:
       假設一個對象中存在著一些與本對象不相關(或許關系較弱)的操作,為了不這些操作淨化這個對象,則可使用拜訪者形式來把這些操作封裝到拜訪者中去。
       假設一組對象中,存在著類似的操作,為了不湧現年夜量反復的代碼,也能夠將這些反復的操作封裝到拜訪者中去。
       然則,拜訪者形式其實不是那末完善,它也有著致命的缺點:增長新的元素類比擬艱苦。經由過程拜訪者形式的代碼可以看到,在拜訪者類中,每個元素類都有它對應的處置辦法,也就是說,每增長一個元素類都須要修正拜訪者類(也包含拜訪者類的子類或許完成類),修正起來相當費事。也就是說,在元素類數量不肯定的情形下,應當慎用拜訪者形式。所以,拜訪者形式比擬實用於對已有功效的重構,好比說,一個項目標根本功效曾經肯定上去,元素類的數據曾經根本肯定上去不會變了,會變的只是這些元素內的相干操作,這時候候,我們可使用拜訪者形式對原本的代碼停止重構一遍,如許一來,便可以在不修正各個元素類的情形下,對原有功效停止修正。
 
總結:
       正如《設計形式》的作者GoF對拜訪者形式的描寫:年夜多半情形下,你並須要應用拜訪者形式,然則當你一旦須要應用它時,那你就是真的須要它了。固然這只是針對真實的年夜牛而言。在實際情形下(至多是我所處的情況傍邊),許多人常常陷溺於設計形式,他們應用一種設計形式時,歷來不去賣力斟酌所應用的形式能否合適這類場景,而常常只是想展現一下本身對面向對象設計的駕御才能。編程時有這類心思,常常會產生濫用設計形式的情形。所以,在進修設計形式時,必定要懂得形式的實用性。必需做到應用一種形式是由於懂得它的長處,不應用一種形式是由於懂得它的弊病;而不是應用一種形式是由於不懂得它的弊病,不應用一種形式是由於不懂得它的長處。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved