Java设计模式之装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
在编写代码过程中我们想要扩展一个实体类的功能时(AOP这里不讨论)并且要保证OCP原则(一个软件实体如类,模块和函数应该对扩展开放,对修改关闭)下一般会选择去重写一个类继承当前的类,然后新增加需要的方法。在一般情况下这个当然没问题,但是如果造成一些问题,就是以后每次想要扩展新的功能都必须要新增一个类,这样长此以往的话会造成类过多,并且不能进行随意搭配想要的新功能,在排列组合中假设我们要新增K个功能,然后需要每N个功能相组合如果采用继承的话会产生 C k n C_{k}^{n} Ckn个类,可想而知这不是一个很有成效的办法。
装饰器模式
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂,可读性比较差。
实现
我们将创建一个 Shape 接口和实现了 Shape 接口的实体类。然后我们创建一个实现了 Shape 接口的抽象装饰类 ShapeDecorator,并把 Shape 对象作为它的实例变量。
RedShapeDecorator 是实现了 ShapeDecorator 的实体类。
接下来我们模仿菜鸟教程中的教程演示类使用 RedShapeDecorator 来装饰 Shape 对象。
下面我们就直接上代码啦
下面展示一些
内联代码片
。
最顶层的抽象类“Shape”
package com.meking.decorator;
public interface Shape {
void draw();
}
“Shape”下面的实现“Rectangle”
package com.meking.decorator;
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Rectangle:绘制功能");
}
}
“Shape”下面的实现“Circle”
package com.meking.decorator;
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Circle:绘制功能");
}
}
抽象的装饰器“ShapeDecorator ”
package com.meking.decorator;
public abstract class ShapeDecorator implements Shape {
private Shape shape;
public ShapeDecorator(Shape shape) {
this.shape = shape;
}
@Override
public void draw() {
shape.draw();
}
}
具体的装饰器实现类“RedShapeDecorator”
package com.meking.decorator;
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape shape) {
super(shape);
}
@Override
public void draw() {
super.draw();
setRedBorder();
}
/**
* 设置红色边界的方法
*/
private void setRedBorder(){
System.out.println("设置红色边界");
}
测试
package com.meking.decorator;
public class DecoratorPatternTest {
public static void main(String[] args) {
new RedShapeDecorator(new Rectangle()).draw();
new RedShapeDecorator(new Circle()).draw();
}
}
结果
以上就是我们的测试结果,在装饰模式中我们可以随意搭配需要装饰什么,只需要实现多个不同的装饰器就行了,接下面我们在对功能进行增强。
具体的装饰器实现类“PaddingShapeDecorator”
package com.meking.decorator;
public class PaddingShapeDecorator extends ShapeDecorator {
public PaddingShapeDecorator(Shape shape) {
super(shape);
}
@Override
public void draw() {
super.draw();
setPadding();
}
/**
* 设置填充图案的方法
*/
private void setPadding(){
System.out.println("设置图案填充");
}
}
测试
package com.meking.decorator;
public class DecoratorPatternTest {
public static void main(String[] args) {
//Rectangle设置红色边框
new RedShapeDecorator(new Rectangle()).draw();
System.out.println("-------------11---------------");
//Circl设置红色边框
new RedShapeDecorator(new Circle()).draw();
System.out.println("-------------22---------------");
//Rectangle设置红色边框并且填图案
new PaddingShapeDecorator(new RedShapeDecorator(new Rectangle())).draw();
System.out.println("-------------33---------------");
//Circle设置红色边框并且填图案
new PaddingShapeDecorator(new RedShapeDecorator(new Circle())).draw();
System.out.println("-------------44---------------");
//Rectangle只进行填充
new PaddingShapeDecorator(new Rectangle()).draw();
}
}
结果
总结
装饰器模式是可以随意灵活的进行各种搭配,有效的避开了因为需要各种不同的组合产生太多的继承类这个问题,有不对之处也请各位同学及时指正,有问题的也请各位同学在评论处进行总结。