欢迎大家提出意见,一起讨论!
转载请标明是引用于 http://blog.csdn.net/chenyujing1234
例子代码:(编译工具:Eclipse)
http://www.rayfile.com/zh-cn/files/1291b5bd-9418-11e1-b6a1-0015c55db73d/
参考书籍: <<软件秘笈-----设计模式那点事>>
装饰者模式(Decorator ['dekəreitə] Pattren),是在不改变原类文件和使用继承的情况下,动态地扩展一个对象的功能,它是通过创建一个包装对象,也就是
装饰来包裹真实的对象。
/**
* 馒头加工接口
*
* @author
*
*/
public interface IBread {
// 准备材料
public void prepair();
// 和面
public void kneadFlour();
// 蒸馒头
public void steamed();
/**
* 加工馒头方法
*/
public void process();
}
/**
* 正常馒头的实现
*
* @author
*
*/
public class NormalBread implements IBread {
// 准备材料
public void prepair() {
System.out.println("准备面粉、水以及发酵粉...");
}
// 和面
public void kneadFlour() {
System.out.println("和面...");
}
// 蒸馒头
public void steamed() {
System.out.println("蒸馒头...香喷喷的馒头出炉了!");
}
/**
* 加工馒头方法
*/
public void process() {
// 准备材料
prepair();
// 和面
kneadFlour();
// 蒸馒头
steamed();
}
}
/**
* 染色的玉米馒头
*
* @author
*
*/
public class CornBread extends NormalBread {
// 黑心商贩 开始染色了
public void paint() {
System.out.println("添加柠檬黄的着色剂...");
}
// 重载父类的和面方法
@Override
public void kneadFlour() {
// 在面粉中加入 染色剂 之后才开始和面
this.paint();
// 和面
super.kneadFlour();
}
}
/**
* 甜蜜素馒头
*
* @author
*
*/
public class SweetBread extends NormalBread {
// 黑心商贩 开始添加甜蜜素
public void paint() {
System.out.println("添加甜蜜素...");
}
// 重载父类的和面方法
@Override
public void kneadFlour() {
// 在面粉中加入 甜蜜素 之后才开始和面
this.paint();
// 和面
super.kneadFlour();
}
}
/**
* 抽象装饰者
*
* @author
*
*/
public abstract class AbstractBread implements IBread {
// 存储传入的IBread对象
private final IBread bread;
public AbstractBread(IBread bread) {
this.bread = bread;
}
// 准备材料
public void prepair() {
this.bread.prepair();
}
// 和面
public void kneadFlour() {
this.bread.kneadFlour();
}
// 蒸馒头
public void steamed() {
this.bread.steamed();
}
// 加工馒头方法
public void process() {
prepair();
kneadFlour();
steamed();
}
}
/**
* 染色的玉米馒头
*
* @author
*
*/
public class CornDecorator extends AbstractBread {
// 构造方法
public CornDecorator(IBread bread) {
super(bread);
}
// 黑心商贩 开始染色了
public void paint() {
System.out.println("添加柠檬黄的着色剂...");
}
// 重载父类的和面方法
@Override
public void kneadFlour() {
// 在面粉中加入 染色剂 之后才开始和面
this.paint();
// 和面
super.kneadFlour();
}
}
/**
* 甜蜜素馒头
*
* @author
*
*/
public class SweetDecorator extends AbstractBread {
// 构造方法
public SweetDecorator(IBread bread) {
super(bread);
}
// 黑心商贩 开始添加甜蜜素
public void paint() {
System.out.println("添加甜蜜素...");
}
// 重载父类的和面方法
@Override
public void kneadFlour() {
// 在面粉中加入 甜蜜素 之后才开始和面
this.paint();
// 和面
super.kneadFlour();
}
}
/**
* 客户端应用程序
*
* @author
*
*/
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// 生产装饰馒头
System.out.println("\n====开始装饰馒头!!!");
// 创建普通的正常馒头实例
// 这是我们需要包装(装饰)的对象实例
IBread normalBread = new NormalBread();
// 下面就开始 对正常馒头进行装饰了!!!
// 使用甜蜜素装饰馒头
normalBread = new SweetDecorator(normalBread);
// 使用柠檬黄的着色剂装饰馒头
normalBread = new CornDecorator(normalBread);
// 生产馒头信息
normalBread.process();
System.out.println("====装饰馒头结束!!!");
}
}
====开始装饰馒头!!!
准备面粉、水以及发酵粉...
添加柠檬黄的着色剂...
添加甜蜜素...
和面...
蒸馒头...香喷喷的馒头出炉了!
====装饰馒头结束!!!
装饰者模式应用中“变化”的部分是组件的扩展功能,装饰者和被装饰者完全隔离开来,这样我们就可以任意地改变装饰者和被装饰者。
我们在需要对组件进行扩展、增添新的功能行为时,只需要实现一个特定的装饰者即可,这完全是增量修改,
对原有软件功能结构没有影响,对客户端APP来说也是完全透明的,不必关心内部实现细节。
在装饰者模式中,装饰者角色就是抽象类实现,面向抽象编程的好处就在于起到了很好的接口隔离作用。在运用时,
我们具体操作的也是抽象类引用,这些显示了面向抽象编程。
装饰者模式最成功在于合理地使用了对象组合方式,通过组合灵活地扩展了组件的功能,所有的扩展功能都是通过组合而非继承获得的,
这从根本上决定了是高内聚、低耦合的。
(2)当某个对象的职责经常发生变化或者经常需要动态地增加职责,避免为了适应这样的变化而增加继承子类扩展的方式,因为这种方式会造成子类膨胀的速度过快,难以控制,此时可以使用装饰者模式。
客户端不会觉得对象在装饰前和装饰后有什么不同,装饰者模式可以在不创建更多子类的情况下,将对象的功能加以扩展,装饰者模式使用原来被装饰的一个子类实例,
把客户端的调用委派到装饰者。
下面我们来看一下装饰者模式的静态类图.使我们对装饰者模式有一个更加清晰的认识
A、被装饰者抽象Component:是一个接口或抽象类,是定义的核心对象。
在装饰者模式中,必然有一个被撮出来最核心、最原始的接口。这个类就是我们需要装饰类的基类。本例中是IBread接口。
B、被装饰者具体实现ConcreteComponent:这是Component类的一个实现类,我们要装饰的就是这个具体的实现类。本例中是NormalBread
C、装饰者Decorator:一般是一个抽象类。它里面有一个指向Component变量的引用。
D、装饰者实现ConcreteDecorator1和ConcreteDecorator2.