zoukankan      html  css  js  c++  java
  • 装饰器模式

    转载:https://www.cnblogs.com/jzb-blog/p/6717349.html

    装饰者模式使用被装饰类的一个子类的实例,把客户端的调用委派到被装饰类,装饰模式的关键在于这种扩展是完全透明的。

    对扩展开放,对修改关闭。

    装饰器模式

    1、初识装饰器模式

        装饰器模式,顾名思义,就是对已经存在的某些类进行装饰,以此来扩展一些功能。其结构图如下:

          

    Component为统一接口,也是装饰类和被装饰类的基本类型。

    ConcreteComponent为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类。

    Decorator是装饰类,实现了Component接口的同时还在内部维护了一个ConcreteComponent的实例,并可以通过构造函数初始化。而Decorator本身,通常采用默认实现,他的存在仅仅是一个声明:我要生产出一些用于装饰的子类了。而其子类才是赋有具体装饰效果的装饰产品类。

    ConcreteDecorator是具体的装饰产品类,每一种装饰产品都具有特定的装饰效果。可以通过构造器声明装饰哪种类型的ConcreteComponent,从而对其进行装饰。

    2、最简单的代码实现装饰器模式

     

    //基础接口
    public interface Component {
        
        public void biu();
    }
    //具体实现类
    public class ConcretComponent implements Component {
    
        public void biu() {
            
            System.out.println("biubiubiu");
        }
    }
    //装饰类
    public class Decorator implements Component {
    
        public Component component;
        
        public Decorator(Component component) {
            
            this.component = component;
        }
        
        public void biu() {
            
            this.component.biu();
        }
    }
    //具体装饰类
    public class ConcreteDecorator extends Decorator {
    
        public ConcreteDecorator(Component component) {
    
            super(component);
        }
    
        public void biu() {
            
            System.out.println("ready?go!");
            this.component.biu();
        }
    }

    这样一个基本的装饰器体系就出来了,当我们想让Component在打印之前都有一个ready?go!的提示时,就可以使用ConcreteDecorator类了。具体方式如下:

    //使用装饰器
      Component component = new ConcreteDecorator(new ConcretComponent());
      component.biu();
    
      //console:
      ready?go!
      biubiubiu

    3、为何使用装饰器模式

    一个设计模式的出现一定有他特殊的价值。仅仅看见上面的结构图你可能会想,为何要兜这么一圈来实现?仅仅是想要多一行输出,我直接继承ConcretComponent,或者直接在另一个Component的实现类中实现不是一样吗?

        首先,装饰器的价值在于装饰,他并不影响被装饰类本身的核心功能。在一个继承的体系中,子类通常是互斥的。比如一辆车,品牌只能要么是奥迪、要么是宝马,不可能同时属于奥迪和宝马,而品牌也是一辆车本身的重要属性特征。但当你想要给汽车喷漆,换坐垫,或者更换音响时,这些功能是互相可能兼容的,并且他们的存在不会影响车的核心属性:那就是他是一辆什么车。这时你就可以定义一个装饰器:喷了漆的车。不管他装饰的车是宝马还是奥迪,他的喷漆效果都可以实现。

        再回到这个例子中,我们看到的仅仅是一个ConcreteComponent类。在复杂的大型项目中,同一级下的兄弟类通常有很多。当你有五个甚至十个ConcreteComponent时,再想要为每个类都加上“ready?go!”的效果,就要写出五个子类了。毫无疑问这是不合理的。装饰器模式在不影响各个ConcreteComponent核心价值的同时,添加了他特有的装饰效果,具备非常好的通用性,这也是他存在的最大价值。

     

    4.以前的测试代码

    /**

     * 装饰者模式,(装饰者和被装饰者的类型必须是一样的,拥有相同的超类或者相同的接口)

     */

    public abstract class Beverage {

        protected String description = "unknow beverage";

        

        public String getDescription() {

            return description;

        }

        

        public abstract double cost();

    }

    //装饰者

    public abstract class CondimentDecorator extends Beverage {

        public abstract String getDescription();

    }

    //被装饰者实现类

    public class HouseBlend extends Beverage {

        

        public HouseBlend() {

            description = "House Blend Coffee";

        }

        

        @Override

        public double cost() {

            return 0.89;

        }

    }

    //装饰者实现类

    public class Mocha extends CondimentDecorator {

        private Beverage beverage;

        

        public Mocha(Beverage beverage) {

            this.beverage = beverage;

        }

        

        @Override

        public String getDescription() {

            return beverage.getDescription() + ", Mocha";

        }

     

        @Override

        public double cost() {

            return 0.20 + beverage.cost();

        }

    }

    //又一装饰者实现类

    public class Whip extends CondimentDecorator {

        private Beverage beverage;

        

        public Whip(Beverage beverage) {

            this.beverage = beverage;

        }

        

        @Override

        public String getDescription() {

            return beverage.getDescription() + ", Whip";

        }

     

        @Override

        public double cost() {

            return 0.10 + beverage.cost();

        }

    }

    //测试类

    public class Test {

        public static void main(String[] args) {

            Beverage beverage = new HouseBlend();

            System.out.println(beverage.getDescription() + " " + beverage.cost());

            

            Beverage beverage1 = new HouseBlend();

            beverage1 = new Mocha(beverage1);

            beverage1 = new Whip(beverage1);

            System.out.println(beverage1.getDescription() + " " + beverage1.cost());

        }

    }

    //结果:

    House Blend Coffee 0.89

    House Blend Coffee, Mocha, Whip 1.1900000000000002

  • 相关阅读:
    C# 基础练习题
    WinForm中实现播放mp3 、mp4文件
    C语言实现的水仙花数
    【转】.net 经典面试题
    vipspa实现前端路由
    spring定时任务<task:scheduled-tasks>的问题
    MongoDB中$month和$dayOfMonth的坑
    SpringMVC中MultipartFile参数问题
    IllegalStateException : Web app root system property already set to different value问题详解
    jsoup简单的爬取网页数据
  • 原文地址:https://www.cnblogs.com/fanguangdexiaoyuer/p/5786820.html
Copyright © 2011-2022 走看看