设计模式23-访问者模式

1.场景问题解决

1.1 场景描述

雇员管理系统遇到的问题:
需要添加一些新的操作功能

1.2 OO设计

  • oo 该package为oo用法
    • Employee 为雇员信息
    • Employees 为对每个雇员信息操作类
    • MainOOTest 为测试类
public class Employee {
	private String name;
	private float income;
	private int vacationDays;
	private int degree;

	public Employee(String name, float income, int vacationDays, int degree) {
		this.name = name;
		this.income = income;
		this.vacationDays = vacationDays;
		this.degree = degree;
	}

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

	public String getName() {
		return name;
	}

	public void setIncome(float income) {
		this.income = income;
	}

	public float getIncome() {
		return income;
	}

	public void setVacationDays(int vacationDays) {
		this.vacationDays = vacationDays;
	}

	public int getVacationDays() {
		return vacationDays;
	}

	public void setDegree(int degree) {
		this.degree = degree;
	}

	public int getDegree() {
		return degree;
	}

}

public class Employees {
	private HashMap employees;

	public Employees() {
		employees = new HashMap();
	}

	public void Attach(Employee employee) {
		employees.put(employee.getName(), employee);
	}

	public void Detach(Employee employee) {
		employees.remove(employee);
	}

	public Employee getEmployee(String name) {
		return employees.get(name);
	}

	public void getCompensation() {
		for (Employee employee : employees.values()) {
			System.out.println(employee.getName()+ "'s Compensation is "+ (employee.getDegree()* employee.getVacationDays() * 100));
		}
	}
}




public class MainOOTest {
	public static void main(String[] args) {
		Employees mEmployees = new Employees();
		mEmployees.Attach(new Employee("Tom", 4500, 8, 1));
		mEmployees.Attach(new Employee("Jerry", 6500, 10, 2));
		mEmployees.Attach(new Employee("Jack", 9600, 12, 3));
		mEmployees.getCompensation();
	}
}

1.3 需求变动

1.4 带来问题

2.用设计模式改进

2.1 分析

2.2 重新设计

[外链图片转存失败(img-qKwUrloS-1568992255618)(https://raw.githubusercontent.com/bobshute/public/master/imgs/csdn/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/23%E8%AE%BF%E9%97%AE%E8%80%85%E6%A8%A1%E5%BC%8F-2.png)]

2.3 源码

  • visitor 该package 为访问者模式优化后

    • 1)Element 为元素抽象类,其中有 accept(Visitor visitor)
    • 2)Employee 为雇员信息 extends Element,实现了accept(Visitor visitor),触发将自己传给visitor.visit(this)[ 5) ];
    • 3)Employees 为对每个雇员信息操作类,
      会发起调出发每个Employee.accept(visitor);
    • 4)Visitor 为一个接口
      根据需要实现该接口:
    • 5)CompensationVisitor
      该访问者实现了visit,并对传入的Element单独处理.
    • 6)MainOOTest 为测试类
public interface Visitor {
	abstract public void visit(Element element);
}



public abstract class Element {
	abstract public void accept(Visitor visitor);
}




public class Employee extends Element {

	private String name;
	private float income;
	private int vacationDays;
	private int degree;

	public Employee(String name, float income, int vacationDays, int degree) {
		this.name = name;
		this.income = income;
		this.vacationDays = vacationDays;
		this.degree = degree;
	}

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

	public String getName() {
		return name;
	}

	public void setIncome(float income) {
		this.income = income;
	}

	public float getIncome() {
		return income;
	}

	public void setVacationDays(int vacationDays) {
		this.vacationDays = vacationDays;
	}

	public int getVacationDays() {
		return vacationDays;
	}

	public void setDegree(int degree) {
		this.degree = degree;
	}

	public int getDegree() {
		return degree;
	}

	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}

}


public class Employees {
	private HashMap employees;

	public Employees() {
		employees = new HashMap();
	}

	public void Attach(Employee employee) {
		employees.put(employee.getName(), employee);
	}

	public void Detach(Employee employee) {
		employees.remove(employee);
	}

	public Employee getEmployee(String name) {
		return employees.get(name);
	}

	public void accept(Visitor visitor) {
		for (Employee e : employees.values()) {
			e.accept(visitor);
		}
	}
}




public class CompensationVisitor implements Visitor {

	@Override
	public void visit(Element element) {
		Employee employee = ((Employee) element);
		System.out.println(employee.getName() + "'s Compensation is "+ (employee.getDegree() * employee.getVacationDays() * 10));
	}

}



public class MainVisitorTest {
	public static void main(String[] args) {
		Employees mEmployees = new Employees();

		mEmployees.Attach(new Employee("Tom", 4500, 8, 1));
		mEmployees.Attach(new Employee("Jerry", 6500, 10, 2));
		mEmployees.Attach(new Employee("Jack", 9600, 12, 3));

		mEmployees.accept(new CompensationVisitor());
	}
}

3.设计模式总结

3.1 定义

访问者模式:对于一组对象,在不改变数据结构的前提下,增加作用于这些结构元素新的功能。
适用于数据结构相对稳定,它把数据结构和作用于其上的操作解耦,使得操作集合可以相对自由地演化。

3.2 分析思路

设计模式23-访问者模式_第1张图片

3.3 优缺点

  • 优点:
    符合单一职责原则
    扩展性良好
    有益于系统的管理和维护
  • 缺点:
    增加新的元素类变得很困难
    破坏封装性

4. 设计模式使用场景及注意

4.1 使用场景

  • 如果一个系统有比较稳定的数据结构,又有经常变化的功能需求,那么访问者模式就是比较合适的

4.2 注意

  • 与迭代器的关系

5.参考文章

内容总计于HeadFirst设计模式及相关视频

你可能感兴趣的:(总结,架构设计)