设计模式(十一)—装饰模式
最后更新于:2022-04-01 16:26:16
**英文名称:(Decorator Pattern)**
**定义**:动态的给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更加灵活。
## 装饰模式的一般模式
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340a94974.jpg)
Component抽象构件
---|Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象。
ConcreteComponent具体构件
---|ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,要装饰的就是它。
Decorator装饰角色
---|一般是一个抽象类,实现接口或者抽象方法,它的属性里必然有一个private变量指向Component抽象构件
具体装饰角色
---|要把最原始的、最基本的、最核心的东西装饰成其他东西。
~~~
public class DecoratorPattern {
public static void main(String[] args) {
//拿到原始构件
Component origin = new ConcreteComponent();
origin = new ConcreteDecorator1(origin);
origin = new ConcreteDecorator2(origin);
origin.doSomething();
}
}
abstract class Component{
//抽象的方法,定义一些核心的方法。让子类去实现
public abstract void doSomething();
}
class ConcreteComponent extends Component{
@Override
public void doSomething() {
System.out.println("我是抽象构件的具体实现....");
}
}
abstract class Decorator extends Component{
//有一个私有方法,指向Component类
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void doSomething() {
//让Component的实现类去执行方法。
this.component.doSomething();
}
}
/**
* 1号修饰类
* @author admin
*
*/
class ConcreteDecorator1 extends Decorator{
//指向父类的方法
public ConcreteDecorator1(Component component) {
super(component);
}
private void decorator1(){
System.out.println("-----开始之前先修饰-----------");
}
@Override
public void doSomething() {
System.out.println("-111111111111111111111-");
//修饰方法
this.decorator1();
//执行原始方法
super.doSomething();
}
}
/**
* 2号修饰类
* @author admin
*
*/
class ConcreteDecorator2 extends Decorator{
//指向父类的方法
public ConcreteDecorator2(Component component) {
super(component);
}
private void decorator2(){
System.out.println("-----结束之后再修饰-----------");
}
@Override
public void doSomething() {
System.out.println("-2222222222222222222222-");
//执行原始方法
super.doSomething();
//修饰方法
this.decorator2();
}
}
~~~
## 一个例子:
老师把我的成绩单发下来,让家长签字。因为成绩考的不好,所以不能直接把成绩单拿给爸爸看,
因此我得在拿出成绩单前加一些修饰语。例如:告诉爸爸班里同学的最高分,我的分数是多少。
之后再说我在班里的名次。这样就能避免一场海骂了。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340ab09c1.jpg)
~~~
public class DecoratorTest {
public static void main(String[] args) {
//拿着自己的原始成绩单。
SchoolScore mScore = new ConcreteStudent();
//加上一层修饰,最高分的修饰。
mScore = new HighScoreDecorator(mScore);
//再加上第二次修饰,我的排名的修饰。
mScore = new SortDecorator(mScore);
//做出报告说明
mScore.report();
//可以让家长签字了
mScore.sign("lzl");
}
}
abstract class SchoolScore{
//定义一个成绩单的接口,共每个学生去实现
//每个学生报告给家长,自己的成绩。
public abstract void report();
//要求家长签字。
public abstract void sign(String name);
}
class ConcreteStudent extends SchoolScore{
@Override
public void report() {
System.out.println("我的语文成绩是 89,数学成绩是 78,英语成绩是 77.");
}
@Override
public void sign(String name) {
System.out.println("家长签字:"+name);
}
}
/**
* 因为怕父亲看到成绩被他骂,所以我要来个装饰类。
* @author admin
*/
abstract class MyDecorator extends SchoolScore{
//定义学生的成绩
private SchoolScore score;
//用构造函数,实例化学生成绩类。
public MyDecorator(SchoolScore score) {
this.score = score;
}
//抽象方法,为学生提交成绩单时,添加一些修饰方法。
public void report(){
this.score.report();
}
//重写父类的方法。让家长签字
@Override
public void sign(String name) {
this.score.sign(name);
}
}
/**
* 首先添加一个全班最高成绩的说明,
* 让父亲知道我这个成绩还算可以。
* @author admin
*/
class HighScoreDecorator extends MyDecorator{
public HighScoreDecorator(SchoolScore score) {
super(score);
}
private void highScoreSchool() {
System.out.println("语文最高分:99,数学最高分:88,英语最高分:77");
}
@Override
public void report() {
//先说明最高成绩
this.highScoreSchool();
//再报自己的成绩
super.report();
}
}
class SortDecorator extends MyDecorator{
public SortDecorator(SchoolScore score) {
super(score);
}
private void getSort() {
System.out.println("我在班里的排名是:第十...");
}
@Override
public void report() {
//先报完成绩
super.report();
//再说明名次。
this.getSort();
}
}
~~~
**装饰模式的优点**:
---|装饰类和被装饰类可以独立的发展,不会相互耦合。
---|装饰模式是继承关系的一种替代方案。Decorator不管修饰多少层,返回的对象还是Component,实现的还是is-a的关系。
---|装饰模式可以动态的扩展一个实现类的功能。
**装饰模式的缺点**:
---|多层的装饰模式是比较复杂的。
**装饰模式的使用场景**:
---|扩展一个类的功能,或给一个类增加附加的功能
---|动态的给一个对象增加功能,这些功能可以动态的撤销
---|为一批的兄弟类进行改装或者加装功能,首选装饰模式。