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<String, Employee> employees;
public Employees() {
employees = new HashMap<String, Employee>();
}
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);
- 3)Employees 为对每个雇员信息操作类,
-
- 4)Visitor 为一个接口
根据需要实现该接口:
- 4)Visitor 为一个接口
-
- 5)CompensationVisitor
该访问者实现了visit,并对传入的Element单独处理.
- 5)CompensationVisitor
-
- 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<String, Employee> 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 分析思路
3.3 优缺点
- 优点:
符合单一职责原则
扩展性良好
有益于系统的管理和维护 - 缺点:
增加新的元素类变得很困难
破坏封装性
4. 设计模式使用场景及注意
4.1 使用场景
- 如果一个系统有比较稳定的数据结构,又有经常变化的功能需求,那么访问者模式就是比较合适的
4.2 注意
- 与迭代器的关系
5.参考文章
内容总计于HeadFirst设计模式及相关视频