设计模式 - 策略模式(Strategy)

Strategy模式定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

类图:
这里写图片描述

案例: 不同的员工薪资计算不同。
没有实现Strategy模式的例子:

public class Employee {
	public static final int ENGINEER = 0;
	public static final int SALESMAN = 1;
	public static final int MANAGER  = 2;
	
	private int type = 0;
	private int monthlySalary;
	private int commission;
	private int bonus;
	public Employee(int type, int monthlySalary) {
		this.type = type;
		this.monthlySalary = monthlySalary;
	}
	public int getType() {
		return type;
	}
	public int getMonthlySalary() {
		return monthlySalary;
	}
	public int getCommission() {
		return commission;
	}
	public void setCommission(int commission) {
		this.commission = commission;
	}
	public int getBonus() {
		return bonus;
	}
	public void setBonus(int bonus) {
		this.bonus = bonus;
	}
	public int payAmount() {
		int result = 0;
		switch(type) {
		case ENGINEER:
			result = monthlySalary;
			break;
		case SALESMAN:
			result = monthlySalary + commission;
			break;
		case MANAGER:
			result = monthlySalary + bonus;
			break;
		}
		return result;
	}
}

测试代码

public class EmployeeTest {
	@Test
	public void testEngineer() {
		Employee engineer = new Employee(Employee.ENGINEER, 8000);
		assertEquals(8000, engineer.payAmount());
		engineer.setCommission(1000);
		engineer.setBonus(2000);
		assertEquals(8000, engineer.payAmount());
	}

	@Test
	public void testSalesman() {
		Employee salesman = new Employee(Employee.SALESMAN, 8000);
		assertEquals(8000, salesman.payAmount());
		salesman.setCommission(1000);
		salesman.setBonus(2000);
		assertEquals(9000, salesman.payAmount());
	}

	@Test
	public void testManager() {
		Employee manager = new Employee(Employee.MANAGER, 8000);
		assertEquals(8000, manager.payAmount());
		manager.setCommission(1000);
		manager.setBonus(2000);
		assertEquals(10000, manager.payAmount());
	}
}

可以看到payAmount()方法有条件语句,不同类型的员工,薪资计算的算法不同,可以使用strategy模式重构:
每个类型码对应一个具体的strategy类, 每个strategy类定义一个payAmount(Employee employee)方法,Employee持有一个strategy类型的引用,它的payAmount委托给这个strategy引用对象,为了多态实现strategy, 提炼strategy接口。

public interface EmployeeType {//strategy interface
	public int payAmount(Employee employee); 
}
public class Engineer implements EmployeeType {
	public int payAmount(Employee employee) {
		return employee.getMonthlySalary();
	}
}
public class Salesman implements EmployeeType {
	public int payAmount(Employee employee) {
		return employee.getMonthlySalary() + employee.getCommission();
	}
}
public class Manager implements EmployeeType {
	public int payAmount(Employee employee) {
		return employee.getMonthlySalary() + employee.getBonus();
	}
}

修改Employee类,将类型码替换成strategy类型引用,payAmount()委托给strategy类型的引用对象的payAmount(Employee employee)方法:

public class Employee {
	private EmployeeType employeeType;
	private int monthlySalary;
	private int commission;
	private int bonus;
	public Employee(EmployeeType employeeType, int monthlySalary) {
		this.employeeType = employeeType;
		this.monthlySalary = monthlySalary;
	}
	public EmployeeType getType() {
		return employeeType;
	}
	public int getMonthlySalary() {
		return monthlySalary;
	}
	public int getCommission() {
		return commission;
	}
	public void setCommission(int commission) {
		this.commission = commission;
	}
	public int getBonus() {
		return bonus;
	}
	public void setBonus(int bonus) {
		this.bonus = bonus;
	}
	public int payAmount() {
		return employeeType.payAmount(this);
	}
}

总结:

  1. Strategy 模式是通过对象组合方式去除复杂的条件逻辑,为什么不选择通过Context的类继承方式?
    a) 运行时动态替换算法。
    b) 独立于客户端,无需修改客户端代码。

  2. Strategy类如何访问Context类的数据?
    a) 将Context引用传递给Strategy类的计算方法(回调机制)。
    b) 将所需的数据传递给Strategy类的计算方法。
    c) 将所需的数据封装成类,通过参数对象传递给Strategy类的计算方法。
    d) 将特殊数据传递给Strategy类的构造函数或初始化方法。

  3. Context类中用于计算的辅助方法 是 放在Context类中还是Strategy类中? 如果只是与计算相关,将这些辅助方法移动到Strategy类中。

返回 设计模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值