https://stackoverflow.com/questions/9239445/sample-of-using-visitor-patternbefore-and-after
我是否正确理解访客模式的主要目的?据我所知:
在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());
}
}
}我说的对吗?
发布于 2012-02-11 14:25:23
从技术上讲,该示例实现了访问者模式。但是这个例子并没有促进游客的优势。要点是:如果您期望几个独立的算法在相同的数据结构上工作-而不更改数据的结构,则实现访问者模式开销。
为了加强您的示例,我建议进行以下更改:将简单的奖金系统替换为固定奖金(例如,本年度的100 k美元)在所有经理之间按照每个经理的一些奖金点数分配。如果有两位经理,一位有140分,另一位有60分,那么第一位得到70k美元,第二位得到30k美元。
这允许您有几个访问者:
ManagerPaydayVisitor)的字段中,打印出员工、老板和经理的支票,并返回所有已支付款项的总和。在代码中编辑(只为简洁起见省略了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中使用。
发布于 2012-02-11 13:39:14
看起来挺好的。但是,在这种情况下,我只使用多态性而不使用任何模式。只要让CompanyItem有一个TotalSalary函数,就可以使用它。如果你有不同的访客,访客会很有用。
发布于 2012-02-11 13:39:29
是的,它是访问者模式的正确用法,因为它为每个类做了不同的事情。但是请记住,当您使用Visitor模式时,您应该涵盖实现相应接口的所有类。
https://stackoverflow.com/questions/9240551
复制相似问题