今天这个设计模式名字有点意思——脏标记模式( Dirty Flag Pattern )。
**01**
**目的**
避免不必要的耗时的重复计算。
**02**
**例子代码**
福报厂实现 P1—P7全员小于35岁, 菊花厂清理 35 岁以上员工......裁员、优化、末位淘汰、不得超过 35 岁等, 各种真真假假的新闻让我们这种互联网人如坐针毡, 危机感满满😨
像我,刚满18 岁就要担心 35 岁的日子了。貌似每个到了 35 岁的互联网人都要转行做快递小哥了(咱这么年迈也不知道能不能应聘得上😢)。
比如,这天公司的老板叫你每天给他统计一下公司的平均年龄, 来作为优 ( cai ) 化 ( yuan ) 的依据, 我们目前只有一个组织结构树和一个根据员工工号查询年龄的接口, 所以我们的代码可能会这么写:
先定义一个根据员工 ID 查询员工年龄的接口:
public class EmployeeWebService { public static Integer queryEmployeeAge(String userId) { return Integer.valueOf(userId); }}
定义一个树节点来存储员工结构:
@Datapublic class TreeNode<T> { private T value; private List<TreeNode<T>> children = new ArrayList<>(); public TreeNode(T value) { this.value = value; }}
计算员工的平均年龄:
public static Integer queryEmployeeAvgAge (TreeNode<String> employeeUserTree) { Integer totalAge = 0; Integer employeeCount = 0; if (employeeUserTree == null) { System.out.println("公司倒闭了"); return 0; } Queue<TreeNode> queue = new LinkedList<>(); queue.offer(employeeUserTree); while (!queue.isEmpty()) { TreeNode<String> node = queue.poll(); totalAge += EmployeeWebService. queryEmployeeAge(node.getValue()); employeeCount++; for (TreeNode<String> child : node.getChildren()) { queue.offer(child); } } return (totalAge / employeeCount);}
**03**
**脏标记模式**
因为是个树层结构, 遍历很耗时, 每个员工还发生了一次 RPC 调用来查询年龄, 但是如果每天都需要计算, 如果这个公司的人员变动不大, 一天内没有人入职和离职, 可以使用前一天的数据, 这个就是使用脏标记模式。
我们先来定义二个变量, 实际应用中可能存储在数据库, 文件或者缓存中:
public class Constant { public static Boolean IS_EMPLOYEE_CHANGED = false; public static Integer LASTDAY_EMPLOYEE_AVG_AGE = 0;}
比如定义了一个员工入职离职的接口:
public static void changeEmploy(String userId) { Constant.IS_EMPLOYEE_CHANGED = true;}
这些改动之后我们的代码:
public static Integer queryEmployeeAvgAge(TreeNode<String> employeeUserTree){ if(!Constant.IS_EMPLOYEE_CHANGED) { return Constant.LASTDAY_EMPLOYEE_AVG_AGE; } //一样的计算年龄的代码 int age = totalAge / employeeCount; Constant.LASTDAY_EMPLOYEE_AVG_AGE = age; return age;}
类图👇:
**04**
**脏标记模式课后作业**
1. 找出例子程序中的风险点代码
2. 找出生产场景下可使用本模式的例子
3. 使用模板方法模式实现脏标记模式
微信: