定义:Decorator装饰器,顾名思义,就是动态地给一个对象添加一些额外的职责,就好比为房子进行装修一样。因此,装饰器模式具有如下的特征:
它必须具有一个装饰的对象。
它必须拥有与被装饰对象相同的接口。
它可以给被装饰对象添加额外的功能。
用一句话总结就是:保持接口,增强性能。
装饰器通过包装一个装饰对象来扩展其功能,而又不改变其接口,这实际上是基于对象的适配器模式的一种变种。它与对象的适配器模式的异同点如下。
相同点:都拥有一个目标对象。
不同点:适配器模式需要实现另外一个接口,而装饰器模式必须实现该对象的接口。
重点理解:1、知道哪个是被装饰的对象,哪个是装饰器;
2、重中之重:一定要明确传给装饰器的对象,比如下面代码中,如果你是一步一步装饰,切记你一定要把前一步装饰后的对象传给下一步进行装饰的装饰器;否则就达不到所有装饰的效果。朋友们可以下去自己试试,如果把传下面这些装饰器类中的对象改成source,是不会保存上一次装饰效果的。切记!!!
// 不满意?行,咱们继续进行装饰,还是得花钱,给装修房子再增加3K
SourceI source1w5 = new Decorator1W5(source1w2);
// 房子第二次装饰好了,再看看1W5的房子满意不
System.out.println("----第二次装饰完毕,房子信息如下:----");
source1w5.build();
// 还不满意?你真挑,不过没关系,咱们有钱,再加点,给装修房子再增加3K
SourceI source1w8 = new Decorator1W8(source1w5);
// 房子第一次装饰好了,再看看1W2的房子满意不
System.out.println("----第三次装饰完毕,房子信息如下:----");
source1w8.build();
实例:亲自监督经历过装修房子事宜,特用该经历举例。
------------接口实现:
//装修房子操作封装
public interface SourceI {
public void build();
}
//装饰对象原始类--房子被装修公司按1W元协议进行半包装修
public class SourceImp implements SourceI {
@Override
public void build() {
// TODO Auto-generated method stub
System.out.println("弄水电");
System.out.println("粉刷墙壁");
System.out.println("铲墙皮");
}
}
//装饰器类--1W2装修公司增加服务
public class Decorator1W2 implements SourceI {
private SourceI source=new SourceImp();
public Decorator1W2(SourceI source){
this.source=source;
}
@Override
public void build() {
// TODO Auto-generated method stub
source.build();
this.buildExtra();
}
public void buildExtra(){
System.out.println("1W2服务增加,房子增加灯饰");
}
}
//装饰器类--1W5装修公司增加服务
public class Decorator1W5 implements SourceI {
private SourceI source=new SourceImp();
public Decorator1W5(SourceI source){
this.source=source;
}
@Override
public void build() {
// TODO Auto-generated method stub
source.build();
this.buildExtra();
}
public void buildExtra(){
System.out.println("1W5服务增加,房子增加壁纸");
}
}
//装饰器类--1W8装修公司增加服务
public class Decorator1W8 implements SourceI {
private SourceI source=new SourceImp();
public Decorator1W8(SourceI source){
this.source=source;
}
@Override
public void build() {
// TODO Auto-generated method stub
source.build();
this.buildExtra();
}
public void buildExtra(){
System.out.println("1W8服务增加,房子增加木地板");
}
}
public class DecoratorTest {
/**
* @param args
*/
public static void main(String[] args) {
// 首先,肯定是得把毛坯房进行基本装修,也就是装修对象肯定是唯一的
SourceI source = new SourceImp();
// 房子装修好了,基本装修,一分价钱一分货,让我们看看1W的房子满意不
System.out.println("----房子基础装修完毕,房子信息如下:----");
source.build();
// 不满意?行,咱们进行装饰,不过当然得花钱,给装修房子增加2K
SourceI source1w2 = new Decorator1W2(source);
// 房子第一次装饰好了,再看看1W2的房子满意不
System.out.println("----第一次装饰完毕,房子信息如下:----");
source1w2.build();
// 不满意?行,咱们继续进行装饰,还是得花钱,给装修房子再增加3K
SourceI source1w5 = new Decorator1W5(source1w2);
// 房子第二次装饰好了,再看看1W5的房子满意不
System.out.println("----第二次装饰完毕,房子信息如下:----");
source1w5.build();
// 还不满意?你真挑,不过没关系,咱们有钱,再加点,给装修房子再增加3K
SourceI source1w8 = new Decorator1W8(source1w5);
// 房子第一次装饰好了,再看看1W2的房子满意不
System.out.println("----第三次装饰完毕,房子信息如下:----");
source1w8.build();
//当然啦,如果有钱淫,直接一次性就定制1W8的服务,给你的房子跟分三次装饰后的房子
//信息是一样的,但是一次性服务的话,装修公司必须一次性到位,这个时候装饰公司是这样子的
SourceI sourceObj =new Decorator1W8(new Decorator1W5(new Decorator1W2(source)));
System.out.println("----装修公司服务一次性到位,房子信息如下:----");
sourceObj.build();
}
}
---------------抽象类实现:
//装修房子操作封装
public abstract class AbstractSource {
public abstract void build();
}
//装饰对象原始类--房子被装修公司按1W元协议进行半包装修
public class SourceImp extends AbstractSource {
@Override
public void build() {
// TODO Auto-generated method stub
System.out.println("弄水电");
System.out.println("粉刷墙壁");
System.out.println("铲墙皮");
}
}
//装饰器类--1W2装修公司增加服务
public class Decorator1W2 extends AbstractSource {
private AbstractSource source=new SourceImp();
public Decorator1W2(AbstractSource source){
this.source=source;
}
@Override
public void build() {
// TODO Auto-generated method stu
source.build();
this.buildExtra();
}
public void buildExtra(){
System.out.println("1W2服务增加,房子增加灯饰");
}
}
//装饰器类--1W5装修公司增加服务
public class Decorator1W5 extends AbstractSource {
private AbstractSource source=new SourceImp();
public Decorator1W5(AbstractSource source){
this.source=source;
}
@Override
public void build() {
// TODO Auto-generated method stu
source.build();
this.buildExtra();
}
public void buildExtra(){
System.out.println("1W5服务增加,房子增加壁纸");
}
}
//装饰器类--1W8装修公司增加服务
public class Decorator1W8 extends AbstractSource {
private AbstractSource source=new SourceImp();
public Decorator1W8(AbstractSource source){
this.source=source;
}
@Override
public void build() {
// TODO Auto-generated method stu
source.build();
this.buildExtra();
}
public void buildExtra(){
System.out.println("1W8服务增加,房子增加木地板");
}
}
public class DecoratorTest {
/**
* @param args
*/
public static void main(String[] args) {
// 首先,肯定是得把毛坯房进行基本装修,也就是装修对象肯定是唯一的
AbstractSource source = new SourceImp();
// 房子装修好了,基本装修,一分价钱一分货,让我们看看1W的房子满意不
System.out.println("----房子基础装修完毕,房子信息如下:----");
source.build();
// 不满意?行,咱们进行装饰,不过当然得花钱,给装修房子增加2K
AbstractSource source1w2 = new Decorator1W2(source);
// 房子第一次装饰好了,再看看1W2的房子满意不
System.out.println("----第一次装饰完毕,房子信息如下:----");
source1w2.build();
// 不满意?行,咱们继续进行装饰,还是得花钱,给装修房子再增加3K
AbstractSource source1w5 = new Decorator1W5(source1w2);
// 房子第二次装饰好了,再看看1W5的房子满意不
System.out.println("----第二次装饰完毕,房子信息如下:----");
source1w5.build();
// 还不满意?你真挑,不过没关系,咱们有钱,再加点,给装修房子再增加3K
AbstractSource source1w8 = new Decorator1W8(source1w5);
// 房子第一次装饰好了,再看看1W2的房子满意不
System.out.println("----第三次装饰完毕,房子信息如下:----");
source1w8.build();
//当然啦,如果有钱淫,直接一次性就定制1W8的服务,给你的房子跟分三次装饰后的房子
//信息是一样的,但是一次性服务的话,装修公司必须一次性到位,这个时候装饰公司是这样子的
AbstractSource sourceObj =new Decorator1W8(new Decorator1W5(new Decorator1W2(source)));
System.out.println("----装修公司服务一次性到位,房子信息如下:----");
sourceObj.build();
}
}
运行结果: