装饰者模式
装饰者模式(Decorator Pattern) 是一种比较常见的模式。
1装饰者模式的定义
装饰者模式的英文原话是:
Attach Additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.
意思是:动态的给对象添加一些额外的职责。就增加功能来说,装饰者模式比生成子类更为灵活。
装饰者模式有4个角色:
- 抽象构件(Component)角色:该角色用于规范需要装饰的对象(原始对象)。
- 具体构件(Concrete Component)角色:该角色实现抽象构件接口,定义一个需要装饰的原始类。
- 装饰者(Decorator)角色:该角色持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口。
- 具体装饰(Concrete Decorator)角色:该角色负责对构件对象进行装饰。
引例:
装饰者模式类图
Component接口
package com.eric.结构型模式.装饰者模式.引例;
/**
* @author Eric
* @ProjectName my_design_23
* @description 抽象构件
* @CreateTime 2020-11-29 19:52:25
*/
public interface Component {
public void operation();
}
ConcreteComponent类---->实现了Component接口
package com.eric.结构型模式.装饰者模式.引例;
/**
* @author Eric
* @ProjectName my_design_23
* @description 具体构件类
* @CreateTime 2020-11-29 20:04:05
*/
public class ConcreteComponent implements Component {
@Override
public void operation() {
//业务代码
}
}
Decorator类实现了Component接口
package com.eric.结构型模式.装饰者模式.引例;
/**
* @author Eric
* @ProjectName my_design_23
* @description 装饰者
* @CreateTime 2020-11-29 20:04:47
*/
public class Decorator implements Component {
private Component component = null;
public Decorator(Component component){
this.component = component;
}
@Override
public void operation() {
this.component.operation();
}
}
ConcreteDecorator类---->继承了Decorator
package com.eric.结构型模式.装饰者模式.引例;
/**
* @author Eric
* @ProjectName my_design_23
* @description 具体装饰者
* @CreateTime 2020-11-29 20:06:35
*/
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
//定义自己的方法
private void method(){
System.out.println("装饰");
}
//重写operation()方法
@Override
public void operation() {
this.method();
super.operation();
}
}
2装饰者模式的应用
a.装饰者模式的优缺点
- 装饰者类和被装饰类可以独立发展,而不会相互耦合。即Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构建。
- 装饰者模式是继承关系的一种替代方案。装饰类Decorator,不管装饰多少层,返回对象还是Component.
- 封装模式可以动态的扩展一个实现类功能。
装饰者模式的缺点:多层的装饰是比较复杂的。
b.装饰者模式的使用场景
- 需要扩展一个类的功能,或给一个类增加附加功能。
- 需要动态的给一个对象增加功能,这些功能可以再动态地撤销。
- 需要为一批类进行改装或加装功能。
装饰者模式是对继承的有力补充。单纯的使用继承时,在一些情况下就会增加很多子类,而且灵活性差,维护起来也不容易。装饰者模式可以代替继承,解决类膨胀的问题,如Java基础类库中的IO(输入输出流)相关的类大量使用了装饰者模式。
3装饰者模式实例
例1裸车的装饰过程
汽车装修的类图
汽车的接口
Car.java
package com.eric.结构型模式.装饰者模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 汽车接口
* @CreateTime 2020-11-29 23:46:29
*/
public interface Car {
//车的装配
public void show();
}
汽车的实现类---->实现Car接口
Benz.java
package com.eric.结构型模式.装饰者模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 奔驰车(裸车-需装饰)
* @CreateTime 2020-11-29 23:47:10
*/
public class Benz implements Car{
@Override
public void show() {
System.out.println("奔驰车的默认颜色是黑色!");
}
}
装饰者的抽象类--->实现Car接口
CarDecorator.java
package com.eric.结构型模式.装饰者模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 汽车装饰抽象类
* @CreateTime 2020-11-29 23:48:36
*/
public abstract class CarDecorator implements Car {
private Car car = null;
public CarDecorator(Car car){
this.car = car;
}
@Override
public void show() {
this.car.show();
}
}
装饰者的实现类---->继承CarDecorator类
ConcreteCarDecorator.java
package com.eric.结构型模式.装饰者模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 具体的汽车装饰类
* @CreateTime 2020-11-29 23:50:14
*/
public class ConcreteCarDecorator extends CarDecorator {
public ConcreteCarDecorator(Car car) {
super(car);
}
//给汽车进行彩绘
private void print(){
System.out.println("在车尾绘制“新手“字样,颜色是紫色霞光");
}
//给车安装GPS设备
private void setGps(){
System.out.println("安装GPS定位导航系统!");
}
//重写show()方法
public void show(){
super.show();
this.print();
this.setGps();
}
}
测试类
package com.eric.结构型模式.装饰者模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 测试
* @CreateTime 2020-11-29 23:54:31
*/
public class ClientDemo {
public static void main(String[] args) {
Car car = new Benz();
//对奔驰车进行装饰
ConcreteCarDecorator decorator = new ConcreteCarDecorator(car);
decorator.show();
}
}
测试结果
package com.eric.结构型模式.装饰者模式.例2;
/**
* @author Eric
* @ProjectName my_design_23
* @description 形状接口
* @CreateTime 2020-11-30 00:09:30
*/
public interface Shape {
//画画
public void draw();
}
Shape接口的两个实现类
Circle.java
package com.eric.结构型模式.装饰者模式.例2;
/**
* @author Eric
* @ProjectName my_design_23
* @description 圈圈
* @CreateTime 2020-11-30 00:10:09
*/
public class Circle implements Shape{
@Override
public void draw() {
System.out.println("画了个圈圈...");
}
}
Rectangle.java
package com.eric.结构型模式.装饰者模式.例2;
/**
* @author Eric
* @ProjectName my_design_23
* @description 矩形
* @CreateTime 2020-11-30 00:11:29
*/
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("画了一个框框...");
}
}
有了Shape的两个实现类后,开始创建它的抽象装饰者类。
ShapeDecorator.java
package com.eric.结构型模式.装饰者模式.例2;
/**
* @author Eric
* @ProjectName my_design_23
* @description 矩形
* @CreateTime 2020-11-30 00:11:29
*/
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("画了一个框框...");
}
}
最后是具体的装饰者类------>继承ShapeDecorator
RedShapeDecorator.java
package com.eric.结构型模式.装饰者模式.例2;
/**
* @author Eric
* @ProjectName my_design_23
* @description 红色的装饰者
* @CreateTime 2020-11-30 00:14:41
*/
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape shape) {
super(shape);
}
private void setRedBorder(){
System.out.println("边边是红色的...");
}
@Override
public void draw() {
shape.draw();
this.setRedBorder();
}
}
测试类
package com.eric.结构型模式.装饰者模式.例2;
/**
* @author Eric
* @ProjectName my_design_23
* @description 测试
* @CreateTime 2020-11-30 00:20:50
*/
public class DecoratorPatternDemo {
public static void main(String[] args) {
Shape circle = new Circle();
ShapeDecorator redShapeDecorator1 = new RedShapeDecorator(circle);
redShapeDecorator1.draw();
Shape rectangle = new Rectangle();
ShapeDecorator redShapeDecorator2 = new RedShapeDecorator(rectangle);
redShapeDecorator2.draw();
}
}
测试截图
后续可能会精简和改进。