设计模式 - 装饰者模式

 代码案例:(末尾有完整代码)

简单介绍下上图的结构

1. 抽象类 快餐--和子实现类:炒饭和炒面

2. 抽象类 配料--和子实现类:鸡蛋和培根

该模式解决的问题:假如我想点个炒饭,配料是鸡蛋,那【一般方式】是不是得新增一个炒饭类的子类(鸡蛋炒饭)去做一个增强(扩展)。而此时,我朋友想点个炒面,配料也是鸡蛋,他是不是也得和我一样去新增一个炒面类的子类(鸡蛋炒面)。问题就在这:鸡蛋这个东西就是重复的!累赘的!(假如你有100个快餐的子类都想要加鸡蛋这个配料,那是不是得写100个子类呢?)

解决办法:

于是,我们就可以把配料做一个抽象。但同时,不只是抽象个配料类Garnish这么简单,需要我们去让每一个配料类的子类都能够对某种FastFood的子实现类去做一个增强(扩展)

重点分析--上图中:

抽象类 配料继承了快餐类,原因是:我们的目标只是利用配料类去对快餐类进行增强(扩展),但不会改变他本身,他还是一个快餐,本质不变,但又可以进行增强(扩展);

抽象类配料Garnish 中包含了一个快餐类对象实例fastFood,而我们将要对他进行增强(扩展)。目的:将这个快餐类的对象实例放进配料类Garnish中,就可以利用多态的特性,达到 FastFood的子实现类与Garnish的子实现类组合在一起(多对多) 的目的!

这里面体现的最基础的思想就是“多态”,这种思想无非就是实现“多对一”,(多个子类,一个父类),上面代码中,两个抽象父类的一个“配合”,实现了多对多的目的(各自的子类可以进行组合使用,例如:不同的炒饭可以与不同的配料组合),最明显的优点:减少子类数量(我想要点一个鸡蛋炒饭,就不用专门新增一个炒饭类FriedRice的子类),扩展性更强了(现在要求新增一种新的配料或新快餐,直接继承父类配料类或快餐类,不影响功能,超方便的哎!)

我的理解图:

 装饰者模式的基本概念

现在再来看看他的4个角色的基本概念就好懂了:

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

  • 具体构件(Concrete Component)角色 :实现抽象构件,通过装饰角色为其添加一些职责。

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

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

【快餐类FastFood】:是将要被增强(扩展)的一个抽象类,不就是“抽象构件-Component” 嘛。

【FastFood的子实现类】:就是抽象构件下,具体的、将被增强的 对象,也就是“具体构件-Concrete Component”

【配料类】:他继承了快餐类,且拥有一个快餐类实例。于是可以接收一个快餐类的子实现类(具体构件),再对他进行增强(扩展)后再返回。能完成这个增强任务的抽象类就称为“抽象装饰-Decorator”

【配料类的子类】:他具体代表的是某一种增强(扩展)的方式,完成了父类配料类的任务,称为“具体装饰-ConcreteDecorator”

总结:

理解更深入了,我觉得这个模式思想基础依然是“继承”“多态”的演化。同时我觉得日后再回头看这个时,应该又会有更好的想法和解释了。

以上都是我个人结合代码例子去理解这个设计模式,希望大家可以多多探讨下,交流下思想。

下面附上实例代码:

//快餐接口
public abstract class FastFood {
    private float price;
    private String desc;

    public FastFood() {
    }

    public FastFood(float price, String desc) {
        this.price = price;
        this.desc = desc;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public float getPrice() {
        return price;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public abstract float cost();  //获取价格
}

//炒饭
public class FriedRice extends FastFood {

    public FriedRice() {
        super(10, "炒饭");
    }

    public float cost() {
        return getPrice();
    }
}

//炒面
public class FriedNoodles extends FastFood {

    public FriedNoodles() {
        super(12, "炒面");
    }

    public float cost() {
        return getPrice();
    }
}

//配料类
public abstract class Garnish extends FastFood {

    private FastFood fastFood;

    public FastFood getFastFood() {
        return fastFood;
    }

    public void setFastFood(FastFood fastFood) {
        this.fastFood = fastFood;
    }

    public Garnish(FastFood fastFood, float price, String desc) {
        super(price,desc);
        this.fastFood = fastFood;
    }
}

//鸡蛋配料
public class Egg extends Garnish {

    public Egg(FastFood fastFood) {
        super(fastFood,1,"鸡蛋");
    }

    public float cost() {
        return getPrice() + getFastFood().getPrice();
    }

    @Override
    public String getDesc() {
        return super.getDesc() + getFastFood().getDesc();
    }
}

//培根配料
public class Bacon extends Garnish {

    public Bacon(FastFood fastFood) {

        super(fastFood,2,"培根");
    }

    @Override
    public float cost() {
        return getPrice() + getFastFood().getPrice();
    }

    @Override
    public String getDesc() {
        return super.getDesc() + getFastFood().getDesc();
    }
}

//测试类
public class Client {
    public static void main(String[] args) {
        //点一份炒饭
        FastFood food = new FriedRice();
        //花费的价格
        System.out.println(food.getDesc() + " " + food.cost() + "元");

        System.out.println("========");
        //点一份加鸡蛋的炒饭
        FastFood food1 = new FriedRice();

        food1 = new Egg(food1);
        //花费的价格
        System.out.println(food1.getDesc() + " " + food1.cost() + "元");

        System.out.println("========");
        //点一份加培根的炒面
        FastFood food2 = new FriedNoodles();
        food2 = new Bacon(food2);
        //花费的价格
        System.out.println(food2.getDesc() + " " + food2.cost() + "元");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值