您好,欢迎访问代理记账网站
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

【Java设计模式】014-装饰器模式

目录

十、装饰器模式

1、概述

2、应用场景

3、优缺点

优点

缺点

4、主要角色

5、代码实现

抽象构件角色:孙悟空

具体构件角色:猴子

抽象装饰角色:Changer

具体装饰角色:美女

具体装饰角色:龙

测试类

运行结果


十、装饰器模式

作用:对原有功能向多个方向进行扩展,每一个扩展是一个具体的装饰角色,就像孙悟空七十二变一样,变化的每一个角色都是一个具体的装饰角色!类似代理模式的作用!既可以提供动态代理的“统一服务”,也可以提供静态代理的“个性化服务”,妙啊!

1、概述

上班族大多都有睡懒觉的习惯,每天早上上班时间都很紧张,于是很多人为了多睡一会,就会用方便的方式解决早餐问题。有些人早餐可能会吃煎饼,煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框等,都是装饰器模式。

在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下,可以动态地扩展其功能。所有这些都可以釆用装饰器模式来实现。

设计模式之间都是相通的,对原有的功能进行扩展的方法有很多。比如Java代码复用的三种常用方式:继承、组合和代理;还比如适配器模式,你缺啥我给你适配啥;这个装饰器模式也是一种扩展方式!

装饰器(Decorator)模式:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

 

2、应用场景

  • 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类;

  • 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰器模式却很好实现;

  • 当对象的功能要求可以动态地添加,也可以再动态地撤销时;

 

3、优缺点

优点

  • 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用;

  • 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果;

  • 装饰器模式完全遵守开闭原则;

 

缺点

装饰器模式会增加许多子类,过度使用会增加程序得复杂性;

 

4、主要角色

装饰器模式所包含的 4 个角色不是任何时候都要存在的,在有些应用环境下模式是可以简化的:

  • 装饰器模式所包含的 4 个角色不是任何时候都要存在的,在有些应用环境下模式是可以简化的;

  • 如果只有一个具体装饰时,可以将抽象装饰和具体装饰合并;

  • 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象;

  • 具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责;

  • 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能;

  • 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任;

 

5、代码实现

抽象构件角色:孙悟空

抽象构件角色就相当于一个装饰器,谁要装饰say()方法就实现我这个接口

比如说这是个快递,我写个统一的包装方法,谁要包装实现我即可

package com.zibo.design.eleven;

// 抽象构件角色:孙悟空
// 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象;
public interface SunWuKong {
    void say();
}

 

具体构件角色:猴子

具体构件角色就相当于想要装饰自己的具体角色,比如说快递需要装箱,实现装箱接口即可

package com.zibo.design.eleven;

// 具体构件角色:猴子
// 具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责;
public class Monkey implements SunWuKong {
    @Override
    public void say() {
        System.out.println("我本是一只猴子!");
    }
}

 

抽象装饰角色:Changer

这个是抽象装饰角色,就相当于一个快递的常规包装流程,装个普通的箱子;

这有一个非常妙的点:可以在抽象装饰里面提供“统一的服务”(动态代理功能);

这个抽象装饰角色不一定要写成一个抽象类(教程就没写,我自己写的)

SunWuKong sunWuKong = new Changer(monkey);
sunWuKong.say(); // 仅需要统一服务

package com.zibo.design.eleven;

// 抽象装饰角色:Changer
// 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,
// 可以通过其子类扩展具体构件的功能;
public abstract class Changer implements SunWuKong{

    private final SunWuKong sunWuKong;

    public Changer(SunWuKong sunWuKong) {
        this.sunWuKong = sunWuKong;
    }

    @Override
    public void say() {
        // 方法前统一服务
        sunWuKong.say();
        // 方法后统一服务
    }
}

 

具体装饰角色:美女

具体装饰角色,相当于这是贵重易损物品,仅仅装个箱子还不够,需要再在外部价格木盒子

这有一个非常妙的点:可以在具体装饰类之内提供“个性化服务”(静态代理功能);

package com.zibo.design.eleven;

// 具体装饰角色:美女
public class Beauty extends Changer {
    public Beauty(SunWuKong sunWuKong) {
        super(sunWuKong);
    }

    @Override
    public void say() {
        // 方法前个性服务
        super.say();
        // 方法后个性服务
        System.out.println("我变成了大美女!");
    }
}

 

具体装饰角色:龙

package com.zibo.design.eleven;

// 具体装饰角色:龙
public class Dragon extends Changer {
    public Dragon(SunWuKong sunWuKong) {
        super(sunWuKong);
    }

    @Override
    public void say() {
        super.say();
        System.out.println("我变成了一条龙!");
    }
}

 

测试类

package com.zibo.design.eleven;

public class Test {
    public static void main(String[] args) {
        Monkey monkey = new Monkey();
        monkey.say();
        SunWuKong beauty = new Beauty(monkey);
        beauty.say();
        SunWuKong dragon = new Dragon(monkey);
        dragon.say();
    }
}

 

运行结果

我本是一只猴子!
我本是一只猴子!
我变成了大美女!
我本是一只猴子!
我变成了一条龙!

 

 


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进