https://stackoverflow.com/questions/9239445/sample-of-using-visitor-patternbefore-and-after
Do I understand correctly main purposes of Visitor pattern?
As I understand:
Before 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;
}
}
}
Before 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;
}
}
}
After(with using of Visitor pattern ???)
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());
}
}
}
Am I right?
Technically the example implements the visitor pattern just fine. But the example does not promote the advantage(s) of a visitor. The main point is: Implement the visitor pattern overhead if you expect several independent algorithms working on the same data structure – without changing the structure of the data.
In order to enhance your example I propose this changes: Replace the simple bonus system by a system where a fixed bonus (e.g. 100k$ in the current year) is distributed between all managers according to some bonus points each manager has. If there are two managers, one has 140 points, the other 60 points, then the first one gets 70k$, the second 30k$.
This allows you to have several visitors:
ManagerPaydayVisitor) prints out the checks for employees, bosses and managers and also returns a sum of all payments done.EDIT In code this would look like this (getter/setter omitted for brevity only):
What is left to be done: Give each item some printable name for usage in
advisePayment.