目录
https://blog.csdn.net/dongganen/article/details/79688794
定义装饰者模式
装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
案例分析
楼下新开了一家牛肉面店,有牛肉面15块,羊肉面20块,海鲜面25块,另外加荷包蛋3块,面结5块,豆腐4块,香菜1块。
硬编码,使用继承
我们对所有的面加佐料进行排列组合,类爆炸
//牛肉面
class BeefNoodles extends Noodles{
}
//牛肉面加鸡蛋
class BeefAndEggNoodles extends Noodles{
}
//牛肉面加鸡蛋加豆腐
class BeefAndEggAndTofuNoodles extends Noodles{
}
//羊肉面
class SheepNoodles extends Noodles{
}
//羊肉面加鸡蛋
class SheepAndEggNoodles extends Noodles{
}
//羊肉面加鸡蛋加豆腐
class SheepAndEggAndTofuNoodles extends Noodles{
}
//海鲜面
class SeaNoodles extends Noodles{
}
//海鲜面加鸡蛋
class SeaAndEggNoodles extends Noodles{
}
//海鲜面加鸡蛋加豆腐
class SeaAndEggAndTofuNoodles extends Noodles{
}
使用实例变量和组合
分析
我们让Noodles持有各种辅料的引用
代码
//装饰者模式
public class Decker {
public static void main(String[] args) {
Noodles noodles = new BeefNoodles();
noodles.setEgg(true);
noodles.setTofu(true);
System.out.println( noodles.cost() + " " + noodles.getDesc());
}
}
//面条
abstract class Noodles{
String desc = "";
Boolean egg = false;
Boolean mianjie= false;
Boolean tofu = false;
Boolean coriander = false;
abstract double cost();
protected double otherCost(){
double cost = 0.00;
if(getEgg()){
desc += " egg";
cost += 3.00;
}
if(getMianjie()){
desc += " mianjie";
cost += 5.00;
}
if(getTofu()){
desc += " tofu";
cost += 4.00;
}
if(getCoriander()){
desc += " coriander";
cost += 1.00;
}
return cost;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Boolean getEgg() {
return egg;
}
public void setEgg(Boolean egg) {
this.egg = egg;
}
public Boolean getMianjie() {
return mianjie;
}
public void setMianjie(Boolean mianjie) {
this.mianjie = mianjie;
}
public Boolean getTofu() {
return tofu;
}
public void setTofu(Boolean tofu) {
this.tofu = tofu;
}
public Boolean getCoriander() {
return coriander;
}
public void setCoriander(Boolean coriander) {
this.coriander = coriander;
}
}
//牛肉面
class BeefNoodles extends Noodles{
public BeefNoodles(){
desc += "BeefNoodles ";
}
@Override
double cost() {
return 15.00 + super.otherCost();
}
}
//羊肉面
class SheepNoodles extends Noodles{
public SheepNoodles(){
desc += "SheepNoodles ";
}
@Override
double cost() {
return 20.00 + super.otherCost();
}
}
//海鲜面
class SeaNoodles extends Noodles{
public SeaNoodles(){
desc += "SeaNoodles ";
}
@Override
double cost() {
return 25.00 + super.otherCost();
}
}
分析
这比使用继承解决已经上了一个台阶。
1. 调整价钱会修改otherCost里的逻辑,容易出错
2. 一旦出现新的辅料,会修改原来封装的逻辑,容易出错
认识装饰者模式
我们以面条为主体,然后在运行时以调料来”装饰”面条。
比如说我现在点了一碗牛肉面,用荷包蛋去装饰他,用面结去装饰他,调用方法,并依赖委托把价钱的描述加上去。
UML
- 装饰者和被装饰者有相同的类型。
- 你可以用一个或多个装饰者包装一个对象。
- 既然装饰者和被装饰者具有相同的超类型,所以在任何需要原始对象的地方都可以用装饰过的对象代替他。
- 装饰者可以在所委托被装饰者前后,加上自己的行为,以达到目的。
- 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
代码
//装饰者模式
public class Decker {
public static void main(String[] args) {
//老板来一碗牛肉面
Noodles noodles = new BeefNoodles();
//价格鸡蛋
noodles = new Egg(noodles);
//加个面结
noodles = new Mianjie(noodles);
System.out.println(noodles.getDesc() + " " + noodles.cost());
}
}
//面条
abstract class Noodles{
String desc = "";
abstract double cost();
public String getDesc() {
return desc;
}
}
//面条装饰者
abstract class NoodlesDecorator extends Noodles{
public abstract String getDesc();
}
//牛肉面
class BeefNoodles extends Noodles{
public BeefNoodles(){
desc += "BeefNoodles ";
}
@Override
double cost() {
return 15.00;
}
}
//羊肉面
class SheepNoodles extends Noodles{
public SheepNoodles(){
desc += "SheepNoodles ";
}
@Override
double cost() {
return 20.00;
}
}
//海鲜面
class SeaNoodles extends Noodles{
public SeaNoodles(){
desc += "SeaNoodles ";
}
@Override
double cost() {
return 25.00;
}
}
//鸡蛋
class Egg extends NoodlesDecorator{
Noodles noodles;
public Egg(Noodles noodles){
this.noodles = noodles;
}
@Override
double cost() {
return 3.00 + noodles.cost();
}
@Override
public String getDesc() {
return noodles.getDesc() + " 加鸡蛋";
}
}
//面结
class Mianjie extends NoodlesDecorator{
Noodles noodles;
public Mianjie(Noodles noodles){
this.noodles = noodles;
}
@Override
double cost() {
return 5.00 + noodles.cost();
}
@Override
public String getDesc() {
return noodles.getDesc() + " 加面结";
}
}
//豆腐
class Tofu extends NoodlesDecorator{
Noodles noodles;
public Tofu(Noodles noodles){
this.noodles = noodles;
}
@Override
double cost() {
return 4.00 + noodles.cost();
}
@Override
public String getDesc() {
return noodles.getDesc() + " 加豆腐";
}
}