设计模式之——装饰器模式

一、基本介绍

装饰器模式(结构型):在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,即对核心功能进行拓展。

二、包含角色

1.抽象构件角色:定义一个抽象接口以规范准备接收附加责任的对象。

2.具体构件角色:实现抽象构件,该角色提供核心功能,被包装的角色。

3.抽象装饰角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。

4.具体装饰角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

三、案例及UML类图

案例说明:

          煎饼主要分为山东的杂粮煎饼和天津的煎饼果子,煎饼都有name和生产的方法,当我们吃煎饼的时候总是需要加一些辅料(即扩增功能),如鸡蛋,火腿,肉松等,但是我们不确定客户会加一样或者多样,但归根到底都是在其煎饼上加(也就是为核心功能进行扩增),如果使用继承的方式,需要为煎饼类的子类山东煎饼或天津煎饼创建更多的子类,如鸡蛋山东煎饼、鸡蛋天津煎饼、鸡蛋火腿山东煎饼等等,如果再新增一种辅料或一个其它类型的煎饼,则要扩增更多的子类,会产生类爆炸的问题。

UML类图:

类Pancake:

public abstract class Pancake {

    protected String name;

    /**
     * 做出一张煎饼
     */
    public abstract void product();

}

说明:煎饼抽象类,抽象构件角色,定义煎饼的属性和功能。

类ShandongPancake:

public class ShandongPancake extends Pancake {

    public ShandongPancake() {
        name = "山东煎饼";
    }

    @Override
    public void product() {
        System.out.println("正在做:"+name);
    }
}

说明:山东煎饼类,具体构件角色,生产山东煎饼。

类TianjinPancake:

public class TianjinPancake extends Pancake {

    public TianjinPancake() {
        name = "天津煎饼";
    }

    @Override
    public void product() {
        System.out.println("正在做:"+name);
    }
}

说明:天津煎饼类,具体构件角色,生产天津煎饼。

类PancakeAddIngredients:

public abstract class PancakeAddIngredients extends Pancake {

    private Pancake pancake;

    public PancakeAddIngredients(Pancake pancake) {
        this.pancake = pancake;
    }

    @Override
    public void product() {
        pancake.product();
    }
}

说明:辅料抽象类,抽象装饰角色,定义辅料的功能和方法,并调用煎饼的核心方法。

类EggAddIngredients:

public class EggAddIngredients extends PancakeAddIngredients {
    
    public EggAddIngredients(Pancake pancake) {
        super(pancake);
    }

    @Override
    public void product() {
        super.product();
        addEgg();
    }


    public void addEgg() {
        System.out.println("添加鸡蛋");
    }
}

说明:鸡蛋辅料类,具体装饰角色,对煎饼进行鸡蛋的添加。

类HamAddIngredients:

public class HamAddIngredients extends PancakeAddIngredients {

    public HamAddIngredients(Pancake pancake) {
        super(pancake);
    }


    @Override
    public void product() {
        super.product();
        addHam();
    }


    public void addHam() {
        System.out.println("添加火腿");
    }
}

说明:火腿辅料类,具体装饰角色,为煎饼进行火腿的添加。

类DecoratorTest:

public class DecoratorTest {

    public static void main(String[] args) {
        //吃一个山东煎饼
        Pancake pancake = new ShandongPancake();
        //把煎饼放入鸡蛋装饰着中加鸡蛋
        Pancake egg = new EggAddIngredients(pancake);
        //做一个山东鸡蛋煎饼
        egg.product();

        //吃一个天津煎饼
        pancake = new TianjinPancake();
        //把煎饼放入鸡蛋装饰着中加鸡蛋
        egg = new EggAddIngredients(pancake);
        //把加了鸡蛋的煎饼放入火腿装饰着中加火腿
        Pancake ham = new HamAddIngredients(egg);
        //做一个天津鸡蛋火腿煎饼
        //注意此时已经为两次装饰
        ham.product();
    }
}

说明:测试及客户端类。

四、适用场景

1.当需要给一个现有类添加附加职责或功能,而又不能采用生成子类的方法进行扩充时。

2.当对象的拓展功能要求可以动态地添加,也可以再动态地撤销时。

3.当需要通过对现有的一组基本功能进行扩增,且这些功能不确定叠加情况时使用装饰者能很好解决。

 

五、其它

注意:在实际开发中,抽象装饰角色很多情况下都是没有的,例如IO模块和mybatis的缓存模块中都不存在抽象装饰角色,抽象装饰角色在一定程度上增加了代码的复杂度。

发布了35 篇原创文章 · 获赞 61 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/m0_37914588/article/details/103903453