设计模式—装饰者模式(用麻辣烫来分析)

转载注明出处:https://blog.csdn.net/qq_39071530/article/details/84671850

github地址 https://github.com/esmusssein777/designpatterns

设计模式目录 https://blog.csdn.net/qq_39071530/article/details/84849070

 

首先做一个假设

假设你要开一家麻辣烫的店了

你要为你们的麻辣烫的店设计一个自动收钱的程序

我们先来思考一下需求

麻辣烫收钱有两部分,一部分是底料的钱,一部分是配料的钱

底料有各种档次不一的底料,不能收一样的钱,比如三鲜、牛油、麻辣、骨汤等等

配料有热狗、生菜、鸡肉等等好多的好多。

那么你会怎么设计呢

 

假设每一个底料和配料都是单独的一个类

那么他们都要实现相同的方法 getDescription() 和 cost()。获得描述和花费的钱。

这违背了我们设计模式的原则。找出程序中会变化的方面,然后将其和固定不变的地方相分离

 

于是有人想到了继承

我们有一个超类里面有这两个方法。其他的所有底料都继承这两个方法。

但是这样设计我们计算价格的时候会有bug。如果有人只点配料不点底料,那么程序也可以照样的执行。

亏本的生意不能做。。。

 

还有人想到这种

在超类中将每个配料都放进去,那么我们点底料时继承这个超类,再将需要什么配料的布尔值传进去,超类计算配料的价格,子类计算底料的价格。

这种是可行的,但是有很大的缺陷。

如果配料的价格改变我们会改变超类的代码。

有新来的配料了我们也要改代码。

如果有某个人想要两根热狗怎么办。。。。。。

这违背了设计模式的原则

类应该对扩展开放,对修改关闭

 

 

终于来到了今天的模式

装饰者模式。

 底料是被装饰者

 配料是装饰者

我们先来看测试的代码

package org.ligz.DesignPatterns.Decorator.mala;

/**
 * @author ligz
 */
public class Test {
	public static void main(String[] args) {
		System.out.println("只要一个清汤底料");
		Primer broth = new Broth();
		System.out.println(broth.getDescription()+"需要花"+broth.cost());
		
		
		System.out.println("我要一个麻辣底料和热狗在加生菜");
		Primer spicy = new Spicy();
		spicy = new HotDog(spicy);
		spicy = new Lettuce(spicy);
		System.out.println(spicy.getDescription()+"需要花"+spicy.cost());
	}
}
只要一个清汤底料
清汤需要花10.0
我要一个麻辣底料和热狗在加生菜
麻辣加一根热狗加生菜需要花15.0

 下面是实现的代码

package org.ligz.DesignPatterns.Decorator.mala;

/**
 * primer底料
 *     麻辣烫的底料,暂时列出清汤和麻辣两种
 * @author ligz
 */
public abstract class Primer {
	String description = "麻辣烫底料";
	
	public String getDescription() {
		return description;
	}
	
	public abstract double cost();
}
package org.ligz.DesignPatterns.Decorator.mala;

/**
 * 清汤
 * @author ligz
 */
public class Broth extends Primer{
	public Broth() {
		description = "清汤";
	}

	@Override
	public double cost() {
		return 10;
	}
	
}
package org.ligz.DesignPatterns.Decorator.mala;

/**
 * 麻辣
 * @author ligz
 */
public class Spicy extends Primer{
	public Spicy() {
		description = "麻辣";
	}

	@Override
	public double cost() {
		return 12;
	}
}
package org.ligz.DesignPatterns.Decorator.mala;

/**
 * 抽象装饰者
 * @author ligz
 */
public abstract class ComdimentDecorator extends Primer{
	public abstract String getDescription();
}
package org.ligz.DesignPatterns.Decorator.mala;

/**
 * 热狗
 * 热狗是一个装饰者,底料是一个被装饰者
 * 用抽象的装饰者将所有的描述,包括底料和配料
 * @author ligz
 */
public class HotDog extends ComdimentDecorator{
	Primer primer;

	public HotDog(Primer primer) {
		this.primer = primer;
	}

	@Override
	public String getDescription() {
		return primer.getDescription() + "加一根热狗";
	}

	@Override
	public double cost() {
		return primer.cost()+ 2;
	}

}
package org.ligz.DesignPatterns.Decorator.mala;

/**
 * 生菜
 * 生菜是一个装饰者,底料是一个被装饰者
 * 用抽象的装饰者将所有的描述,包括底料和配料
 * @author ligz
 */
public class Lettuce extends ComdimentDecorator{
	Primer primer;

	public Lettuce(Primer primer) {
		this.primer = primer;
	}

	@Override
	public String getDescription() {
		return primer.getDescription() + "加生菜";
	}

	@Override
	public double cost() {
		return primer.cost()+ 1;
	}
}

 

装饰者可以在所委托被装饰者的行为前和后,加上自己的行为。已达到特定的目的。

 

我们再来看定义。

装饰者模式动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值