04_Decorator 装饰器 ——新瓶装旧酒,要新功能,但不要新对象!

GoF定义:对一个对象动态地添加额外功能。装饰器提供了一种替代子类实现的方法,灵活地扩展类的功能。(Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.)

进一步说明:使用装饰器是为了给现有的类方法增加额外功能。但装饰器模式不改写(modify)方法,而是扩展(extends)方法。一旦继承父类并改写某个方法,那就不叫装饰器了。

装饰器这个名词很形象地描述了这样一个场景:增加的功能只是装饰品,是附属在实体类之上的,被装饰的实体类的结构不能被改变(包括继承并改变)。

 

举例:例如我们有一位Y教授,他本质上是一个人类,具有普通人的共性。但他出席不同的活动就会有不同的打扮和装饰。例如去做国际报告,那就要穿一身正装讲一口流利的英语,说一些谁都没听过的东西,以便把台下的人忽悠的一愣一愣;如果他去请朋友吃饭,就会打扮时尚,讲话引经据典风趣幽默。我们用代码来实现以上的描述。显然,不同场合下的Y叫兽是同一个人,我们不能继承出一个新的人出来完全改写他的属性,而是使用装饰器,扩展他的属性。

public class Main {

    public static void main(String[] args) {
        ProfessorY prof = new ProfessorY();
        AbstractDecoratorProfessorY profAtCon = new ProfessorYAtConference();
        profAtCon.setProfessorY(prof);
        profAtCon.getDescription();

        AbstractDecoratorProfessorY proAtDinner = new ProfessorYAtDinner();
        proAtDinner.setProfessorY(prof);
        proAtDinner.getDescription();
    }
}

abstract class AbstractProfessorY {
    abstract void getDescription();
}

// 被装饰的实体类
class ProfessorY extends AbstractProfessorY {
    @Override
    void getDescription() {
        System.out.println("I am a human being.");
    }
}

// 装饰器的抽象类,给予此,我们将扩展出2种不同的场景
abstract class AbstractDecoratorProfessorY extends AbstractProfessorY {
    ProfessorY professor;

    // 这里是关键,我们加载实体类对象,在此基础上扩展。
    void setProfessorY(ProfessorY p) {
        this.professor = p;
    }

    @Override
    void getDescription() {
        if (professor != null) {
            professor.getDescription();
        }
    }
}

// 为开会而装饰
class ProfessorYAtConference extends AbstractDecoratorProfessorY {
    @Override
    void getDescription() {
        System.out.println("-- Conference decorator --");
        super.getDescription();
        actingAtConference();
    }

    void actingAtConference() {
        System.out.println("I wear a suit, speaking english and talk something no one knows!");
    }
}

// 为聚会而装饰
class ProfessorYAtDinner extends AbstractDecoratorProfessorY {
    @Override
    void getDescription() {
        System.out.println("-- Dinner decorator --");
        super.getDescription();
        actingAtDinnerParty();
    }

    void actingAtDinnerParty() {
        System.out.println("I am casual wearing and have fun!");
    }
}

运行结果:

实现关键:

× 装饰器里不继承实体类对象,而是在实体类对象的前后添加额外功能。

 

后记:

装饰器相比与继承的优点在于,一个装饰器能装饰不同的类,只要这些被装饰的类具有相同的接口即可(即实现了一开始所说的“动态添加功能”)。而如果要用继承来实现,每一个类都要分别继承并重写方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值