装饰模式的本质是:动态组合。
一、装饰模式的定义:
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更为灵活。
二、应用场景
1)需要在不影响其他对象的情况下,以动态、透明的方式给对象添加职责,可以使用装饰模式,这几乎就是装饰模式的主要功能;
2)不适合使用子类来扩展的时候,可以考虑使用装饰模式。因为装饰模式是使用“对象组合”的方式。
三、装饰模式代码示例
假设在计算员工奖金时,普通员工有月度奖金、团队奖金,部门经理不仅同时拥有月度、团队奖金,还额外拥有经理奖金,下面用编码模拟实现:
1、奖金计算器抽象类
/**
* 奖金计算器
*/
public abstract class PrizeCalculator {
/**
* 计算奖金方法
*/
protected abstract double calPrize(String user);
}
2、奖金计算器实现类
public class ConcretePrizeCalculator extends PrizeCalculator {
@Override
protected double calPrize(String user) {
// 默认奖金为0
return 0;
}
}
3、装饰器抽象类
public abstract class Decorator extends PrizeCalculator {
private PrizeCalculator prizeCalculator;
public Decorator(PrizeCalculator prizeCalculator) {
this.prizeCalculator = prizeCalculator;
}
@Override
protected double calPrize(String user) {
return prizeCalculator.calPrize(user);
}
}
4、月度奖金装饰器
/**
* 月度奖金装饰器
*/
public class MonthPrizeDecorator extends Decorator{
public MonthPrizeDecorator(PrizeCalculator prizeCalculator) {
super(prizeCalculator);
}
@Override
protected double calPrize(String user) {
// 假设当月业务奖金计算出来为1000元
double monthPrize = 1000;
System.out.println(String.format("%s获取的月度奖金为%s",user,monthPrize));
return super.calPrize(user) + monthPrize;
}
}
5、团队奖金装饰器
/**
* 团队奖金装饰器
*/
public class GroupPrizeDecorator extends Decorator {
public GroupPrizeDecorator(PrizeCalculator prizeCalculator) {
super(prizeCalculator);
}
@Override
protected double calPrize(String user) {
// 假设计算出来的团队奖金为 1500
double groupPrize = 1500;
System.out.println(String.format("%s获取的团队奖金为%s",user,groupPrize));
return super.calPrize(user) + groupPrize;
}
}
6、经理奖金装饰器
/**
* 部门经理奖金
*/
public class ManagerPrizeDecorator extends Decorator{
public ManagerPrizeDecorator(PrizeCalculator prizeCalculator) {
super(prizeCalculator);
}
@Override
protected double calPrize(String user) {
// 假设部门经理计算出来的奖金为2000
double managerPrize = 2000;
System.out.println(String.format("%s获取的经理奖金为%s",user,managerPrize));
return super.calPrize(user) + managerPrize;
}
}
7、客户端类
public class Client {
public static void main(String[] args) {
PrizeCalculator prizeCalculator = new ConcretePrizeCalculator();
// 假设张三是普通员工,享有月度奖金和团队奖金
// 用月度奖金装饰器装饰奖金计算器
Decorator monthPrize = new MonthPrizeDecorator(prizeCalculator);
// 用团队奖金装饰器装饰月度奖金装饰器
Decorator groupPrize = new GroupPrizeDecorator(monthPrize);
final double prizeZs = groupPrize.calPrize("张三");
System.out.println("张三奖金总和:" + prizeZs);
System.out.println("--------------------------------");
// 假设李四是部门经理,享有月度奖金、团队奖金和经理奖金三种
// 用部门奖金装饰器装饰团队奖金装饰器
Decorator managerPrize = new ManagerPrizeDecorator(groupPrize);
final double prizeLs = managerPrize.calPrize("李四");
System.out.println("李四的奖金总和:" + prizeLs);
}
}
8、运行结果 四、装饰模式的优缺点
优点:
1)比继承更灵活;
2)符合开闭原则。
缺点:
1)会产生很多细粒度的对象。