装饰器模式,听名字就知道是在原来的上面加点东西。在原类上加点东西,是不是让你想到了什么,对了,就是继承。那么他和继承的优劣是什么呢?面向对象的23种设计模式点这里。我们可以先看一下装饰器完整示例代码:
public class Decorator {
public interface Color {//颜色接口,可返回任意颜色
String draw();
}
public static class RedColor implements Color {
@Override
public String draw() {
return "红色";
}
}
public static class BlueColor implements Color {
@Override
public String draw() {
return "蓝色";
}
}
public static abstract class ColorDecorator implements Color {//抽象装饰器,也可实现正方体
protected Color decoratedColor;
public ColorDecorator(Color decoratedColor) {
this.decoratedColor = decoratedColor;
}
public String draw() {
return decoratedColor.draw();
}
}
public static class BallColorDecorator extends ColorDecorator {
public BallColorDecorator(Color decoratedColor) {
super(decoratedColor);
}
@Override
public String draw() {
String a = "画个" + super.draw() + "球";
System.out.println(a);
return a;
}
}
public static void main(String[] args) {
Color red = new BallColorDecorator(new RedColor());
red.draw();
Color blue = new BallColorDecorator(new BlueColor());
blue.draw();
}
}
输出:
画个红色球
画个蓝色球
这个实现没啥好说的,但是我们要讨论的是装饰器模式的适用场景。即他和继承到底有什么不同,像这种画圆球红球的用属性更简单,代码如下:
public class Decorator {
public static class SimpleObject {
private String name;
private String color;
public SimpleObject(String name, String color) {
this.name = name;
this.color = color;
}
public String draw() {
return "画个" + color + name;
}
}
public static void main(String[] args) {
System.out.println(new SimpleObject("球", "红色").draw());
System.out.println(new SimpleObject("球", "蓝色").draw());
}
}
可以看出,如果是物体固有的性质。我们应该将他们设置成属性,但是不是固有的。那它的适应场景是什么呢,前面说到了继承,所以就是在原类继承不了或继承实现复杂时使用。我们知道像String这样final类是继承不了的。
public class Decorator {
public static class myString {
private String string;
public myString(String string) {
this.string = string;
}
public myString(char value[]) {
this.string = new String(value);
}
public String[] split(String regex, int limit) {
return string.split(regex, limit);
}
//.............中间省略n行,每个方法都要调用原方法
//我们更改toString方法
public String toString() {
return "myString:" + string;
}
}
public static void main(String[] args) {
String a = "haha";
System.out.println(a);
System.out.println(new myString(a));
}
}
输出:
haha
myString:haha
可以看到,我们终于可以继承String类了。但缺点也很明显,我要实现原类的每个方法。写哭了有没有。其实继承原类也是子类会有父类的一个引用。只不过方法调用啥的是jvm自动判断的。。还有个和它很像的代理模式。