23种设计模式介绍:https://mp.csdn.net/postedit/90552052
1.1 意图
一般有两种方式可以实现给一个类或对象增加行为:
- 继承机制,使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法。但是这种方法是静态的,用户不能控制增加行为的方式和时机。
- 关联机制,即将一个类的对象嵌入另一个对象中,由另一个对象来决定是否调用嵌入对象的行为以便扩展自己的行为,我们称这个嵌入的对象为装饰器(Decorator)
装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任,换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。这就是装饰模式的模式动机。
1.2 模式定义
装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
1.3 使用场景
1.4 模式结构
装饰模式主要包含以下角色。
- 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
- 具体构件(Concrete Component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
- 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
- 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
1.5 时序图
1.6 demo
demo1:变形金刚
变形金刚在变形之前是一辆汽车,它可以在陆地上移动。当它变成机器人之后除了能够在陆地上移动之外,还可以说话;如果需要,它还可以变成飞机,除了在陆地上移动还可以在天空中飞翔。
步骤1:创建接口:
package DesignPattern23.Decorator;
/**
* Description:
* Author:
* Date: 2019/11/11
*/
public interface Trasform {
void move();
}
步骤2:创建实体:
package DesignPattern23.Decorator;
/**
* Description:
* Author:
* Date: 2019/11/11
*/
public class Car implements Trasform{
@Override
public void move() {
System.out.println("car is running!");
}
}
步骤3:创建装饰器Changer抽象类
package DesignPattern23.Decorator;
/**
* Description:
* Author:
* Date: 2019/11/11
*/
public abstract class Changer implements Trasform{
protected Trasform car;
public Changer(Trasform car) {
this.car = car;
}
@Override
public void move() {
car.move();
}
}
步骤5:创建具体装饰子类
package DesignPattern23.Decorator;
/**
* Description:
* Author:
* Date: 2019/11/11
*/
public class Robot extends Changer{
public Robot(Trasform car) {
super(car);
}
@Override
public void move(){
car.move();
say();
}
void say(){
System.out.println("can say");
}
}
package DesignPattern23.Decorator;
/**
* Description:
* Author:
* Date: 2019/11/11
*/
public class Airplane extends Changer{
public Airplane(Trasform car) {
super(car);
}
@Override
public void move(){
car.move();
fly();
}
void fly(){
System.out.println("can fly");
}
}
步骤6:测试
package DesignPattern23.Decorator;
/**
* Description:
* Author:
* Date: 2019/11/11
*/
public class TestDemo {
public static void main(String[] args) {
Trasform car = new Car();
car.move();
System.out.println("~~~~~~~~~~~~~");
Robot robot = new Robot(car);
robot.move();
}
}
执行结果:
car is running!
~~~~~~~~~~~~~
car is running!
can say
Process finished with exit code 0
1.7 总结
- 装饰模式用于动态地给一个对象增加一些额外的职责,就增加对象功 能来说,装饰模式比生成子类实现更为灵活。它是一种对象结构型模 式。
- 装饰模式包含四个角色:抽象构件定义了对象的接口,可以给这些对 象动态增加职责(方法);具体构件定义了具体的构件对象,实现了 在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法); 抽象装饰类是抽象构件类的子类,用于给具体构件增加职责,但是具 体职责在其子类中实现;具体装饰类是抽象装饰类的子类,负责向构 件添加新的职责。
- 使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动 态地给一个对象附加更多的责任。装饰模式可以在不需要创造更多子 类的情况下,将对象的功能加以扩展。
- 装饰模式的主要优点在于可以提供比继承更多的灵活性,可以通过一种动态的 方式来扩展一个对象的功能,并通过使用不同的具体装饰类以及这些装饰类的 排列组合,可以创造出很多不同行为的组合,而且具体构件类与具体装饰类可 以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类;其主要缺 点在于使用装饰模式进行系统设计时将产生很多小对象,而且装饰模式比继承 更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需 要逐级排查,较为烦琐。
- 装饰模式适用情况包括:在不影响其他对象的情况下,以动态、透明的方式给 单个对象添加职责;需要动态地给一个对象增加功能,这些功能也可以动态地 被撤销;当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展 和维护时。
- 装饰模式可分为透明装饰模式和半透明装饰模式:在透明装饰模式中,要求客 户端完全针对抽象编程,装饰模式的透明性要求客户端程序不应该声明具体构 件类型和具体装饰类型,而应该全部声明为抽象构件类型;半透明装饰模式允 许用户在客户端声明具体装饰者类型的对象,调用在具体装饰者中新增的方法。