目录
- 一、定义
- 二、结构
- 三、优点
- 四、使用场景
- 五、代码示例
- 六、截图示例
一、定义
- 1.在不改变现有对象结构的情况下,动态给该对象添加额外功能的模式
- 2.类B继承于类A,并将类A作为B类的属性(B类聚合A类)
- 3.BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter都用到了装饰者模式
二、结构
- 1.抽象构件角色(Component):定义一个抽象接口以规范准备接收附加责任的对象
- 2.具体构件角色(Concrete Component):实现抽象构件,通过装饰角色为其添加一些职责
- 3.抽象装饰角色(Decorator):继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能
- 4.具体装饰角色(ConcreteDecorator):实现抽象装饰的相关方法,并给具体构件对象添加附加的责任
三、优点
- 1.装饰者模式可以带来比继承更加灵活性的扩展功能,使用更加方便,可以通过组合不同的装饰者对象来获取具有不同行为状态的多样化结果
- 2.装饰者模式比继承更具良好的扩展性,完美的遵循开闭原则,继承是静态的附加责任,装饰者则是动态的附加责任
- 3.装饰类和被装饰类可以独立发展,不会互相耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能
四、使用场景
- 1.当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时
- 2.不能采用继承的情况主要有两类:1.系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;2.类定义不能被继承(例如被final修饰的类)
- 3.在不影响其它对象情况下,以动态、透明的方式给单个对象添加职责
- 4.当对象的功能要求可以动态添加,也可以动态撤销时
五、代码示例
package com.learning.decorator;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 抽象构件角色
* 快餐类
*/
@Data
@AllArgsConstructor
public abstract class FastFood {
// 价格
private float price;
// 名称
private String name;
public abstract float cost();
public void printFastFood(){
System.out.println(this.getName() + " " + this.cost());
}
}
package com.learning.decorator;
/**
* 炒饭类
* 具体构件角色
*/
public class FriedRice extends FastFood{
public FriedRice(){
super(10, "炒饭");
}
@Override
public float cost() {
return getPrice();
}
}
package com.learning.decorator;
/**
* 炒面类
* 具体构件角色
*/
public class FriedNoodles extends FastFood{
public FriedNoodles(){
super(12, "炒面");
}
@Override
public float cost() {
return getPrice();
}
}
package com.learning.decorator;
import lombok.Getter;
import lombok.Setter;
/**
* 装饰者类
* 抽象装饰者角色
*/
@Setter
@Getter
public abstract class Garnish extends FastFood{
// 声明快餐类的变量
private FastFood fastFood;
public Garnish(FastFood fastFood, float price, String name) {
super(price, name);
this.fastFood = fastFood;
}
}
package com.learning.decorator;
/**
* 鸡蛋类
* 具体的装饰者角色
*/
public class Egg extends Garnish{
public Egg(FastFood fastFood){
super(fastFood, 1, "鸡蛋");
}
@Override
public float cost() {
// 计算价格
return getFastFood().cost() + this.getPrice();
}
@Override
public String getName() {
return super.getName() + getFastFood().getName();
}
}
package com.learning.decorator;
/**
* 培根类
* 具体的装饰者角色
*/
public class Bacon extends Garnish{
public Bacon(FastFood fastFood){
super(fastFood, 1, "培根");
}
@Override
public float cost() {
// 计算价格
return getFastFood().cost() + this.getPrice();
}
@Override
public String getName() {
return super.getName() + getFastFood().getName();
}
}
package com.learning.decorator;
public class Client {
public static void main(String[] args) {
FastFood fastFood = new FriedRice();
// 点一份炒饭
fastFood.printFastFood();
// 炒饭中添加鸡蛋
fastFood = new Egg(fastFood);
fastFood.printFastFood();
// 鸡蛋炒饭中加培根
fastFood = new Bacon(fastFood);
fastFood.printFastFood();
// 再加一个鸡蛋
fastFood = new Egg(fastFood);
fastFood.printFastFood();
}
}
六、截图示例