装饰模式

Posted zuolanlan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰模式相关的知识,希望对你有一定的参考价值。

一、基本概念

1、定义:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
2、作用:为已有功能动态地添加更多功能的一种方式。
 
3、何时使用装饰模式:当系统需要新功能时,要求向旧的类中添加新的代码,这些新的代码通常装饰了原有类的核心职责或主要行为。
4、优点:把类中装饰功能从类中搬移去除,这样可以简化原有的类。   
有效地把类的核心职责和装饰功能区分开了,而且可以去除相关类中重复的装饰逻辑。
5、特点:在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,并让这个类包装它所需要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地,按顺序地使用装饰功能包装对象了
 
6、装饰模式结构图
Component:定义一个对象接口(或者抽象类),可以给这些对象动态地添加职责;
ConcreteComponent:定义了一个具体的对象,也可以给这个对象添加一些职责;——人
Decorator:装饰抽象类,继承了Component,从外类来扩展Component类的功能,但Component无需知道Decorator的存在。——衣物
ConcreteDecoratorA:具体的装饰对象,起到给Component添加职责的功能~落到实处;——裙子
 
技术分享图片

 

7、简化具体的实施过程
  • 如果ConcreteComponent只有一个,没有Component,就可以让Decorator直接继承ConcreteComponent;
e.g 给一个人穿各种衣服
  • 如果ConcreteDecoratorA只有一种,就可以不要Decorator,直接让ConcreteDecoratorA继承Component。

 

二、示例:给小仙猪打扮一下

属于简化实施过程的第一种情况。

1、UML图

技术分享图片

 

2、代码

 Person类

 1 package thirdDecoration;
 2 
 3 // 相当于ConcreteCompement的person
 4 public class Person {
 5     private String name;
 6     public Person(){}
 7     public Person(String name){
 8         this.name=name;
 9     }
10      
11     public  void  show(){ //由于在Java中,普通类不能拥有抽象方法,且抽象方法无方法体,所以和书上C#的写法不同
12         System.out.println("装扮的"+this.name);
13     };
14 }

 

服饰类

 1 package thirdDecoration;
 2 
 3 public class Finery extends Person {
 4     protected Person compenent;
 5     public void Decorate(Person person){
 6         this.compenent=person;
 7     }
 8     public void show(){  //通过覆写的方式增加子类的特性
 9         if (compenent!=null){
10             compenent.show();
11         }
12     }    
13 }

 

具体服饰类

1 package thirdDecoration;
2 
3 public class Tshirt extends Finery {
4     public void show(){
5         System.out.println("T恤");
6         super.show();
7     }
8 }
1 package thirdDecoration;
2 
3 public class Skirt extends Finery {
4     public void show(){
5         System.out.println("超短裙");
6         super.show();
7     }
8 }
1 package thirdDecoration;
2 
3 public class Dress extends Finery {
4     public void show(){
5         System.out.println("连衣裙");
6         super.show();
7     }
8 }

 

客户端

 

 1 package thirdDecoration;
 2 
 3 public class DecorationTest {
 4 
 5     public static void main(String[] args) {
 6         Person person=new Person("小仙猪");//把对象找出来
 7         Tshirt tshirt=new Tshirt(); //把衣服准备好
 8         Skirt skirt=new Skirt(); //把衣服准备好
 9         
10         skirt.Decorate(person);//裙子穿上
11         tshirt.Decorate(skirt);//再把上衣穿上
12         tshirt.show();
13         
14         System.out.println("done!");
15     }
16 
17 }

 

分析:

  • 这部分和常理的理解有那么一点不太一样,因为我们正常是觉得,人还是那个人,但是穿了不同的衣服,人是主题,贯穿始终,但是这里,人好像被包裹了一件衣服后,就不是这个人了。不过这只是一个例子而已。
  • 装饰功能的装饰顺序很重要,示例中“穿衣服”是比较随性的,但是工程中,例如加密数据和过滤词汇都可以是数据持久化的装饰功能,但是一定是先过滤词汇然后再加密,否则会出问题的。
 

以上是关于装饰模式的主要内容,如果未能解决你的问题,请参考以下文章

Thymeleaf 模板 - 有没有办法装饰模板而不是包含模板片段?

swift设计模式学习 - 装饰模式代码大全

设计模式---装饰者模式

设计模式之单例模式

装饰模式与代理模式的区别

Java设计模式之装饰者模式