2012-02-11 78 views
1

https://stackoverflow.com/questions/9239445/sample-of-using-visitor-patternbefore-and-after訪問者模式使用

難道我理解Visitor模式的正確主要用途? 據我所知:

之前1

public class Main { 

    public static void main(String[] args) { 
     List<CompanyItem> items = new ArrayList<CompanyItem>(); 
     items.add(new Employee(10)); 
     items.add(new Employee(10.6)); 
     items.add(new Employee(15.9)); 
     items.add(new Manager(20.1)); 
     items.add(new Boss(30)); 

     double totalSalary = 0; 
     for(CompanyItem i:items){ 
      if (i instanceof Employee) { 
       totalSalary += ((Employee) i).getSalary(); 
      } else if (i instanceof Manager) { 
       totalSalary += ((Manager) i).getSalary(); 
       totalSalary += ((Manager) i).getBonusses(); 
      }else if (i instanceof Boss) { 
       totalSalary += ((Boss) i).getSalary(); 
       totalSalary += ((Boss) i).getAdditionalSalary(); 
      } 
     } 
     System.out.println(totalSalary); 
    } 

    interface CompanyItem { 
    } 

    static class Employee implements CompanyItem { 
     double salary; 

     public Employee(double salary) { 
      this.salary = salary; 
     } 

     public double getSalary() { 
      return salary; 
     } 
    } 

    static class Manager implements CompanyItem { 
     double salary, bonusses; 

     public Manager(double salary) { 
      this.salary = salary; 
      this.bonusses = 1.5 * salary; 
     } 

     public double getSalary() { 
      return salary; 
     } 

     public double getBonusses() { 
      return bonusses; 
     } 
    } 

    static class Boss implements CompanyItem { 
     double salary, addSalary; 

     public Boss(double salary) { 
      this.salary = salary; 
      this.addSalary = 3 * salary; 
     } 

     public double getSalary() { 
      return salary; 
     } 

     public double getAdditionalSalary() { 
      return addSalary; 
     } 
    } 
} 

之前2

public class Main3 { 

    public static void main(String[] args) { 
     List<CompanyItem> items = new ArrayList<CompanyItem>(); 
     items.add(new Employee(10)); 
     items.add(new Employee(10.6)); 
     items.add(new Employee(15.9)); 
     items.add(new Manager(20.1)); 
     items.add(new Boss(30)); 

     double totalSalary = 0; 
     for(CompanyItem i:items){ 
      totalSalary+=i.getSalary(); 
      totalSalary+=i.getBonusses(); 
      totalSalary+=i.getAdditionalSalary(); 
     } 
     System.out.println(totalSalary); 
    } 

    interface CompanyItem { 
     public double getSalary(); 
     public double getBonusses(); 
     public double getAdditionalSalary(); 
    } 

    static class Employee implements CompanyItem { 
     double salary; 

     public Employee(double salary) { 
      this.salary = salary; 
     } 

     public double getSalary() { 
      return salary; 
     } 

     @Override 
     public double getBonusses() { 
      return 0; 
     } 

     @Override 
     public double getAdditionalSalary() { 
      return 0; 
     } 
    } 

    static class Manager implements CompanyItem { 
     double salary, bonusses; 

     public Manager(double salary) { 
      this.salary = salary; 
      this.bonusses = 1.5 * salary; 
     } 

     public double getSalary() { 
      return salary; 
     } 

     public double getBonusses() { 
      return bonusses; 
     } 

     @Override 
     public double getAdditionalSalary() { 
      return 0; 
     } 
    } 

    static class Boss implements CompanyItem { 
     double salary, addSalary; 

     public Boss(double salary) { 
      this.salary = salary; 
      this.addSalary = 3 * salary; 
     } 

     public double getSalary() { 
      return salary; 
     } 

     public double getAdditionalSalary() { 
      return addSalary; 
     } 

     @Override 
     public double getBonusses() { 
      return 0; 
     } 
    } 
} 

後(使用訪問者模式???的)

public class Main1 { 

    public static void main(String[] args) { 
     List<CompanyItem> items = new ArrayList<CompanyItem>(); 
     items.add(new Employee(10)); 
     items.add(new Employee(10.6)); 
     items.add(new Employee(15.9)); 
     items.add(new Manager(20.1)); 
     items.add(new Boss(30)); 

     SalaryVisitor visitor = new SalaryVisitor(); 
     for(CompanyItem i:items){ 
      i.accept(visitor); 
     } 
     System.out.println(visitor.getTotalSalary()); 
    } 

    interface CompanyItem { 
     public void accept(Visitor v); 
    } 

    static class Employee implements CompanyItem { 
     double salary; 

     public Employee(double salary) { 
      this.salary = salary; 
     } 

     public double getSalary() { 
      return salary; 
     } 

     @Override 
     public void accept(Visitor v) { 
      v.visit(this); 
     } 
    } 

    static class Manager implements CompanyItem { 
     double salary,bonusses; 

     public Manager(double salary) { 
      this.salary = salary; 
      this.bonusses = 1.5 * salary; 
     } 

     public double getSalary() { 
      return salary; 
     } 

     public double getBonusses(){ 
      return bonusses; 
     } 

     @Override 
     public void accept(Visitor v) { 
      v.visit(this); 
     } 
    } 

    static class Boss implements CompanyItem { 
     double salary, addSalary; 

     public Boss(double salary) { 
      this.salary = salary; 
      this.addSalary = 3 * salary; 
     } 

     public double getSalary() { 
      return salary; 
     } 
     public double getAdditionalSalary(){ 
      return addSalary; 
     } 

     @Override 
     public void accept(Visitor v) { 
      v.visit(this); 
     } 
    } 

    interface Visitor { 
     public void visit(Employee e); 
     public void visit(Manager m); 
     public void visit(Boss b); 
    } 

    static class SalaryVisitor implements Visitor { 
     double totalSalary; 

     public SalaryVisitor() { 
      totalSalary = 0; 
     } 

     public double getTotalSalary(){ 
      return totalSalary; 
     } 

     @Override 
     public void visit(Employee e) { 
      totalSalary += e.getSalary();   
     } 

     @Override 
     public void visit(Manager m) { 
      totalSalary += (m.getSalary()+m.getBonusses()); 
     } 

     @Override 
     public void visit(Boss b) { 
      totalSalary += (b.getSalary()+b.getAdditionalSalary()); 
     } 
    } 
} 

我對不對?

+0

除了您個人的肯定之外,您還有疑問嗎?代碼的工作和行爲是否符合預期?這在代碼審查網站上可能會更好。 – duffymo 2012-02-11 13:26:12

+0

問題:我正確地寫了訪客模式嗎? – drifter 2012-02-11 13:28:50

+0

如果是,在這種情況下使用它的好例子? – drifter 2012-02-11 13:29:24

回答

7

從技術上講,示例實現訪問者模式就好了。但是這個例子並沒有提升訪客的優勢。主要觀點是:如果您期望幾個獨立的算法在相同的數據結構上工作而不改變數據結構,則實現訪問者模式開銷。

爲了提高你的榜樣,我建議這種變化:由其中一固定獎勵系統(例如100,000 $本年度)根據一些獎金所有經理之間的分配更換簡單的獎金制度每個經理都有積分。如果有兩個經理,一個有140點,另外60個點,那麼第一個獲得70k $,第二個30k $。

這可以讓你有幾個遊客:

  • 一個總結所有經理
  • 之一的全部獎勵積分使用來自前一步驟的總和分發經營者之間的獎金(10萬$) 。將此計算的個人獎金設置到Manager
  • Manager
  • 第三位訪客(PaydayVisitor)打印出員工,老闆和經理的支票,並返回所有已完成付款的總和。

編輯在這個代碼看起來像這樣(只略去了的getter/setter):

import java.util.ArrayList; 
import java.util.List; 

public class VisitorExample { 
    public static void main(String[] args) { 
     List<CompanyItem> items = new ArrayList<CompanyItem>(); 
     items.add(new Employee(10)); 
     items.add(new Employee(10.6)); 
     items.add(new Employee(15.9)); 
     items.add(new Manager(20.1, 140)); 
     items.add(new Manager(42.1, 70)); 
     items.add(new Boss(30, 10)); 

     // sum up all bonus points of all Managers 
     BonusPointVisitor bonusPointVisitor = new BonusPointVisitor(); 
     for(CompanyItem i: items) 
      i.accept(bonusPointVisitor); 

     // distribute given bonus sum among the managers 
     BonusDistributorVisitor bonusDistributorVisitor = 
      new BonusDistributorVisitor(bonusPointVisitor.totalBonusPoints, 100.0); 
     for(CompanyItem i: items) 
      i.accept(bonusDistributorVisitor); 

     // PayDay - print all checks 
     PrintCheckVisitor printCheckVisitor = new PrintCheckVisitor(); 
     for(CompanyItem i: items) 
      i.accept(printCheckVisitor); 
     System.out.println("total money spent this month: "+printCheckVisitor.totalPayments); 
    } 

    interface CompanyItem { 
     public void accept(Visitor v); 
    } 

    interface Visitor { 
     public void visit(Employee e); 
     public void visit(Manager m); 
     public void visit(Boss b); 
    } 

    static class Employee implements CompanyItem { 
     double salary; 

     public Employee(double salary) { 
      this.salary = salary; 
     } 

     @Override 
     public void accept(Visitor v) { 
      v.visit(this); 
     } 
    } 

    static class Manager implements CompanyItem { 
     double salary, bonusPoints, bonus; 

     public Manager(double salary, double bonusPoints) { 
      this.salary = salary; 
      this.bonusPoints = bonusPoints; 
      this.bonus = 0; 
     } 

     @Override 
     public void accept(Visitor v) { 
      v.visit(this); 
     } 
    } 

    static class Boss implements CompanyItem { 
     double salary, addSalary; 

     public Boss(double salary, double addSalary) { 
      this.salary = salary; 
      this.addSalary = addSalary; 
     } 

     @Override 
     public void accept(Visitor v) { 
      v.visit(this); 
     } 
    } 

    static class BonusPointVisitor implements Visitor { 
     double totalBonusPoints = 0d; 

     @Override 
     public void visit(Employee e) { 
     } 

     @Override 
     public void visit(Manager m) { 
      totalBonusPoints += m.bonusPoints; 
     } 

     @Override 
     public void visit(Boss b) { 
     } 
    } 


    static class BonusDistributorVisitor implements Visitor { 
     double totalBonusPoints, totalBonus; 

     public BonusDistributorVisitor(double totalBonusPoints, double totalBonus) { 
      this.totalBonusPoints = totalBonusPoints; 
      this.totalBonus = totalBonus; 
     } 

     @Override 
     public void visit(Employee e) { 
     } 

     @Override 
     public void visit(Manager m) { 
      m.bonus = (m.bonusPoints/totalBonusPoints) * totalBonus; 
     } 

     @Override 
     public void visit(Boss b) { 
     } 
    } 

    static class PrintCheckVisitor implements Visitor { 
     double totalPayments = 0; 

     @Override 
     public void visit(Employee e) { 
      advisePayment(e.salary); 
     } 

     @Override 
     public void visit(Manager m) { 
      advisePayment(m.salary + m.bonus); 
     } 

     @Override 
     public void visit(Boss b) { 
      advisePayment(b.salary + b.addSalary); 
     } 

     private void advisePayment(double amount){ 
      System.out.println("pay "+amount+" credits"); 
      totalPayments += amount; 
     } 
    } 
} 

留下了什麼做:給每個項目一些打印的名稱爲advisePayment使用。

+0

如果你有空閒時間,你可以向幾位參觀者展示以上描述的例子。我遇到了一些困難。 在此先感謝。 – drifter 2012-02-11 15:02:38

+0

@drifter:你在這裏。 – 2012-02-11 15:28:02

+0

感謝您的回覆。它幫助我很好。 – drifter 2012-02-11 15:32:33

1

看起來不錯。但是在這種情況下,我只是使用多態而沒有任何模式。只要讓CompanyItem有一個TotalSalary函數,你就可以使用它。如果您有不同的訪問者,訪問者將會很有用。

1

是的,這是Visitor模式的正確用法,因爲它爲每個類做了不同的事情。但請記住,當您使用Visitor模式時,您應該覆蓋實現相應界面的所有類。

1

這取決於您是否擁有SalaryVisitor以外的其他類型的訪問者。如果你沒有任何其他訪問者,你應該避免訪問者模式:這是一個非常「重」的模式,在這裏似乎並不需要。

編輯
我原來說我喜歡之前,但AH的評論之後,也許你實際上可以創建一個名爲PaidByCompany(壞名新的子類,但我想不出什麼好現在),它有一個方法getTotalCompensation()。 之前1工作正常。

+0

'2之前'是很不好的恕我直言,因爲每個孩子班級都包含不屬於那裏的東西:經理有AddSalary,老闆有獎金,員工都有。爲了什麼? – 2012-02-11 14:17:53

+0

@ A.H。我改變了我的答案。然而,對於一個真正的公司,我可能想爲員工獲得獎金和額外薪資,因爲他們可能真的會得到一些。我明白,在這個例子的背景下,他們永遠不會,所以我改變了我的答案。確實沒有「鬼」成員和方法更清潔。 – toto2 2012-02-11 14:34:34

+0

這確實是找到好例子的問題。 – 2012-02-11 14:37:05