2012-02-11 162 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