转载注明出处:https://blog.youkuaiyun.com/qq_39071530/article/details/84671850
github地址 https://github.com/esmusssein777/designpatterns
设计模式目录 https://blog.youkuaiyun.com/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;
}
}
装饰者可以在所委托被装饰者的行为前和后,加上自己的行为。已达到特定的目的。
我们再来看定义。