装饰模式

一,定义

装饰模式,动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
或者说:在不必改变原类文件和原类使用的继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是用装饰来包裹真实的对象来实现。

二,角色

抽象构件角色(Component):给出一个接口,以规范准备接收附加责任的对象。
具体构件角色(ConcreteComponent):定义一个将要接收附加责任的类。
装饰角色(Decorator):持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰角色(ConCreteDecoratorA,ConcreteDecoratorB):负责给构件对象“贴上”附加的责任。

三,实例

下面我要是实现一个给一个人进行装饰的例子,即给人穿上外套,裤子,鞋子等装饰。并且可以控制装饰顺序。
这里写图片描述
这里的人就是抽象构建角色,当然也可以不抽象没有具体构建角色。服饰就是装饰角色,其子类就是具体装饰角色。下面贴一下代码:

public abstract class Person {
    //这里要实现的是给人装扮的功能。类似于QQ秀 换衣服然后展示这种的。
    public abstract void show();
}

public class ConcretePersonA extends Person {
    @Override
    public void show() {
        System.out.println("嘻哈装扮");
    }
}

上面是一个抽象的人,和一个喜欢嘻哈风格装扮的人。

public abstract class Finery extends Person {
    protected  Person component;

    public void decorate(Person component){
        this.component = component;
    }
    @Override
    public void show() {
        if (null != component){
            component.show();
        }
    }
}

public class BigTrouser extends Finery {
    @Override
    public void show() {
        super.show();
        System.out.println("大垮裤");
    }
}

public class TShirts extends Finery {
    @Override
    public void show() {
        super.show();
        System.out.println("大T恤");
    }
}

上面是一个抽象的装饰类,绑定一下装饰对象,和他的具体装饰类。

public static void main(String[] args) {
        //装饰模式
        ConcretePersonA a = new ConcretePersonA();
        Sneakers sneakers = new Sneakers();
        BigTrouser bigTrouser = new BigTrouser();
        TShirts tShirts = new TShirts();
        sneakers.decorate(a);
        bigTrouser.decorate(sneakers);
        tShirts.decorate(bigTrouser);//装饰过程
        tShirts.show();
        ConcretePersonB b = new ConcretePersonB();
        LeatherShoes leatherShoes = new LeatherShoes();
        Tie tie = new Tie();
        Suit suit = new Suit();
        leatherShoes.decorate(b);
        tie.decorate(leatherShoes);
        suit.decorate(tie); //装饰过程
        suit.show();
    }

输出结果:
嘻哈装扮
运动鞋
大垮裤
大T恤
庄重装扮
皮鞋
领带
西装

以上就是装饰模式的实现,从代码我们能看到,装饰模式是为已有功能动态的添加更多功能的一种方式。那到底什么时候用它呢,当系统中需要新功能的时候,是向旧的类中添加新代码,这些新代码通常装饰了原有类的核心职责或者主要行为。我们看到,它把每个要装饰的功能放在一个单独的类中,并让这类包装它所要装饰的对象,因此,当需要执行特殊行为的时候,客户代码就可以在运行时根据需要选择地,按顺序地使用装饰功能包装对象。

这样更大的好处是,有效的把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。

四,优缺点

优点:

  • 1,使用装饰者模式比使用继承更加灵活,因为它选择通过一种动态的方式来扩展一个对象的功能,在运行时可以选择不同的装饰器,从而实现不同的行为。
  • 2,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
  • 3,具体构件类与具体装饰类可以独立变化,他能是低耦合的。用户可以根据需要来增加新的具体构件类和具体装饰类,在使用时再对其进行各种组合,原有代码无须改变,符合“开闭原则”。

缺点:

  • 1,会产生很多的小对象,增加了系统的复杂性
  • 2,这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

装饰者和继承的区别:
继承:

  • 优点:代码结构清晰,而且实现简单
  • 缺点:对于每一个的需要增强的类都要创建具体的子类来帮助其增强,这样会导致继承体系过于庞大。

装饰者:

  • 优点:内部可以通过多态技术对多个需要增强的类进行增强
  • 缺点:需要内部通过多态技术维护需要增强的类的实例。进而使得代码稍微复杂。

五,使用场景

1,需要扩展一个类的功能,或给一个类添加附加职责。
2,需要动态的给一个对象添加功能,这些功能可能不明确或者暂时的,可以随时很方便的动态撤销掉。
3,需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

参考:《大话设计模式》 阿木虾 Java知音

源码:https://github.com/wangxp423/ExerciseDesignmodel

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值