首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >访客模式使用

访客模式使用
EN

Stack Overflow用户
提问于 2012-02-11 13:22:22
回答 4查看 1.2K关注 0票数 1

https://stackoverflow.com/questions/9239445/sample-of-using-visitor-patternbefore-and-after

我是否正确理解访客模式的主要目的?据我所知:

在1之前

代码语言:javascript
复制
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之前

代码语言:javascript
复制
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;
        }
    }
}

后(使用访问者模式?)

代码语言:javascript
复制
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()); 
        }
    }
}

我说的对吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-02-11 14:25:23

从技术上讲,该示例实现了访问者模式。但是这个例子并没有促进游客的优势。要点是:如果您期望几个独立的算法在相同的数据结构上工作-而不更改数据的结构,则实现访问者模式开销。

为了加强您的示例,我建议进行以下更改:将简单的奖金系统替换为固定奖金(例如,本年度的100 k美元)在所有经理之间按照每个经理的一些奖金点数分配。如果有两位经理,一位有140分,另一位有60分,那么第一位得到70k美元,第二位得到30k美元。

这允许您有几个访问者:

  • One总结所有经理的所有奖金点,
  • One在经理之间分配奖金(100 K美元),使用上一步的总和。将计算出来的个人奖金设置到Manager
  • A第三访问者(PaydayVisitor)的字段中,打印出员工、老板和经理的支票,并返回所有已支付款项的总和。

在代码中编辑(只为简洁起见省略了getter/setter):

代码语言:javascript
复制
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中使用。

票数 8
EN

Stack Overflow用户

发布于 2012-02-11 13:39:14

看起来挺好的。但是,在这种情况下,我只使用多态性而不使用任何模式。只要让CompanyItem有一个TotalSalary函数,就可以使用它。如果你有不同的访客,访客会很有用。

票数 1
EN

Stack Overflow用户

发布于 2012-02-11 13:39:29

是的,它是访问者模式的正确用法,因为它为每个类做了不同的事情。但是请记住,当您使用Visitor模式时,您应该涵盖实现相应接口的所有类。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9240551

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档