前言:
装饰模式是动态的给一些对象添加一些职责,通过装饰模式比生成子类更灵活。就增加功能来说,装饰模式比生成子类更灵活。
一.装饰模式的简介
装饰模式是为已有的功能添加更多功能的一种方式。
应用场景: 系统需要新功能,向旧的类中增加代码,来装饰旧类的核心职责,这些功能可能是只在特殊情况下才执行的,所以增加了旧类的复杂度。而装饰模式把每个要增加的功能,单独的放在类中,用这个类包装它想要装饰的对象,当需要执行特殊行为时,可以有选择、有顺序的使用装饰功能包装对象。
二.装饰模式的实现:
案例:给葫芦娃装扮衣物,登台亮相。
1. 装饰模式UML类图:
2. 被装饰对象的抽象类:
Component类定义一个对象抽象类(也可是接口),给这些对象动态的添加职责。
如果有多个被装饰类,用此类作为被装饰类的父类,如果只有一个被装饰类可以省略,直接让Decorator类继承Concrete Component类即可。
package com.pattern.component;
/**
* 被装饰对象的抽象类(也可用接口)
* @author 葫芦娃
* @see 所有被装饰对象的抽象父类
*/
public abstract class Component {
public abstract void show();
}
3.被装饰类:
定义类一些具体的对象,可以给这些对象添加一些职责。
package com.pattern.component;
/**
* 被装饰类(Concrete Component)
*
* @author 葫芦娃
* @see 这里只展示被装饰类中的一个
*/
public class Person extends Component {
private String name;
public Person(String name) {
this.name = name;
}
/**
* 继承父类方法
*/
@Override
public void show() {
System.out.println(name + ",开始装扮");
};
}
4.装饰抽象类:
继承了Component从外类扩展Component类的功能。对于Component类来说,无需知道Decorator的存在。
package com.pattern.decorator;
import com.pattern.component.Component;
/**
* 装饰类的抽象类
* @author 葫芦娃
*
*/
public abstract class Decorator extends Component {
protected Component component;//具体的被装饰者对象
//装饰方法
public void decorate(Component component) {
this.component = component;
}
/**
* 装饰类是为了实现被装饰者中的show方法,实现装饰,所以要继承父类。
*/
@Override
public void show() {
if (null != component) {
component.show();
}
}
}
5.具体的装饰实现类:
这些具体装饰类(concrete decorator),是具体的装饰对象,用来给Component添加职责功能。
T恤装扮类:
可以在此concrete decorator类中增加自有的属性和方法,再执行完super.show()方法后执行。
package com.pattern.decorator;
/**
* T恤装扮类(具体装扮类)
* @author 葫芦娃
*
*/
public class Tshirt extends Decorator {
//重写父类的装饰方法
@Override
public void show() {
super.show();
System.out.println("装扮上T恤");
}
}
裤子装扮类:
package com.pattern.decorator;
/**
* 裤子装饰类(具体的装饰类)
* @author 葫芦娃
*
*/
public class Trousers extends Decorator {
//重写父类的装饰方法
@Override
public void show() {
super.show();
System.out.println("装扮上了裤子");
}
}
腰带装扮类:
package com.pattern.decorator;
/**
* 藤蔓腰带装扮类(具体装扮类)
* @author 葫芦娃
*
*/
public class VineBelt extends Decorator {
//重写父类的装饰方法
@Override
public void show() {
super.show();
System.out.println("装扮上藤蔓腰带");
}
}
6.客户端:
在此只展示了一套装扮,可以多增加几个Concrete decorator类,按不同的需求来装扮
package com.pattern.client;
import com.pattern.component.Person;
import com.pattern.decorator.Trousers;
import com.pattern.decorator.Tshirt;
import com.pattern.decorator.VineBelt;
/**
* 客户端
* @author 葫芦娃
*
*/
public class Client {
public static void main(String[] args) {
// 初始化被装饰者
Person baby = new Person("葫芦娃");
// 初始化各种装饰类
Tshirt tshirt = new Tshirt();
Trousers trousers = new Trousers();
VineBelt belt = new VineBelt();
// 开始装扮,对客户端隐藏具体装扮过程
tshirt.decorate(baby);
trousers.decorate(tshirt);
belt.decorate(trousers);
// 调用一次展示方法即可。而不是装扮一次,show一次
belt.show();
}
}
7.运行结果:
葫芦娃,开始装扮
装扮上T恤
装扮上了裤子
装扮上藤蔓腰带
三. 总结:
1.装饰模式把类的核心功能和装饰功能区分开,简化了原有的类,并且去除了相关类中的重复装饰逻辑。
2.装饰类之间的独立,可以随便调换装饰的顺序,任意组合使用。如对数据的过滤后在加密,就可分别封装在两个不同的装饰类中使用。