一、简介
装饰者模式要求有一个被装饰对象及多个装饰者,每个装饰者与被装饰者实现同一个接口或有同一个超类,被装饰者持有一个装饰者对象,所有实现由持有对象完成,装饰者则在方法执行过程中增强方法实现(如:在方法执行前进行权限验证,在返回结果前进行加密处理等)。
二、代码示例
要求:
商家活动要求商品具有多种打折方式在不同节日使用:
1、满30元减5元,满50元减10元,满100元减30元
2、满30元打9.5折,满50元打9折,满100元打8折
3、…..更多活动待扩展
商品接口:
public interface IGoods {
//商品描述
String getDescription();
//获得商品价格
double getPrice();
}
普通商品类:
public class NomalGoods implements IGoods{
private String description;
private double price;
//构造器:初始化商品描述、价格
public NomalGoods(String description,double price) {
this.description = description;
this.price = price;
}
@Override
public String getDescription() {
return this.description;
}
@Override
public double getPrice() {
return this.price;
}
}
打折商品类:
public class DiscountGoods implements IGoods {
private IGoods goods;
//构造器:获得被装饰对象
public DiscountGoods(IGoods goods) {
this.goods = goods;
}
@Override
//获取商品价格,根据活动要求对价格进行相应折扣处理
public double getPrice() {
double price = this.goods.getPrice();
if(price<30){
price *= 0.95;
}else if(price<50){
price *= 0.9;
}else{
price *= 0.8;
}
return price;
}
@Override
//获取商品描述并添加折扣商品标志
public String getDescription() {
return this.goods.getDescription()+"---折扣商品";
}
}
此处装饰者获得价格及描述都是通过普通商品获得,之后通过装饰者本身进行一定的处理完成一层包装(通常用来动态的添加类的职责功能)。
满减商品类
public class DecreaseGoods implements IGoods {
private IGoods goods;
//构造器:获得被装饰对象
public DecreaseGoods(IGoods goods) {
this.goods = goods;
}
@Override
//获取商品描述并添加满减商品标志
public String getDescription() {
return goods.getDescription()+"---满减商品";
}
@Override
//获取商品价格,根据活动要求对价格进行相应满减处理
public double getPrice() {
double price = goods.getPrice();
if(price<30){
price -= 5;
}else if(price<50){
price -= 10;
}else{
price -= 30;
}
return price;
}
}
场景模拟:
public class DecoratorTest {
//获取随机数的工具
static Random random = new Random();
public static void main(String[] args) {
//初始化货物仓库
List<IGoods> wareHouse = initWareHouse();
//获取随机测试对象
for(IGoods goods:wareHouse){
int type = random.nextInt(3);
if(type==1){//随机数1进行满减装饰
goods = new DecreaseGoods(goods);
}else if(type==2){//随机数2进行折扣操作
goods = new DiscountGoods(goods);
}else{//随机数3包装两层,两个活动同时进行
goods = new DiscountGoods(new DecreaseGoods(goods));
}
//打印基本信息
System.out.println("--------------------------------");
System.out.println(goods.getDescription()
+"---price:"+(int)goods.getPrice());
}
}
//获取随机价格
static int getRandPrice(){
return random.nextInt(100)+10;
}
//获取随机商品名
static char getDescription(){
return (char)(random.nextInt(26)+65);
}
//初始化仓库
static List<IGoods> initWareHouse(){
List<IGoods> wareHouse = new ArrayList<>();
for(int i=1;i<100;i++){
wareHouse.add(new NomalGoods(getDescription()+"", (double)getRandPrice()));
}
return wareHouse;
}
}
结果打印:
--------------------------------
G---折扣商品---price:32
--------------------------------
L---满减商品---price:20
--------------------------------
M---满减商品---折扣商品---price:30
--------------------------------
N---满减商品---折扣商品---price:23
--------------------------------
G---折扣商品---price:68
--------------------------------
F---满减商品---折扣商品---price:24
--------------------------------
Y---折扣商品---price:27
总结:
这个例子存在着许多瑕疵,代码中充斥着许多的 if…else…,比如在每种活动商品类中处理价格时仅在价格的处理方式上有所不同,因此可以通过创建一个价格方案工厂来生成不同的处理方案,另外在场景模拟中,如果多出其他的打折方式需要添加更多的 if…else,因此可以创建一个商品工厂通过传入不同参数,创建出不同的折扣商品。