装饰者模式,顾名思义就是用来对某个事物进行修饰,从而增强它的原本功能。而且这是一种动态的添加,可以多重嵌套,逐级增强。所以说,装饰者提供了比继承更有弹性的替代方案。那么它具体是怎样一种实现方式呢,先看下面这张图:
首先component,这是一个抽象组件,定义了接口方法,每一个组件都可以单独使用,或者被装饰者包装起来使用。concreteComponent组件,对component的简单实现,最终被装饰的对象,也就是我们所说的被装饰者。Decorator装饰者类,这是一个抽象类,被所有具体的装饰者所继承,内部持有一个component组件的引用。conreteDecoratoeA和conreteDecoratorB即使具体的装饰者,可以加上新的行为,增强被装饰者某个具体的功能。这么说可能有点抽象,接下来我们用实际的代码说明具体实现方式:
比如说,我们有一个机器人接口,而且它有一个说话的方法:
public interface Robot {
void speak();
}
好了现在我们先生产一代机器人,只能讲只能讲中文:
public class ChineseRobot implements Robot {
@Override
public void speak() {
System.out.println("speak chinese");
}
}
随着需求的变化,机器人要学习新的语言,英语,法语,日语,而且有每一代机器人可能会的语言还不一样,那么我们就想到了,是不是可以用装饰模式来增强机器人的说话功能呢。说干就干,我们先建一个装饰者:
public abstract class Robot_Decorateor implements Robot {
protected Robot mRobot;
Robot_Decorateor(Robot robot){
mRobot=robot;
}
public abstract void speak();
}
注意这里,我们的装饰者机器人是持有了一个机器人类的引用,这也是我们整个模式的重点所在。
接下来就可以实现很多的机器人类了:
说英语的机器人:
public class EnglishRobot extends Robot_Decorateor {
EnglishRobot(Robot robot) {
super(robot);
// TODO Auto-generated constructor stub
}
@Override
public void speak() {
mRobot.speak();
speakEnglish();
}
public void speakEnglish(){
System.out.println("speak english");
}
}
说法语的机器人:
public class FrenchRobot extends Robot_Decorateor {
FrenchRobot(Robot robot) {
super(robot);
// TODO Auto-generated constructor stub
}
@Override
public void speak() {
mRobot.speak();
speakFrench();
}
public void speakFrench(){
System.out.println(" speak french");
}
}
说日语的机器人:
public class JapaneseRobot extends Robot_Decorateor{
JapaneseRobot(Robot robot) {
super(robot);
// TODO Auto-generated constructor stub
}
@Override
public void speak() {
mRobot.speak();
speakJananese();
}
public void speakJananese(){
System.out.println("speak japanese");
}
}
那么现在我们就可以轻松的让机器人实现说不同的语言:
public class Main {
public static void main(String[] args) {
EnglishRobot robot1 = new EnglishRobot(new FrenchRobot(
new ChineseRobot()));
FrenchRobot robot2 = new FrenchRobot(new JapaneseRobot(
new ChineseRobot()));
JapaneseRobot robot3 = new JapaneseRobot(new EnglishRobot(
new ChineseRobot()));
System.out.println("机器人1说了:");
robot1.speak();
System.out.println("机器人2说了:");
robot2.speak();
System.out.println("机器人3说了:");
robot3.speak();
}
}
结果如下:
就是这样,如果有新的语言要学习,我们可以在建一个具体的装饰类来实现,逐级增强机器人的说话功能。是不是感觉很熟悉,没错,我们经常使用的缓冲io流就是这样的一直设计方式。
装饰者模式的设计原则为:对扩展开展,对修改关闭。也就是说如果我们想扩展被装饰类的行为,不需要去修改抽象装饰者,只需要对其进行继承,添加额外的一些装饰或者叫行为即可对被装饰者进行包装。所以扩展体现着继承,修改体现在子类的实现,这就是我所理解的装饰者模式。