装饰者模式,真是越来越生活化了,其实设计不就是源于生活高于生活吗?人类,一般总是把生活中观察的东西作为原料才能抽象出东西。装饰者模式,就是用各种装饰者对象来给被装饰者装饰,达到人们的多种多样的需求。不举咖啡的例子,实在没喝过几杯正式的咖啡。考虑炒饭,主要的原材料就是饭,但是变种非常多,近几天我就吃过和有深印象的,扬州炒饭、生牛肉炒饭、五香肉丁炒饭、XO酱海鲜炒饭、黄金炒饭、蛋炒饭等,像什么牛肉、葱花、肉丁、鸡蛋就是装饰者了,厨师用他们炒出(装饰出)各种饭。这种模式的优点是可以订制各种各样的需求,不再面临类爆炸的问题,我们只需要用组合就可以解决问题了。
怎么实现呢?
首先看,这是一个抽象被装饰者类,所谓的饭。 package com.csshu; /** * 抽象的组件类,饮料基类,抽象类,是所有饮料的基础类,这里也可以设计成接口 * @author shujianhua * */ public abstract class Beverage { String description = "Unknown Beverage"; // 在子类中必须重写这个类 public String getDescription(){ return description; } // 抽象类,子类必须重写它 public abstract double cost(); } 可以设计成接口也可以是抽象类。 下面这个是装饰者类的抽象类 package com.csshu; /** * 调料装饰者类,抽象的,简称抽象的装饰者类,由众多调料来继承它,属于装饰者类的抽象类 * 为什么用继承,因为保持类型一致。 * @author shujianhua * */ public abstract class CondimentDecorator extends Beverage{ // 抽象类,子类必须重写它 public abstract String getDescription(); } 为什么要继承被装饰者类,为了保持类型一致,以后装饰的时候方便,可以说都是大地之物。 下面这个是具体的被装饰者类 package com.csshu; /** * 这是具体的组件类,属于饮料类的一种,属于最原始的东西,比如一杯原味奶茶 * @author shujianhua * */ public class Espresso extends Beverage{ // 考虑饮料的最原始名字,一杯原味奶茶 public Espresso(){ description = "Espresso"; // 这个是继承,所以可以用父类的变量 } @Override public double cost() { return 1.99; } } package com.csshu; /** * 这是具体的组件类,属于饮料类的一种,属于最原始的东西,比如一杯原味奶茶 * @author shujianhua * */ public class HouseBlend extends Beverage{ // 考虑饮料的最原始名字,一杯原味奶茶 public HouseBlend(){ description = "HouseBlend"; // 这个是继承,所以可以用父类的变量 } @Override public double cost() { return 0.99; } } 下面是具体的被装饰者类, package com.csshu; /** * 调料装饰者类,具体的,具体的装饰者类 * @author shujianhua * */ public class Mocha extends CondimentDecorator{ Beverage beverage; // 通过构造函数来实现包裹类,来装饰 public Mocha(Beverage beverage){ this.beverage = beverage; } // 这个叫做委托 @Override public double cost() { return 0.20+beverage.cost(); } // 这个叫做委托delegation,在最后的输出类中可以吧描述,装饰者全部输出 @Override public String getDescription() { return beverage.getDescription()+",Mocha"; } } package com.csshu; /** * 调料装饰者类,具体的,具体的装饰者类 * @author shujianhua * */ public class Soy extends CondimentDecorator{ Beverage beverage; // 通过构造函数来实现包裹类,来装饰 public Soy(Beverage beverage){ this.beverage = beverage; } // 这个叫做委托 @Override public double cost() { return 0.39+beverage.cost(); } // 这个叫做委托delegation,在最后的输出类中可以吧描述,装饰者全部输出 @Override public String getDescription() { return beverage.getDescription()+",Soy"; } } package com.csshu; /** * 调料装饰者类,具体的,具体的装饰者类 * @author shujianhua * */ public class Whip extends CondimentDecorator{ Beverage beverage; // 通过构造函数来实现包裹类,来装饰 public Whip(Beverage beverage){ this.beverage = beverage; } // 这个叫做委托 @Override public double cost() { return 0.53+beverage.cost(); } // 这个叫做委托delegation,在最后的输出类中可以吧描述,装饰者全部输出 @Override public String getDescription() { return beverage.getDescription()+",Whip"; } } 发现上面并没有上面多大的不同。。 接下来是入口main函数, package com.csshu; /** * 这里是允许装饰者模式的入口。 * 我们来看,Beverage是抽象的组件类,HouseBlend和Espresso是具体的组件类 * CondimentDecorator是抽象的装饰者类,Mocha和Soy以及Whip是具体的装饰者类 * @author shujianhua * */ public class DecoratorEnter { public static void main(String[] args) { Beverage beverage1 = new Espresso(); System.out.println(beverage1.cost()+"dao,"+beverage1.getDescription()); Beverage beverage = new HouseBlend(); beverage = new Mocha(beverage); // 这里就是包装者,包进去了,其实装饰者装饰的顺序不重要 beverage = new Soy(beverage); beverage = new Whip(beverage); System.out.println(beverage.cost()+"dao,"+beverage.getDescription()); } } 可以看到,首先new出了一个实体类,然后实体类的引用继续迭代引用其它装饰者包裹的新类。虽然是不断地引用其它,但是实体类的引用在这里面获得了很多新的属性。关键就是委托 (delegation)和接口的使用,一层层的传进去,最后一层层地传出来。
时间: 2024-10-12 20:57:23