装饰模式
装饰模式又名包装(Wrapper)模式。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
定义:动态给一个对象添加一些额外的职责,使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。
设计初衷:通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的。
装饰模式的结构
装饰模式使用原来被装饰的类的一个子类的实例,把客户端的调用委派到被装饰类。装饰模式的关键在于这种扩展是完全透明的。
装饰模式类图如下:
在装饰模式中的角色有:
● 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
● 具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类。
● 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
● 具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。
源代码:
/**
* @author: Col.Mai
* @date:2014-9-23 下午11:07:34
* @description :<p>抽象角色构件</P>
**/
public interface Component {
void sampleOperation();
}
/**
* @author: Col.Mai
* @date:2014-9-23 下午11:08:40
* @description :<p>具体构件角色</P>
**/
public class ConcreteComponent implements Component {
public void sampleOperation() {
//TODO 写相关业务代码
}
}
/**
* @author: Col.Mai
* @date:2014-9-23 下午11:09:58
* @description :<p>装饰角色</P>
**/
public class Decorator implements Component {
private Component component;
public void sampleOperation() {
// 委派给构件
component.sampleOperation();
}
public Decorator(Component component){
this.component = component;
}
}
/**
* @author: Col.Mai
* @date:2014-9-23 下午11:13:36
* @description :<p>具体装饰角色</P>
**/
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
@Override
public void sampleOperation() {
super.sampleOperation();
// 写相关的业务代码
}
}
- 在上面的装饰类里,有一个私有的属性component,其数据类型是构件(Component)
- 此装饰类实现了构件(Component)接口
- 接口的方法也值得注意,每一个实现类的方法都委派给父类,但并不单纯地委派,而是有功能增强。
下面举个简单的例子,我记的我小时候看过一个动画片叫《战神金刚》,当时非常喜欢看,放学后就盯着电视连饭都不吃,为此没少挨揍,这个动画片讲的是几个小朋友团队合作组成战神金刚消灭强大的敌人,在组成战神金刚前,他们分别是单独的对象,在组成时他们分别组成身体、头部、腿部、手部从而完成战神金刚(时间久远具体剧情也忘记了,组成部分只是靠回忆猜测,不要在意这些细节,主要是以此为例)。
类图如下:
代码如下:
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:39:24
* @description :<p>抽象构件角色(战神金刚)</P>
**/
public interface Robot {
/**
* 组成某个部位
*/
void composition();
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:49:27
* @description :<p>具体构件角色</P>
**/
public class ConcreteRobot implements Robot{
public void composition() {
System.out.println("组成战神金刚!");
}
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午1:18:48
* @description :<p>装饰者角色</P>
**/
public class Decorator implements Robot{
private Robot robot;
public Decorator(Robot robot){
this.robot = robot;
}
public void composition() {
robot.composition();
}
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:47:06
* @description :<p>装饰身体</P>
**/
public class Decorator4Body extends Decorator {
public Decorator4Body(Robot robot) {
super(robot);
}
public void composition() {
System.out.println("我来组成身体!");
super.composition();
}
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:47:28
* @description :<p>装饰手部</P>
**/
public class Decorator4Hand extends Decorator {
public Decorator4Hand(Robot robot) {
super(robot);
}
public void composition() {
System.out.println("我来组成手部!");
super.composition();
}
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:44:20
* @description : <p> 装饰头部 </P>
**/
public class Decorator4Head extends Decorator {
public Decorator4Head(Robot robot) {
super(robot);
}
public void composition() {
System.out.println("我来组成头部!");
super.composition();
}
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:46:27
* @description :<p>装饰腿部</P>
**/
public class Decorator4Leg extends Decorator{
public Decorator4Leg(Robot robot) {
super(robot);
}
public void composition() {
System.out.println("我来组成腿部!");
super.composition();
}
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:55:34
* @description :<p>xxx功能描述</P>
**/
public class Client {
public static void main(String [] args){
Robot robot = new ConcreteRobot();
Robot obj = new Decorator4Body(new Decorator4Head(new Decorator4Leg(new Decorator4Hand(robot))));
obj.composition();
}
}
我来组成身体!
我来组成头部!
我来组成腿部!
我来组成手部!
组成战神金刚!
装饰模式的简化
大多数情况下,装饰模式的实现都要比上面给出的示意性例子要简单。
有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。甚至在只有两个ConcreteDecorator类的情况下,都可以这样做。如下图所示:
还是组成《战神金刚》的例子,看我们简化后如何做。
类图如下:
源码:
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:39:24
* @description :<p>抽象构件角色(战神金刚)</P>
**/
public interface Robot {
/**
* 组成某个部位
*/
void composition();
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:49:27
* @description :<p>具体构件角色</P>
**/
public class ConcreteRobot implements Robot{
public void composition() {
System.out.println("组成战神金刚!");
}
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:47:06
* @description :<p>装饰身体</P>
**/
public class Decorator4Body implements Robot {
private Robot robot;
public Decorator4Body(Robot robot) {
this.robot = robot;
}
public void composition() {
System.out.println("我来组成身体!");
robot.composition();
}
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:47:28
* @description :<p>装饰手部</P>
**/
public class Decorator4Hand implements Robot {
private Robot robot;
public Decorator4Hand(Robot robot) {
this.robot = robot;
}
public void composition() {
System.out.println("我来组成手部!");
robot.composition();
}
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:44:20
* @description : <p> 装饰头部 </P>
**/
public class Decorator4Head implements Robot {
private Robot robot;
public Decorator4Head(Robot robot) {
this.robot = robot;
}
public void composition() {
System.out.println("我来组成头部!");
robot.composition();
}
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:46:27
* @description :<p>装饰腿部</P>
**/
public class Decorator4Leg implements Robot {
private Robot robot;
public Decorator4Leg(Robot robot) {
this.robot = robot;
}
public void composition() {
System.out.println("我来组成腿部!");
robot.composition();
}
}
/**
* @author: Col.Mai
* @date:2014-9-26 上午12:55:34
* @description :<p>xxx功能描述</P>
**/
public class Client {
public static void main(String [] args){
Robot robot = new ConcreteRobot();
Robot obj = new Decorator4Body(new Decorator4Head(new Decorator4Leg(new Decorator4Hand(robot))));
obj.composition();
}
}
输出
我来组成身体!
我来组成头部!
我来组成腿部!
我来组成手部!
组成战神金刚!