zoukankan      html  css  js  c++  java
  • (java)从零开始之--装饰者设计模式

    装饰者设计模式
    简单定义:增强一个类的功能,而且还可以让这些装饰类互相装饰。

    应用场景:当要在某个功能的基础上扩充功能,并且扩充的功能具有大量排列组合,通过继承关系会衍生出大量子类,这时候用装饰者模式来解决。

    装饰者设计模式的步骤
    1. 在装饰类的内部维护一个被装饰类的引用。
    2. 让装饰类有一个共同的父类或者是父接口。

    例如:人有一种行为叫“吃水果”,其中水果有4种:苹果、香蕉、鸭梨、橘子
    现在有需求如下:
    A类人行为:吃苹果
    B类人行为:先吃苹果,再吃香蕉
    C类人行为:先吃香蕉,再吃苹果
    D类人行为:先吃橘子,后吃鸭梨

    我们先用子类继承来实现:代码如下

     1 interface IEatFruit{
     2 public void eatFruit();
     3 }
     4 
     5 class PersonA implements IEatFruit{
     6 
     7   @Override
     8   public void eatFruit() {
     9     System.out.println("吃苹果"); 
    10   }
    11 
    12 }
    13 class PersonB implements IEatFruit{
    14 
    15 @Override
    16   public void eatFruit() {
    17     System.out.println("吃苹果"); 
    18     System.out.println("吃香蕉"); 
    19   }
    20 
    21 }
    22 class PersonC implements IEatFruit{
    23 
    24   @Override
    25   public void eatFruit() {
    26     System.out.println("吃香蕉");
    27     System.out.println("吃苹果"); 
    28   }
    29 
    30 }
    31 class PersonD implements IEatFruit{
    32 
    33   @Override
    34   public void eatFruit() {
    35     System.out.println("吃橘子");
    36     System.out.println("吃鸭梨"); 
    37   }
    38 
    39 }

    这样当然是没问题的,每一类人对应new出来的对象 都可以实现对应的需求。
    但是,当需求改为:
    某类人行为:吃上面四种水果,并且要求有先后顺序
    这样的排列组合有24种....
    这样你还会用继承去做吗?写24个子类去实现接口,明显不合适。
    这时候如果用到装饰者模式,代码则会变成:

      1 interface IEatFruit{
      2     public void eatFruit();
      3 }
      4 
      5 class PersonA implements IEatFruit{
      6     IEatFruit eat;
      7     public PersonA(){
      8         this.eat = this;
      9     }
     10     public PersonA(IEatFruit _eat){
     11         this.eat = _eat;
     12     }
     13     @Override
     14     public void eatFruit() {
     15         if(!(this.eat instanceof PersonA)){
     16             this.eat.eatFruit();
     17             System.out.println("吃苹果"); 
     18         }else{
     19             System.out.println("吃苹果"); 
     20         }
     21     }
     22     
     23 }
     24 class PersonB implements IEatFruit{
     25     IEatFruit eat;
     26     public PersonB(){
     27         this.eat = this;
     28     }
     29     public PersonB(IEatFruit _eat){
     30         this.eat = _eat;
     31     }
     32     @Override
     33     public void eatFruit() {
     34         if(!(this.eat instanceof PersonB)){
     35             this.eat.eatFruit();
     36             System.out.println("吃香蕉"); 
     37         }else{
     38             System.out.println("吃香蕉"); 
     39         }
     40     }
     41     
     42 }
     43 class PersonC implements IEatFruit{
     44     IEatFruit eat;
     45     public PersonC(){
     46         this.eat = this;
     47     }
     48     public PersonC(IEatFruit _eat){
     49         this.eat = _eat;
     50     }
     51     @Override
     52     public void eatFruit() {
     53         if(!(this.eat instanceof PersonC)){
     54             this.eat.eatFruit();
     55             System.out.println("吃鸭梨"); 
     56         }else{
     57             System.out.println("吃鸭梨"); 
     58         }
     59     }
     60     
     61 }
     62 class PersonD implements IEatFruit{
     63     IEatFruit eat;
     64     public PersonD(){
     65         this.eat = this;
     66     }
     67     public PersonD(IEatFruit _eat){
     68         this.eat = _eat;
     69     }
     70     @Override
     71     public void eatFruit() {
     72         if(!(this.eat instanceof PersonD)){
     73             this.eat.eatFruit();
     74             System.out.println("吃橘子"); 
     75         }else{
     76             System.out.println("吃橘子"); 
     77         }
     78     }
     79     
     80 }
     81 
     82 
     83 
     84 public class Demo2 {
     85 
     86     public static void main(String[] args) {
     87         //这样就可以通过上述4类人来相互装饰,就可以随意任意一种组合“吃水果”
     88         //如:吃橘子->吃苹果
     89         PersonD d = new PersonD();
     90         PersonA a = new PersonA(d);
     91         a.eatFruit();
     92         System.out.println("-------我是分割线------------");
     93         //如:吃苹果->吃橘子->吃鸭梨->吃香蕉
     94         PersonA a2 = new PersonA();
     95         PersonD d2 = new PersonD(a2);
     96         PersonC c2 = new PersonC(d2);
     97         PersonB b2 = new PersonB(c2);
     98         b2.eatFruit();
     99     }
    100 
    101 }

    输出结果如下:
    吃橘子
    吃苹果
    -------我是分割线------------
    吃苹果
    吃橘子
    吃鸭梨
    吃香蕉

    最后总结
    继承实现的增强类和修饰模式实现的增强类有何区别?
    继承实现的增强类:
    优点:代码结构清晰,而且实现简单.
    缺点:对于每一个的需要增强的类都要创建具体的子类来帮助其增强,这样会导致
    继承体系过于庞大。
    装饰者模式实现的增强类:
    优点:内部可以通过多态技术对多个需要增强的类进行增强, 可以使这些装饰类
    达到互相装饰的效果。使用比较灵活。
    缺点:需要内部通过多态维护需要被增强的类的实例。进而使得代码稍微复杂

  • 相关阅读:
    win7下如何配置ODBC数据源
    串口小票打印机调试命令
    如何测试一个网页登陆界面
    Cookie是否是httponly
    XSS攻击 (安全方面)和传统防御技术
    Linux下查看文件和文件夹大小
    linux停止和查看启动服务的命令使用方法
    查看Linux下系统资源占用常用命令(top、free、uptime)
    三种经典iPhone上网络抓包方法详解
    如何用Fiddler对Android应用进行抓包
  • 原文地址:https://www.cnblogs.com/fnz0/p/5406402.html
Copyright © 2011-2022 走看看