美文网首页Java学习笔记JavaJava设计模式
Java设计模式之装饰者模式

Java设计模式之装饰者模式

作者: 文艺小卿年 | 来源:发表于2019-04-04 09:15 被阅读0次

    1. 什么是装饰者模式

    装饰者模式就是动态的给某个对象扩展一些额外的功能。装饰模式相比生成子类更为灵活。

    2. 装饰者模式中都有什么角色

    2.1. 抽象组件(Component)

    给出一个抽象接口,用来规范准备接收附加功能的对象

    2.2. 具体组件(ConcreteComponent)

    将要被附加功能的类,实现抽象组件角色的接口

    2.3. 抽象装饰者组件(Decorator)

    是抽象组件的一个子类,是“装饰者”角色,其作用是装饰具体组件,因此,抽象装饰者角色需要包含抽象组件的引用。可以是抽象类,也可以是非抽象类。

    2.4. 具体装饰者组件(ConcreteDecorator)

    实现抽象装饰者角色,负责对具体组件添加额外功能

    3. 类图

    装饰者模式1.jpg

    4. 代码描述

    装饰模式是动态的扩展一个对象的功能,而不需要改变原始类代码的一种成熟模式。

    在许多设计中,可能需要改进对某个对象的功能,而不是该类所有的对象。

    • 例如:小鸟类的实例对象可以连续飞行100米,我们创建了5只小鸟,想让其中一只可以连续飞行200米,其他鸟还是100米。
    • 这时我们可以给这只小鸟装一个加速器,这只小鸟就可以借助加速器比别的小鸟多飞100米,如果装两个加速器,小鸟就可以飞300米。
    • 这就是我们设计装饰者模式的初衷——改变类的某个对象的功能

    4.1. 抽象组件

    public abstract class Bird {
        public abstract int fly();
    }
    

    4.2. 具体组件

    具体组件是抽象组件的一个子类,具体组件的实例称为“被装饰者”。

    public class SuperBird extends Bird {
        public final int DISTANCE = 100;
    
        @Override
        public int fly() {
            return DISTANCE;
        }
    }
    

    4.3. 抽象装饰者组件

    抽象装饰组件是抽象组件的一个子类,其作用是装饰具体组件。因此,抽象装饰组件需要包含“被装饰者”的引用。而且,抽象装饰组件本身也是抽象组件的子类,即也是具体组件的角色,不同之处在于,抽象装饰组件额外提供了一些方法。

    public abstract class Faster extends Bird {
        Bird bird;//被装饰者
    
        public Faster(Bird bird) {
            this.bird = bird;
        }
    
        @Override
        public int fly() {
            return bird.fly();
        }
    
        public abstract int eleFly();//用于修饰fly()方法,具体行为由装饰者去实现
    }
    

    4.4. 具体装饰组件

    根据具体的问题,具体装饰组件用新的方法去装饰具体组件。

    public class FasterDecorator extends Faster {
        public final int ELEDISTANCE = 100;//加速器能多飞100米
    
        FasterDecorator(Bird bird) {
            super(bird);
        }
    
        @Override
        /**
         * 被装饰的方法
         */
        public int fly() {
            return bird.fly() + eleFly();
        }
    
        @Override
        /**
         *具体装饰者重写装饰者中用于装饰的方法
         */
        public int eleFly() {
            return ELEDISTANCE;
        }
    }
    
    

    4.5. 测试

    public class Test {
        public static void main(String[] args) {
            Bird bird=new SuperBird() ;
            System.out.println("没有安装加速器的小鸟飞行距离:"+bird.fly());
            bird=new FasterDecorator(bird);
            System.out.println("安装了1个加速器的小鸟飞行距离:"+bird.fly());
            bird=new FasterDecorator(bird);
            System.out.println("安装了2个加速器的小鸟飞行距离:"+bird.fly());
            bird=new FasterDecorator(bird);
            System.out.println("安装了3个加速器的小鸟飞行距离:"+bird.fly());
    
        }
    }
    

    运行结果

    没有安装加速器的小鸟飞行距离:100
    安装了1个加速器的小鸟飞行距离:200
    安装了2个加速器的小鸟飞行距离:300
    安装了3个加速器的小鸟飞行距离:400
    

    5. 使用多个装饰器

    由于抽象装饰组件本身也是抽象组件的一个子类,所以“装饰者”本身也可以成为一个“被装饰者”,这意味着我们可以使用多个具体装饰类来装饰具体组件的实例。

    • 比如我们需要一个可以飞行150米的鸟,那么就不必修改现有的类,只需要再添加一个具体装饰即可。
    public class FasterDecorator2 extends Faster{
        public final int ELEDISTANCE = 50;//加速器能多飞50米
    
        FasterDecorator2(Bird bird) {
            super(bird);
        }
    
        @Override
        /**
         * 被装饰的方法
         */
        public int fly() {
            return bird.fly() + eleFly();
        }
    
        @Override
        /**
         *具体装饰者重写装饰者中用于装饰的方法
         */
        public int eleFly() {
            return ELEDISTANCE;
        }
    }
    
    Bird bird=new SuperBird() ;
    bird=new FasterDecorator(bird);
    bird=new FasterDecorator(bird);
    bird=new FasterDecorator(bird);
    bird=new FasterDecorator2(bird);
    

    6. 装饰模式的优势

    • 被装饰者和装饰者是松耦合关系,由于抽象装饰组件仅仅依赖于抽象组件,因此,具体装饰只需要知道它要装饰的对象是抽象组件的某一个实例,不需要知道是哪一个具体子类。

    • 装饰模式满足“开-闭”原则,用户不必修改具体组件,就可以增加新的针对该具体组件的具体装饰。

    • 可以使用多个具体装饰来装饰具体组件的实例。

    相关文章

      网友评论

        本文标题:Java设计模式之装饰者模式

        本文链接:https://www.haomeiwen.com/subject/toixiqtx.html