设计模式之禅跨战区PK
前言
- 创建类模式描述如何创建对象
- 行为类模式关注如何管理对象的行为
- 结构类模式则侧重于如何建立一个软件结构
- 实际的应用还是有重叠的,会出现一种模式适用,另一种模式也适用的情况
【门面模式】VS【中介者模式】
- 门面模式为复杂的子系统提供一个统一的访问界面,他定义的是一个高层的接口,该接口使得子系统更加容易使用,避免外部模块深入到子系统内部而产生与子系统细节耦合问题
- 中介者模式使用一个中介对象来封装一系列同事对象的交互行为,它使各对象之间不再显示地引用,从而使其耦合松散,建立一个可扩展的应用架构
案例驱动--工资计算
- 类图比较
中介者模式 | 门面模式 |
---|---|
代码实现
中介者模式
- AbsColleague
#
package com.peng.kzq3;
/**
* @author kungfu~peng
* @data 2018年1月4日
* @description
*/
public abstract class AbsColleague {
// 每个同事都对中介者非常了解
protected AbsMediator mediator;
public AbsColleague(AbsMediator mediator) {
super();
this.mediator = mediator;
}
}
- AbsMediator
#
package com.peng.kzq3;
/**
* @author kungfu~peng
* @data 2018年1月4日
* @description
*/
public abstract class AbsMediator {
public abstract void up(Position position);
public abstract void down(Position position);
public abstract void up(Salary salary);
public abstract void down(Salary salary);
public abstract void down(Tax tax);
public abstract void up(Tax tax);
}
- Client
#
package com.peng.kzq3;
/**
* @author kungfu~peng
* @data 2018年1月4日
* @description
*/
public class Client {
public static void main(String[] args) {
// 定义中介者
Mediator mediator = new Mediator();
// 定义各个同事类
IPosition p = new Position(mediator);
ISalary s = new Salary(mediator);
ITax t = new Tax(mediator);
// 职位提升
System.out.println("======职位提升========");
p.promote();
}
}
- IPosition
#
package com.peng.kzq3;
/**
* @author kungfu~peng
* @data 2018年1月4日
* @description
*/
public interface IPosition {
// 升职
public void promote();
// 降职
public void demote();
}
- ISalary
#
package com.peng.kzq3;
/**
* @author kungfu~peng
* @data 2018年1月4日
* @description
*/
public interface ISalary {
// 加薪
public void increaseSalary();
// 降薪
public void decreaseSalary();
}
- ITax
#
package com.peng.kzq3;
/**
* @author kungfu~peng
* @data 2018年1月4日
* @description
*/
public interface ISalary {
// 加薪
public void increaseSalary();
// 降薪
public void decreaseSalary();
}
- Mediator
#
package com.peng.kzq3;
/**
* @author kungfu~peng
* @data 2018年1月4日
* @description
*/
public class Mediator extends AbsMediator {
@Override
public void up(Position position) {
upPosition();
upSalary();
upTax();
}
@Override
public void down(Position position) {
downPosition();
downSalary();
downTax();
}
@Override
public void up(Salary salary) {
upSalary();
upTax();
}
@Override
public void down(Salary salary) {
downSalary();
downTax();
}
@Override
public void down(Tax tax) {
downTax();
}
@Override
public void up(Tax tax) {
upTax();
}
// 工资上升
void upSalary() {
System.out.println("工资涨了!");
}
// 职位升高
void upPosition() {
System.out.println("职位升高");
}
// 税收上升
void upTax() {
System.out.println("税收加重");
}
// 工资下降
void downSalary() {
System.out.println("薪水少了");
}
// 职位下降
void downPosition() {
System.out.println("职位下降");
}
// 税收下降
void downTax() {
System.out.println("税收下降");
}
}
- Position
#
package com.peng.kzq3;
/**
* @author kungfu~peng
* @data 2018年1月4日
* @description
*/
public class Position extends AbsColleague implements IPosition {
public Position(AbsMediator mediator) {
super(mediator);
}
@Override
public void promote() {
super.mediator.up(this);
}
@Override
public void demote() {
super.mediator.down(this);
}
}
- Salary
#
package com.peng.kzq3;
/**
* @author kungfu~peng
* @data 2018年1月4日
* @description
*/
public class Salary extends AbsColleague implements ISalary {
/**
* @param mediator
*/
public Salary(AbsMediator mediator) {
super(mediator);
}
@Override
public void increaseSalary() {
super.mediator.up(this);
}
@Override
public void decreaseSalary() {
super.mediator.down(this);
}
}
- Tax
#
package com.peng.kzq3;
/**
* @author kungfu~peng
* @data 2018年1月4日
* @description
*/
public class Tax extends AbsColleague implements ITax {
public Tax(AbsMediator mediator) {
super(mediator);
}
@Override
public void relase() {
super.mediator.down(this);
}
@Override
public void drop() {
super.mediator.up(this);
}
}
- 执行结果
#
======职位提升========
职位升高
工资涨了!
税收加重
门面模式
-
Attendance
package com.peng.kzq4; import java.util.Random; /** * @author kungfu~peng * @data 2018年1月4日 * @description 考勤 */ public class Attendance { // 得到出勤天数 public int getWorkDays() { return (new Random().nextInt(30)); } }
-
BasicSalary
package com.peng.kzq4; /** * @author kungfu~peng * @data 2018年1月4日 * @description */ public class BasicSalary { // 获得一个人的基本工资 public int getBasicSalary() { return 2000; } }
-
Bouns
package com.peng.kzq4; /** * @author kungfu~peng * @data 2018年1月4日 * @description */ public class Bouns { // 考勤情况 private Attendance atte = new Attendance(); // 奖金 public int getBonus() { // 获得出勤情况 int workdays = atte.getWorkDays(); // 奖金计算模型 int bouns = workdays * 1800 / 30; return bouns; } }
-
Client
package com.peng.kzq4; import java.util.Date; /** * @author kungfu~peng * @data 2018年1月4日 * @description */ public class Client { public static void main(String[] args) { // 定义门面 HRFacade facade = new HRFacade(); // 查询kungfupeng的收入 System.out.println("收入:" + facade.query("kungfupeng", new Date())); System.out.println("工作:" + facade.queryWorkDays() + "天"); } }
-
HRFacade
package com.peng.kzq4; import java.util.Date; /** * @author kungfu~peng * @data 2018年1月4日 * @description */ public class HRFacade { // 总工资情况 private SalaryProvider salaryProvider = new SalaryProvider(); // 考勤情况 private Attendance attentence = new Attendance(); // 查询一个人的总收入 public int query(String name, Date date) { return salaryProvider.totalSalary(); } // 查询一个员工一个月工作了多少天 public int queryWorkDays() { return attentence.getWorkDays(); } }
-
Performance
package com.peng.kzq4; import java.util.Random; /** * @author kungfu~peng * @data 2018年1月4日 * @description */ public class Performance { // 基本工资 private BasicSalary salary = new BasicSalary(); // 绩效奖励 public int getPerformanceValue() { // 绩效随机 int perf = (new Random().nextInt(100)); return salary.getBasicSalary() * perf / 100; } }
-
SalaryProvider
package com.peng.kzq4; /** * @author kungfu~peng * @data 2018年1月4日 * @description */ public class SalaryProvider { // 基本工资 private BasicSalary basicSalary = new BasicSalary(); // 奖金 private Bouns bouns = new Bouns(); // 绩效 private Performance perf = new Performance(); // 税收 private Tax tax = new Tax(); // 获得的总收入 public int totalSalary() { return basicSalary.getBasicSalary() + bouns.getBonus() + perf.getPerformanceValue() - tax.getTax(); } }
-
Tax
package com.peng.kzq4; import java.util.Random; /** * @author kungfu~peng * @data 2018年1月4日 * @description */ public class Tax { // 收取多少税金 public int getTax() { // 缴纳一个随机数量的税金 return (new Random().nextInt(300)); } }
-
某一次的执行结果
收入:3653 工作:17天
最佳实践
- 门面模式和中介模式之间的区别还是比较明显的,门面模式是以封装和隔离为主要任务,而中介者模式则是以调和同事类之间的关系为主,因为要调和,所以具有了部分的业务逻辑控制
- 比较
比较项 | 门面模式 | 中介者模式 |
---|---|---|
功能 | 门面模式只是增加了一个门面,它对系统来说没有增加任何的功能,子系统若脱离门面模式是完全可以独立运行的 | 中介者模式增加了业务功能,它把同事类中原有的耦合关系移植到了中介者,同事类不可能脱离中介者而独立存在,除非是想增加系统的复杂性和降低扩展性 |
知晓状态 | 子系统不知道有个门面存在 | 每个同事都知道中介者的存在,因为要依靠中介者调和和同事之间的关系,他们对中介者都很熟悉 |
封装程度 | 简单的封装,所有的请求处理都委托给子系统完成 | 需要一个中心,由中心协调同事类完成,并且中心本身也完成部分任务,它属于更进一步的业务功能的封装 |