牛骨文教育服务平台(让学习变的简单)

装饰模式(包装模式),也是结构型设计模式之一。它主要用于动态地对一个类或者对象添加新的功能,使得原有的类得到扩展,与代理模式不同的是该模式是直接对一个原有的对象进行扩展功能,而代理模式代理原对象的行为,而不是对原来的对象进行扩展。同时也不同于适配器模式,适配器模式是对一个接口或者类进行适配,使得在新的场合下也可以使用。而装饰模式则是对对象进行扩展包装,是继承关系的代替方案。但比继承的子类更加灵活,因为在关系上包装的类与被包装的类不是继承关系。

定义:动态地对一个对象进行装饰(包装),以使得该对象具有更多的功能。

使用场景:

  • 需要透明或者动态地扩展类的功能,即需要对类进行包装。

与代理模式的区别:

  • 可以将这种模式说成是代理模式的特殊情况,但装饰模式是对类行为或者说功能进行扩展,增强类的功能。而代理模式强调通过一个代理对象对原对象的行为施加控制,而不对类本身扩展功能。这两种模式很相似,因此要细心加以区分。

装饰模式的例子在生活中也随处可见,生活中的万物可以都需要进行包装,如水果,店铺,教室等等,甚至我们人也要进行包装,如穿衣服,带帽子等等以便我们自己的形象更加好。所以,下面以生活中的一个小例子来用代码实现装饰模式,以便我们对装饰模式有一个清晰的认识。

假设我们开了一个淘宝店铺,那么我们在卖商品前要对我们的淘宝店进行装饰。什么logo,公告,背景音乐等等。

代码实现:

店铺(接口)

/**
 * 店铺(接口),淘宝给商家开放的一个接口
 * @author lt
 *
 */
public interface ShopI {

    /**
     * 展示
     */
    public void show();
}

淘宝店(被装饰的对象)

public class TaobaoShop implements ShopI{

    private String name;
    public TaobaoShop(String name){
        this.name = name;
    }
    /**
     * 展示
     */
    @Override
    public void show() {
        System.out.println("名字:"+name);
    }
}

装饰后的淘宝店(装饰对象)

public class DecoratedShop implements ShopI{

    private ShopI shop; // 持有一个要装饰对象的引用,通过该引用对对象进行装饰

    public DecoratedShop(ShopI shop){
        this.shop = shop;
    }

    /**
     * logo,我们扩展的功能
     */
    private void logo(){
        System.out.println("logo:特卖Logo");
    }

    /**
     * 背景音乐,我们扩展的功能
     */
    private void bgMusic(){
        System.out.println("背景音乐:你是我的小啊小苹果,怎么爱你都不嫌多...");
    }

    /**
     * 公告,我们扩展的功能
     */
    private void notice(){
        System.out.println("公告:这是一家专门做特卖的店铺,原装正品,童叟无欺!");
    }

    @Override
    public void show() {
        shop.show();
        logo(); // 上传logo
        notice(); // 发布公告
        bgMusic(); // 添加背景音乐
    }
}

说明:这里装饰对象和被装饰对象实现相同的接口是为了使得装饰对象对原对象功能装饰包装得对客户端更加能透明,也可以不用实现相同的接口,如果装饰对象通过继承被装饰对象以扩展它的功能的话,那就是继承关系了。

测试:

public class Test {

    public static void main(String[] args) {
        // 申请一个淘宝店,叫微真会
        TaobaoShop newShop = new TaobaoShop("微真会");
        System.out.println("刚申请的店铺:");
        newShop.show();

        // 对这个店铺进行装饰
        DecoratedShop decoratedShop = new DecoratedShop(newShop);
        System.out.println("装饰后的店铺:");
        decoratedShop.show();
    }
}

Run AS:

这里写图片描述

如果我们在对原对象(newShop)进行show()方法调用,那么还是会显示只有一个名字,因为我们进仅仅是对原对象进行了一层包装,而并没有改变原对象的功能,原对象脱离了装饰它的对象那么就只有原来的功能了,就像我们人一样,卸掉身上的装饰品后还是我们自己,但就是更不那么好看了。

总结:

装饰模式特别容易理解,因为这样的例子在我们生活中随处可见,完全可以通过字面进行理解,即装饰。但我们要注意细心区分装饰模式和代理模式的区别,因为这两种模式特别像,区别在于代理原对象的行为还是要扩展原对象的行为以装饰包装原对象。