什么是装饰模式
动态地给一个类添加一些额外的职责,就拿添加功能来说,装饰模式比生成子类更为灵活
UML图
图片来自网络
优缺点分析
优点:
1、将类的核心职责与装饰功能分开
2、客户端代码可以有选择,有层次的使用装饰功能来包装对象
3、减少类的复杂性
缺点:
1、容易产生很多细粒度对象
与策略模式对比
策略模式改变的是对象的核心,装饰模式改变的是对象的外壳。
策略模式是一层调用,装饰模式可以递归调用。
小测验
UML图
采用装饰模式完成奖金的分发,对于奖金的计算,使用策略模式实现奖金计算。
代码实现:
package salary;
public abstract class SalaryComponent {
protected double sum;
public abstract void computeSalary();
}
package salary;
public class Staff extends SalaryComponent{
private String name;
private double salary;
public Staff(String name,double salary ){
this.name = name;
sum = 0;
this.salary = salary;
}
@Override
public void computeSalary() {
System.out.println(name+"的总奖金为"+sum);
System.out.println("个人月工资" + salary);
}
}
package salary;
public class ExecutiveStaff extends SalaryComponent{
private String name;
private double salary;
public ExecutiveStaff(String name,double salary ){
this.name = name;
sum = 0;
this.salary = salary;
}
@Override
public void computeSalary() {
System.out.println(name+"的总奖金为"+sum);
System.out.println("个人工资为"+salary);
}
}
package salary;
import java.lang.reflect.InvocationTargetException;
public class Bonus extends SalaryComponent{
protected SalaryComponent component;
protected double bonus;
protected Strategy strategy;
public Bonus(double bonus,String strategy) {
this.bonus = bonus;
try {
this.strategy=(Strategy) Class.forName("salary."+strategy).getConstructor(Bonus.class).newInstance(this);
} catch (Exception e) {
e.printStackTrace();
}
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
@Override
public void computeSalary() {
strategy.computeBonus();
component.sum+=sum;
component.computeSalary();
}
}
package salary;
public class CumulateBonus extends Bonus{
public CumulateBonus(double bonus, SalaryComponent component,String strategy) {
super(bonus,strategy);
this.component = component;
}
}
package salary;
public class MonthBonus extends Bonus{
public MonthBonus(double bonus,SalaryComponent component,String strategy) {
super(bonus,strategy);
this.component = component;
}
}
package salary;
public class TeamBonus extends Bonus{
public TeamBonus(double bonus, SalaryComponent component,String strategy) {
super(bonus,strategy);
this.component = component;
}
}
package salary;
public class 回款奖金 extends Bonus {
public 回款奖金(double bonus,SalaryComponent component,String strategy) {
super(bonus,strategy);
this.component = component;
}
}
package salary;
public abstract class Strategy {
protected Bonus bonus;
public abstract void computeBonus();
}
package salary;
public class CumulateBonusS1 extends Strategy{
public CumulateBonusS1(Bonus bonus) {
this.bonus = bonus;
}
@Override
public void computeBonus() {
bonus.setBonus(bonus.bonus*1);
bonus.sum+=bonus.bonus;
System.out.println("累计奖金为"+bonus.bonus);
}
}
package salary;
public class MonthBonusS1 extends Strategy{
public MonthBonusS1(Bonus bonus) {
this.bonus = bonus;
}
@Override
public void computeBonus() {
bonus.setBonus(bonus.bonus*1);
bonus.sum+=bonus.bonus;
System.out.println("月奖金为"+bonus.bonus);
}
}
package salary;
public class TeamBonusS1 extends Strategy{
public TeamBonusS1(Bonus bonus) {
this.bonus = bonus;
}
@Override
public void computeBonus() {
bonus.bonus = bonus.bonus*1;
bonus.sum+=bonus.bonus;
System.out.println("团队奖金为"+bonus.bonus);
}
}
package salary;
public class 回款奖金S1 extends Strategy{
public 回款奖金S1(Bonus bonus) {
this.bonus = bonus;
}
@Override
public void computeBonus() {
bonus.bonus= bonus.bonus*1;
bonus.sum+=bonus.bonus;
System.out.println("限时回款奖金为"+bonus.bonus);
}
}
测试类:
package salary;
public class test {
public static void main(String[] args) {
Staff liu = new Staff("mr.liu",1000);
ExecutiveStaff liu2 = new ExecutiveStaff("mr.liu",10000);
MonthBonus monthBonus = new MonthBonus(1000,liu,"MonthBonusS1");
CumulateBonus cumulateBonus = new CumulateBonus(1000,monthBonus,"CumulateBonusS1");
回款奖金 bonus = new 回款奖金(1000,cumulateBonus,"回款奖金S1");
bonus.computeSalary();
System.out.println();
monthBonus = new MonthBonus(1000,liu2,"MonthBonusS1");
cumulateBonus = new CumulateBonus(1000,monthBonus,"CumulateBonusS1");
bonus = new 回款奖金(1000,cumulateBonus,"回款奖金S1");
TeamBonus teamBonus = new TeamBonus(1000,bonus,"TeamBonusS1");
teamBonus.computeSalary();
}
}
测试结果:
限时回款奖金为1000.0
累计奖金为1000.0
月奖金为1000.0
mr.liu的总奖金为3000.0
个人月工资1000.0
团队奖金为1000.0
限时回款奖金为1000.0
累计奖金为1000.0
月奖金为1000.0
mr.liu的总奖金为4000.0
个人工资为10000.0
进程已结束,退出代码为 0