一、场景

增加车的功能

二、实质

动态的为一个对象增加新的功能,是一种​用于代替继承的技术​,无须通过继承增加新的子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,​同时避免类型体系的快速膨胀。


三、实现细节

Component抽象构件角色

真实对象与装饰对象有相同的接口,这样客户端对象就能够以​与真实对象相同的方式​同装饰对象交互。

ConcreteComponent具体构件角色(真实对象)

Decorator装饰角色

持有一个抽象构件的引用​,装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象,这样就能在真实对象调用前后增加新的功能。

ConcreteDecorator具体装饰角色

负责给构件对象增加新的责任。

四、示例

实例1


package IOOthers;

public class Voice {
private int voice = 10;
public Voice() {
}
public Voice(int voice) {
super();
this.voice = voice;
}
public int getVoice() {
return voice;
}
public void setVoice(int voice) {
this.voice = voice;
}
public void say()
{
System.out.println(voice);
}
}


class Amplifier {
private Voice voice;
public Amplifier() {
}
public Amplifier(Voice voice) {
super();
this.voice = voice;
}
public void say()
{
System.out.println(voice.getVoice()*1000);
}
}



package IOOthers;

/**
* 扩音器
* 类与类之间的关系
* 1、依赖:形参|局部变量
* 2、关联:属性
* 聚合:属性 整体与部分 不一致的生命周期 人与手
* 组合:属性 整体与部分 一致的生命周期 人与大脑
* 3、继承:父子类关系
* 4、实现:接口与实现类关系
*/

public class Demo09 {
public static void main(String[] args) {
Voice v = new Voice(20);
v.say();
Amplifier am = new Amplifier(v);
am.say();
}
}



运行结果:

20

20000


实例2

设计模式学习笔记---装饰模式decorator(Java版)_装饰模式

package com.lgd.decorator;
/**
* 抽象组件
* @author liguodong
*
*/
public interface ICar {
void move();
}

//具体构建对象(真实对象)
class Car implements ICar{

@Override
public void move() {
// TODO Auto-generated method stub
System.out.println("陆地上跑");
}

}

//装饰器角色
class SuperCar implements ICar{
private ICar car;

public SuperCar(ICar car) {
super();
this.car = car;
}

@Override
public void move() {
// TODO Auto-generated method stub
car.move();
}

}

//具体装饰角色
class FlyCar extends SuperCar{

public FlyCar(ICar car) {
super(car);
// TODO Auto-generated constructor stub
}

public void fly(){
System.out.println("天上飞");
}

@Override
public void move() {
// TODO Auto-generated method stub
super.move();
fly();
}
}


//具体装饰角色
class WaterCar extends SuperCar{

public WaterCar(ICar car) {
super(car);
// TODO Auto-generated constructor stub
}

public void Water(){
System.out.println("水上游");
}

@Override
public void move() {
// TODO Auto-generated method stub
super.move();
Water();
}
}

//具体装饰角色
class AICar extends SuperCar{

public AICar(ICar car) {
super(car);
// TODO Auto-generated constructor stub
}

public void AI(){
System.out.println("自动跑");
}

@Override
public void move() {
// TODO Auto-generated method stub
super.move();
AI();
}
}



package com.lgd.decorator;

import java.awt.CardLayout;


public class Client {
public static void main(String[] args) {
Car car = new Car();
car.move();

System.out.println("增加新的功能,飞行-----");
FlyCar flyCar = new FlyCar(car);
flyCar.move();

System.out.println("增加新的功能,水里游-----");
WaterCar waterCar = new WaterCar(car);
waterCar.move();

System.out.println("增加新的功能,水里游天上飞-----");
WaterCar waterflyCar = new WaterCar(new FlyCar(new Car()));
waterflyCar.move();
}
}



运行结果:

陆地上跑

增加新的功能,飞行-----

陆地上跑

天上飞

增加新的功能,水里游-----

陆地上跑

水上游

增加新的功能,水里游天上飞-----

陆地上跑

天上飞

水上游



五、应用场景

IO中的输入流和输出流的设计

Swing包中图形界面构建功能

Servlet API中提供了一个request对象的Decoratot设计模式的默认实现类HttpServletRequestWrapper,增强了request的功能。

Struct2中,request,response,session对象的处理

六、总结

装饰模式(Decorator)也叫包装器模式(Wrapper)

装饰模式降低了系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,一边增加新的具体构建类和具体装饰类。

优点:

扩展对象功能,比继承灵活,不会导致类个数的急剧增加。

可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更强大的对象。

具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类。


缺点:

产生很多小的对象,大量小对象占据内存,一定程度上影响性能。

装饰模式易于出错,调试排查比较麻烦。


七、装饰模式和桥接模式的区别

都是为了解决多子类对象问题,但他们的诱因不一样。

桥接模式是对象自身现有机制沿着多个维度变化,是有部分不稳定。

装饰模式是为了增加新的功能。