浅学设计模式之装饰模式 (2/23)

1、装饰模式的概念

装饰模式就是动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。

对于人来说,衣服、鞋子、领带、袜子等都是装饰,装饰模式就是给光着身子的人穿上各种衣服裤子。
对于程序对象来说,每一个功能都是装饰,给一个类增加功能,就是给这个类进行装饰。

2、装饰模式的UML图及对应代码

在这里插入图片描述
Compoent是一个对象接口,可以给这些对象动态地添加职责

class interface Component{
    void Operation();
}

ConcreteComponent类,定义了一个具体的对象,也可以给这个对象添加一些职责

class ConcreteComponent implement Component{
   
   @Override
   public void Operation(){
       //做一些具体的操作
   } 
}

Decorator 是装饰抽象类,继承了Component接口,从外类来扩展Component类的功能,但是对于Component来说,是无需要知道Decorator的存在的。

public class Decorator implements Component{
    protected Component component;
    
    //设置Component
    public SetComponent(Component component){
        this.component = component;
    }

    //重写Operation(),实际执行的是Component的Operation()
    @Override
    public void Operation() {
        if(component != null){
           component.Operation();
        }
    }   
}

ConcreteDecorator 是具体的装饰对象,起到给Component添加职责的功能
我们来实现一下A和B

public class ConcreteDecoratorA extends Decorator {
    
    //本类特有的功能,以区别B
    private String addedState;
    
    @Override
    public void Operation() {
      // 首先运行原Component的Operation()
   super.sampleOperation();
     // 再执行本类的功能,如addState相当于对原Component进行了装饰
     addState = "New State";
     //具体装饰对象A的操作。
    }
}

public class ConcreteDecoratorB extends Decorator {
    
    //本类特有的方法,以区别A
    public AddBehavior() {
    }
    
    @Override
    public void Operation() {
      // 首先运行原Component的Operation()
   super.sampleOperation();
     // 再运行自己的功能
     AddBehavior();
     ....
    }
}

最后客户端代码点睛之笔:

        main(){
            ConcreteComponent c = new ConcreteComponent();
            ConcreteDecoratorA d1 = new  ConcreteDecoratorA();
            ConcreteDecoratorB d2 = new  ConcreteDecoratorB();
            
            //装饰的方法是:
            //首先用 ConcreteComponent实例化c
            //然后用 ConcreteDecoratorA的实例化对象d1来包装c
            //再用ConcreteDecoratorB的对象d2来包装d1
            //最后执行d2的Operation
            d1.setComponent(c);
            d2.setComponent(d1);
            d2.Operation();
            ...
       }
  • 装饰模式就是利用SetComponent来对对象进行包装的。
    这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象值关心自己的功能,不需要关心如何被添加到对象链当中。

注:不一定要去构造Component类,要善于变通,假如只有一个ConcreteComponent(我们只修饰一个“人”),那么久没有必要些Component类,同时,Decorator就是ConcreteComponent类的子类,如果ConcreteDecorator只有一个(“衣服”只有一件),那么也没有必要构造Decorator,直接让唯一的ConcreteDecorator来继承ConcreteComponent就行啦。

3、经典场景—穿衣服

在这个场景下,我们给一个人穿各种衣服,包括裤子、袜子、鞋子、衣服。
在之前的UML来说,ConcreteComponent可以说是代表着具体的一类人,而这个问题让我们针对这个人,所以我们可以不用构造Component类,或者说 “人”这个类就是Component类。而Decorator很自然就是“服装类”,其子类就是各种衣服,那么我们可以画出下面的UML图:
在这里插入图片描述

接着按图来写代码:
首先是Person类

class Person{
     public Person(){
     }
     private String name;
     public Person(String name){
     this.name = name;
     }
     public abstract void show(){
     System.out.plintln("穿衣服的rikka");
     }
}

接着是服饰类Finery:

class Finery extends Person{
     protected Person component;
     //打扮
     public void Decorate(Person component){
     this.component = component;
     }
     
     @Override
     public void show(){
     if(component != null){
        component.show();
       }
     }
}

接下来就是具体服饰类ConcreteDecorator

class GoldLianzi extends Finery{
     @Override
     public void show(){
       System.out.prinlin("大金链子");
       super.show();
     }
}
class Sunglasses extends Finery{
     @Override
     public void show(){
       System.out.prinlin("墨镜");
       super.show();
     }
}
。。。。

最后的客户端代码:

  main(){
     Person rikka = new Person("Rikka");
     
     System.out.println("装扮\n");
     
     Sunglasses sunglasses = new Sunglasses();
     GoldLianzi gold = new GoldLianzi();
     Cigarette cigarette = new Cigarette();
     ThugLife thuglife = new ThugLife();
       
     sunglasses.Decorate(rikka);
     gold.Decorate(sunglasses);
     cigarette.Decorate(gold);
     thuglife.Decorate(cigarette);
     thuglife.show();
}

结果显示:

装扮
ThugLife帽子 香烟 大金链子 墨镜 穿衣服的rikka

这样,我们就为一个什么都没有穿的人,穿上了各种衣服啦!
同理就是给类加功能。

总结

学了这么多,其实装饰模式是为已有功能动态地添加更多功能的一种设计模式。

问题:在以往,在系统功能需要更新的时候,是向旧类添加新的代码,这些新的代码通常装饰了原有类的核心职责或主要行为,但这种做法的问题就在于:它们在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度。

答案:而装饰模式提供了很好的解决方案,它把每个装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象。因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择的、按顺序的使用装饰功能包装类对象

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值