2

装饰器模式

被这个模式困惑了一段时间,其实是被一些术语吓到了,其实并没有那么难。

通俗来说,就是一个对象原来有一些功能,然后发现功能不够用,想让这个对象更加强大,就使用一个装饰器对这个对象装饰一下,给其在原有的基础上装饰功能。

实现装饰的核心就是这个对象的装饰前后类型不变,所以被装饰的就应该是一个接口或抽象类类型,被装饰器装饰之后还是可以指向接口或抽象类。

以接口为例

总接口People

/**
 * 一个人的接口
 */
public interface People {

    // 这个人有描述自己的方法
    void show();
}

基础的实现,普通人:

/**
 * People的基础实现,一无所有的普通人
 */
public class CommonPeople implements People {

    @Override
    public void show() {
        System.out.println("普通人,一无所有");
    }
}

三个装饰器,分别为人装饰车、房、对象。

每个装饰器都是调用原People的方法,然后为其添加本类应该装饰的功能。所有的装饰器都需要实现People接口(如果采用抽象类实现需要继承抽象类),保证这个对象被装饰之后仍然是People类型。

/**
 * 车装饰器
 */
public class CarDecorator implements People {

    private People people;

    public CarDecorator(People people) {
        this.people = people;
    }

    @Override
    public void show() {
        this.people.show();
        System.out.println("许多年后,终于有车了");
    }
}
/**
 * 房装饰器
 */
public class HouseDecorator implements People {

    private People people;

    public HouseDecorator(People people) {
        this.people = people;
    }

    @Override
    public void show() {
        this.people.show();
        System.out.println("许多年后,终于有房了");
    }
}
/**
 * 对象装饰器
 */
public class ObjectDecorator implements People {

    private People people;

    public ObjectDecorator(People people) {
        this.people = people;
    }

    @Override
    public void show() {
        this.people.show();
        System.out.println("许多年后,终于有对象了");
    }
}

装饰

public class Main {

    public static void main(String[] args) {
        // 一无所有的普通人
        People people = new CommonPeople();
        people.show();

        System.out.println("-------------------");

        // 这个人有车了
        people = new CarDecorator(people);
        people.show();

        System.out.println("-------------------");

        // 这个人有房了
        people = new HouseDecorator(people);
        people.show();

        System.out.println("-------------------");

        // 这个人有对象了
        people = new ObjectDecorator(people);
        people.show();
    }
}

运行结果:

clipboard.png

如果不使用装饰器,我们无法这么随意地去拓展对象的功能。

如果不使用装饰器,类有什么功能,new出来的对象就有什么功能。三个装饰器,可以排列组合,有房有车的人,有房有对象的人,随意地为这个对象添加功能,想要什么就加什么。而不是像之前生硬地继承,new什么就有什么功能。

装饰器使用

说起装饰器,AngularJS中可是提供了非常详尽的支持,Decorators in AngularJS

clipboard.png

就比如AngularJS中的装饰器,如果是我们自己写的一个Service,有一天发现功能不够用了,随便改,反正是我自己写的代码。

但是如果你发现第三方库给你提供的Service方法不够用呢?去改它的代码吗?这是不现实的。

这个慕课网的课程描述了当开发阿里云时,发现UI-Bootstrap中的一个popover组件不能自定义模板(现在的UI-Bootstrap已解决此问题),基于公共组件的开发心得 - 阿里懒懒交流会AngularJS专场

解决方案:

一、改掉它的源代码,自己发布一个库,然后项目中使用这个修改完的库。(没错,阿里的大大们就是这么干的。)

二、设置装饰器,用装饰器为原组件添加新功能。(这个在视频中也提到了,不过是在他们用方案一解决完这个问题时才发现的新方案。偷偷地去看过阿里云中关于popover弹窗的代码,还是用的方案一,可能时间久了,不好改动。)


张喜硕
2.1k 声望423 粉丝

浅梦辄止,书墨未浓。


« 上一篇
观察者模式
下一篇 »
Spring IOC 学习