设计模式系列(结构型模式)之二 装饰模式

装饰模式

在不改变原有对象的基础之上,动态地将额外的功能附加到该对象上,提供了比继承更有弹性的替代方案。

适用于:
拓展一个类的功能;
动态给对象添加功能,并且动态撤销。

优点:
继承的有力补充,不改变原有对象的情况下给对象拓展功能;
通过使用不同的装饰类、不同的组合方式,实现不同的效果。
符合开闭原则。

缺点:
装饰模式增加了许多子类,如果过度使用会使程序变得很复杂,增加程序复杂性;

装饰模式主要包含以下角色。
抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
具体构件(Concrete Component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

比如去沙县吃面的时候,可以往面里加鸡蛋和肉末啥的,价格也会相应的调整,要支持不同食物自由组合,并计算相应的价格,则可以使用装饰模式来完成。
1.假设去沙县吃碗面,定义一个面条的抽象类,里面有备注和价格两个抽象方法

public abstract class NoodlesAbstract {
    public abstract int price();
    public abstract String remark();
}

2.定义一个面条抽象类的装饰器,继承自面条抽象类,重写抽象类的抽象方法

public abstract class NoodlesAbstractDecorator extends NoodlesAbstract {
    private NoodlesAbstract noodles;

    public NoodlesAbstractDecorator(NoodlesAbstract noodles) {
        this.noodles = noodles;
    }

    @Override
    public String remark(){
        return noodles.remark();
    }

    @Override
    public int price(){
        return noodles.price();
    }
}

3.创建初始的面条类,继承自面条抽象类

public class Noodles extends NoodlesAbstract{
    @Override
    public String remark(){
        return "点了一碗面";
    }
    @Override
    public int price(){
        return 10;
    }
}

4.定义一个鸡蛋装饰器继承自面条装饰器,吃面的时候可以加个蛋

public class EggDecorator extends NoodlesAbstractDecorator{
    public EggDecorator(NoodlesAbstract noodles) {
        super(noodles);
    }
    @Override
    public String remark(){
        return super.remark()+",加了一个蛋";
    }
    @Override
    public int price(){
        return super.price()+2;
    }
}

5.定义一个肉末装饰器继承自面条装饰器,吃面的时候可以加点肉末

public class MeatDecorator extends NoodlesAbstractDecorator {
    public MeatDecorator(NoodlesAbstract noodles) {
        super(noodles);
    }
    @Override
    public String remark(){
        return super.remark()+",加了点肉末";
    }
    @Override
    public int price(){
        return super.price()+5;
    }
}

6.测试输出,有两种写法

public class Test {
    public static void main(String[]args){
        //写法一
        NoodlesAbstract noodles=new Noodles();
        noodles=new EggDecorator(noodles);
        noodles=new MeatDecorator(noodles);
        System.out.println(noodles.remark()+" 价格要"+noodles.price()+"元");
        
        //写法二
        NoodlesAbstract noodles2=new Noodles();
        //在括号里的会先加进去
        noodles2=new EggDecorator(new MeatDecorator(noodles2));
        System.out.println(noodles2.remark()+" 价格要"+noodles2.price()+"元");
    }
}
//点了一碗面,加了一个蛋,加了点肉末 价格要17元
//点了一碗面,加了点肉末,加了一个蛋 价格要17元

通过不同的装饰器自由组合,我们可以灵活的加自己喜欢吃的东西,这是装饰模式的优点,但明显可以看出代码变复杂了。下一篇讲讲适配器模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值