Visitor Pattern - Company Hierarchy

a schema definition

Visitor Mode: It represents an operation that acts on each element in an object structure, which enables users to define new operations that act on these elements without changing the element classes.

 

Two-mode example

1 Pattern Analysis

We use the corporate hierarchy to illustrate this pattern.


 

2 visitor pattern static class diagram



 

3 Code Examples

3.1 Abstract employee-Staff

package com.demo.structure;

import com.demo.visitor.IVisitor;

/**
 * Abstract employee class
 *
 * @author
 *
 */
public abstract class Staff {
	// employee ID
	protected String no;
	// employee name
	protected String name;
	// Position
	protected String position;
	// salary
	protected float salary;

	// private property length string
	private int length;

	// Construction method
	public Staff(String no, String name, String position, float salary) {
		this.no = no;
		this.name = name;
		this.position = position;
		this.salary = salary;

		// Calculate the total length in bytes
		this.length += (no == null || "".equals(no.trim())) ? 0
				: no.getBytes().length;
		this.length += (name == null || "".equals(name.trim())) ? 0 : name
				.getBytes().length;
		this.length += (position == null || "".equals(position.trim())) ? 0
				: position.getBytes().length;
		this.length += String.valueOf(salary).getBytes().length;

	}

	// Get basic user information
	public void printUserBaseInfo() {
		System.out.println("-|" + this.no + " " + this.name + " "
				+ this.position + " " + this.salary);
	}

	// add employee information
	public abstract void add(Staff staff);

	// delete employee
	public abstract Staff remove(String no);

	// receive the visitor object
	public abstract void accept(IVisitor visitor);

	public String getNo() {
		return no;
	}

	public void setNo(String no) {
		this.no = no;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPosition() {
		return position;
	}

	public void setPosition(String position) {
		this.position = position;
	}

	public float getSalary() {
		return salary;
	}

	public void setSalary(float salary) {
		this.salary = salary;
	}

}

3.2 Manager-Manager

package com.demo.structure;

import java.util.ArrayList;

import com.demo.visitor.IVisitor;

/**
 * Managers (people with other employees)
 *
 * @author
 *
 */
public class Manager extends Staff {

	// store employee information
	private final ArrayList<Staff> arrayList = new ArrayList<Staff>();

	// Construction method
	public Manager(String no, String name, String position, float salary) {
		super(no, name, position, salary);
	}

	/**
	 * Add an employee
	 */
	@Override
	public void add(Staff staff) {
		this.arrayList.add(staff);
	}

	/**
	 * Delete employee information
	 */
	@Override
	public Staff remove(String no) {
		Staff staff = null;
		if (no != null && !"".equals(no.trim())) {
			for (int i = 0; i < this.arrayList.size(); i++) {
				if (this.arrayList.get(i) == null) {
					continue;
				}

				if (no.equals(this.arrayList.get(i).getNo())) {
					staff = this.arrayList.remove(i);
					break;
				}
			}
		}
		return staff;
	}

	// receive the visitor object
	@Override
	public void accept(IVisitor visitor) {

		// access itself
		visitor.visit(this);
		// Traverse each element object in the list list and receive the visitor object
		for (int i = 0; i < this.arrayList.size(); i++) {
			if (this.arrayList.get(i) == null) {
				continue;
			}

			// receive the visitor object
			this.arrayList.get(i).accept(visitor);
		}
	}
}

3.3 Ordinary employees - Employees

package com.demo.structure;

import com.demo.visitor.IVisitor;

/**
 * Ordinary employees (people who really work)
 *
 * @author
 *
 */
public class Employees extends Staff
{
	// Construction method
	public Employees(String no, String name, String position, float salary)
	{
		super(no, name, position, salary);
	}

	/**
	 * Add employee information
	 */
	@Override
	public void add(Staff staff)
	{
		return;
	}

	/**
	 * Delete employee information
	 */
	@Override
	public Staff remove(String no)
	{
		// directly return null
		return null;
	}

	// receive the visitor object
	public void accept(IVisitor visitor)
	{
		visitor.visit(this);
	}
}

3.4 Visitor interface - IVisitor

package com.demo.visitor;

import com.demo.structure.Employees;
import com.demo.structure.Manager;

/**
 * Visitor interface
 *
 * @author
 *
 */
public interface IVisitor {
	// access manager
	public void visit(Manager manager);

	// access ordinary employees
	public void visit(Employees employees);
}

3.5 Employee Basic Information Visitor - PrintBaseInfoVistor

package com.demo.visitor;

import com.demo.structure.Employees;
import com.demo.structure.Manager;

/**
 * Print basic information for visitors
 *
 * @author
 *
 */
public class PrintBaseInfoVisitor implements IVisitor {

	/**
	 * access manager object
	 */
	public void visit(Manager manager) {
		System.out.print("- manager: ");
		manager.printUserBaseInfo();
	}

	/**
	 * Access common employee objects
	 */
	public void visit(Employees employees) {
		System.out.print("- General staff: ");
		employees.printUserBaseInfo();
	}

}

3.6 Create a visitor interface for employee salary statistics - ISalaryVistor

package com.demo.visitor;

/**
 * Calculate salary for visitors
 *
 * @author
 *
 */
public interface ISalaryVisitor extends IVisitor {
	// Statistics manager salary
	public void printManagerTotalSalary();

	// Statistics of general employee salary
	public void printEmployeesTotalSalary();

	// Calculate the salary of all employees
	public void printTotalSalary();

}

3.7 Statistical Employee Salary Visitor Implementation of a SalaryVistor

package com.demo.visitor;

import com.demo.structure.Employees;
import com.demo.structure.Manager;

/**
 * Calculate salary visitor specific implementation
 *
 * @author
 *
 */

public class SalaryVisitor implements ISalaryVisitor {
	// total manager salary
	private float managerSalary;
	// The total salary of ordinary employees
	private float employeesSalary;

	public SalaryVisitor() {
		managerSalary = 0;
		employeesSalary = 0;
	}

	// access manager
	public void visit(Manager manager) {
		managerSalary += manager.getSalary();
	}

	// access ordinary employees
	public void visit(Employees employees) {
		employeesSalary += employees.getSalary();
	}

	// Statistics of general employee salary
	public void printEmployeesTotalSalary() {
		System.out.println("General employee salary sum: " + employeesSalary);
	}

	// Statistics manager salary
	public void printManagerTotalSalary() {
		System.out.println("Manager Salary Sum: " + managerSalary);

	}

	// Calculate the salary of all employees
	public void printTotalSalary() {
		System.out.println("Employee Salary Sum: " + (managerSalary + employeesSalary));

	}

}

3.8 Client Test One Client

package com.demo;

import com.demo.structure.Employees;
import com.demo.structure.Manager;
import com.demo.structure.Staff;
import com.demo.visitor.PrintBaseInfoVisitor;
import com.demo.visitor.SalaryVisitor;

/**
 * Main application
 *
 * @author
 *
 */
public class Client {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// Company CEO
		Staff boss = new Manager("1", "大老板", "CEO", 100000);
		/**
		 * There are several department managers under the CEO
		 */
		// Finance Manager
		Staff financeManager = new Manager("11", "Mr. Zhang", "Finance Manager", 60000);

		// HR manager
		Staff personnelManager = new Manager("12", "Mr. Wang", "Personnel Manager", 60000);

		// technical manager
		Staff technicalManager = new Manager("13", "Mr. Chen", "Technical Manager", 60000);
		/**
		 * The technical department also has assistants and several supervisors
		 */
		// technical department assistant
		Staff deptAssistant = new Manager("1301", "Assistant Wang", "Dept Assistant", 20000);
		// Head of technical department 1
		Staff deptManager1 = new Manager("1302", "Supervisor 1", "Technical Supervisor", 30000);
		/**
		 * There are also software engineers under the technical director deptManager1 (the one who does the final work)
		 */
		Staff softwareEngineer1 = new Employees("1302001", "Zhang San", "Software Engineer", 5000);
		Staff softwareEngineer2 = new Employees("1302002", "Li Si", "Software Engineer", 5500);
		Staff softwareEngineer3 = new Employees("1302003", "Wang Wu", "Software Engineer", 4500);
		// Add employee information for technical supervisor 1
		deptManager1.add(softwareEngineer1);
		deptManager1.add(softwareEngineer2);
		deptManager1.add(softwareEngineer3);

		// Head of technical department 2
		Staff deptManager2 = new Manager("1303", "Supervisor 2", "Technical Supervisor", 30000);

		// Added for Technical Manager: Department Assistant, Technical Supervisor 1 and Technical Supervisor 2
		technicalManager.add(deptAssistant);
		technicalManager.add(deptManager1);
		technicalManager.add(deptManager2);

		// Marketing Manager
		Staff marketingManager = new Manager("14", "Mr. Wu", "Marketing Manager", 60000);

		// Added for CEO: Finance Manager, HR Manager, Technical Manager and Marketing Manager
		boss.add(financeManager);
		boss.add(personnelManager);
		boss.add(technicalManager);
		boss.add(marketingManager);

		// print CEO info
		// boss.printUserBaseInfo();
		// Print the employee information of the CEO
		boss.accept(new PrintBaseInfoVisitor());

		/**
		 * Statistics on employee salary
		 */
		// Create a statistical employee salary visitor
		SalaryVisitor visitor = new SalaryVisitor();
		// Let the big boss accept the visitor
		boss.accept(visitor);
		// manager salary statistics
		visitor.printManagerTotalSalary();
		// General employee salary statistics
		visitor.printEmployeesTotalSalary();
		// All employee salary statistics
		visitor.printTotalSalary ();
	}
}

4 Running results

- Manager: -|1 Big Boss CEO 100000.0

- Manager: -|11 Zhang, Manager of General Finance Department 60000.0

- Manager: -|12 Mr. Wang, Manager of Personnel Department 60000.0

- Manager: -|13 General Manager Chen Technology Department 60000.0

- Manager: -|1301 Assistant Wang Department Assistant 20000.0

- Manager: -|1302 Supervisor 1 Technical Supervisor 30000.0

- General staff:-|1302001 Zhang San Software Engineer 5000.0

- General staff:-|1302002 Li Si software engineer 5500.0

- General staff:-|1302003 Wang Wu Software Engineer 4500.0

- Manager: -|1303 Supervisor 2 Technical Supervisor 30000.0

- Manager: -|14 Wu, Manager of Marketing Department 60000.0

Total salary of managers: 420000.0

General employee salary sum: 15000.0

Total employee salary: 435000.0

 

Three principles of pattern design

1 "Open-close" principle

2 Single Responsibility Principle

 

Four use cases

1 If there are many objects of different types in an object structure, they have different interfaces, and you want to implement some operations that depend on concrete classes on these different objects.

2 Need to perform many different and unrelated operations on objects in an object structure, and want to avoid having those operations associated with the classes of those objects. The visitor pattern makes it possible to group related operations together and define them in a single class.

3 When the object structure is shared by many applications, use the visitor pattern to let each application contain only the operations it needs to use.

4 The class that defines the structure of an object rarely changes, but it is often necessary to define new operations in this structure.

 

Five visitor pattern static class diagram



 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326608653&siteId=291194637