定义
动态的给一个对象添加一些额外的职责。比用继承生成子类更灵活。
不改变原有对象的基础上,将功能附加到对象上。
比继承更有弹性。
适用场景
动态的增加/撤销一个类的功能。
优缺点
是继承的有力补充,比继承灵活,不改变原有对象,同时扩展功能。
通过适用不同装饰类以及这些装饰类的排列组合,可以实现不同的效果。
但是会出现更多的代码、类。多层装饰时,会更复杂。
UML
public abstract class Component {
abstract void operate();
}
class ConcreteComponent1 extends Component{
@Override
void operate() {
System.out.println("do something1");
}
}
class ConcreteComponent2 extends Component{
@Override
void operate() {
System.out.println("do something2");
}
}
abstract class Decorator extends Component{
Component c;
Decorator(Component c){
this.c = c;
}
}
class ConcreteDecorator1 extends Decorator{
ConcreteDecorator1(Component c){
super(c);
}
@Override
void operate() {
System.out.println("装饰一下");
c.operate();
}
}
class ConcreteDecorator2 extends Decorator{
ConcreteDecorator2(Component c){
super(c);
}
@Override
void operate() {
System.out.println("再装饰一下");
c.operate();
}
}
class Test{
public static void main(String[] args) {
new ConcreteDecorator1(new ConcreteDecorator2(new ConcreteComponent1())).operate();
}
}
示例1
玩过红警的都知道。如果想造一个超级坦克兼具光棱和天启的特性。
public abstract class Tank {
public abstract void fire();
public static void main(String[] args) {
Tank t1 = new Tank1();
t1 = new TianQiTankDecorator(new GuangLengTankDecorator(t1));
t1.fire();
}
}
class Tank1 extends Tank{
@Override
public void fire() {
System.out.println("普通坦克射击");
}
}
abstract class TankDecorator extends Tank{
abstract void doSomething();
}
class TianQiTankDecorator extends TankDecorator{
Tank t;
TianQiTankDecorator(Tank t){
this.t = t;
}
@Override
public void fire() {
doSomething();
t.fire();
}
@Override
void doSomething() {
System.out.println("天启坦克射击");
}
}
class GuangLengTankDecorator extends TankDecorator{
Tank t;
GuangLengTankDecorator(Tank t){
this.t = t;
}
@Override
public void fire() {
doSomething();
t.fire();
}
@Override
void doSomething() {
System.out.println("光棱坦克射击");
}
}
注意装饰者和被装饰者都有共同的父类。
示例2
public interface IFunction {
// 查看角色装备详情的方法
String select();
String add();
String hit();
String dazhao();
}
abstract class AbstractRoleDecorate implements IFunction {
private IFunction target;
public AbstractRoleDecorate(IFunction target) {
this.target = target;
}
@Override
public String select() {
// 调用具体被装饰后的类的方法
return target.select();
}
@Override
public String add() {
return null;
}
@Override
public String hit() {
return null;
}
@Override
public String dazhao() {
return null;
}
}
class HairDecoration extends AbstractRoleDecorate {
public HairDecoration(IFunction target) {
super(target);
}
@Override
public String select() {
return super.select() + " 戴上头发 ";
}
}
class JacketDecoration extends AbstractRoleDecorate {
public JacketDecoration(IFunction target) {
super(target);
}
@Override
public String select() {
return super.select() + " 穿上衣服 ";
}
}
class PlantDecoration extends AbstractRoleDecorate {
public PlantDecoration(IFunction target) {
super(target);
}
@Override
public String select() {
return super.select() + " 穿上裤子 ";
}
}
class ShoesDecoration extends AbstractRoleDecorate {
public ShoesDecoration(IFunction target) {
super(target);
}
@Override
public String select() {
return super.select() + " 穿上鞋子 ";
}
}
class GM implements IFunction {
@Override
public String select() {
return "超管 ";
}
@Override
public String add() {
return null;
}
@Override
public String hit() {
return null;
}
@Override
public String dazhao() {
return null;
}
}
class Magic implements IFunction {
@Override
public String select() {
return " 法师 ";
}
@Override
public String add() {
return null;
}
@Override
public String hit() {
return null;
}
@Override
public String dazhao() {
return null;
}
}
class DecoratorTests {
public static void main(String[] args) {
// 创建法师角色
IFunction target = new Magic();
// 爆了鞋子,穿上鞋子
target = new PlantDecoration(target);
// 查看装备
System.out.println(target.select());
// 爆了头发,戴上头发
target = new HairDecoration(target);
System.out.println(target.select());
// GM
IFunction gm =
new ShoesDecoration(
new HairDecoration(
new PlantDecoration(
new JacketDecoration(new GM()))));
System.out.println("gm:"+gm.select());
}
}
示例3
FilterInputStream是装饰者,InputStream是总的抽象接口,FileInputStream和ByteArrayInputStream都是被装饰者。
使用方式:
DataInputStream dis = new DataInputStream(new
BufferedInputStream(new FileInputStream("xxxx")));
dis.read();