目录
一、基本概念
二、角色设计
三、代码实现
案例一
案例二
四、总结
一、基本概念
装饰器模式是指不必在改变原有的类和不使用继承的情况下,动态扩展一个对象的功能。
二、角色设计
角色 | 描述 |
---|---|
抽象构件 | 是一个接口或者抽象类,定义我们最核心的对象 |
基础构件 | 抽象构件的实现,可以单独用,也可以将其进行装饰 |
装饰角色 | 一般是一个抽象类,继承自或实现抽象构件,在它的属性中有个变量指向抽象构建,这是关键 |
具体装饰角色 | Type-C充电和Wireless充电是两个具体的装饰类,可以把基础构件进行装饰,延伸出新的功能 |
三、代码实现
案例一
假设一个场景,以前手机充电只有usb充电,但是目前手机多出了2种新的充电方式,Typc-C和无线充电,这就需要我们动态去扩展功能,让我们看看装饰器如何实现的。
1、首先定义一个基本的充电接口,采用usb充电
public interface Charge {
public void usb();
}
2、实现一个普通手机去使用usb接口充电
public class PhoneCharge implements Charge{
@Override
public void usb() {
System.out.println("采用usb接口充电...");
}
}
3、 抽象的充电装饰器
public abstract class AbstractPhoneDecorator implements Charge{
protected final Charge charge;
public AbstractPhoneDecorator(Charge charge){
this.charge = charge;
}
}
4、Type-C充电具体装饰
public class TypeCDecorator extends AbstractPhoneDecorator{
public TypeCDecorator(Charge charge) {
super(charge);
}
@Override
public void usb() {
super.charge.usb();
System.out.println("采用type-c接口充电...");
}
}
5、无线充电的具体装饰
public class WirelessDecorator extends AbstractPhoneDecorator{
public WirelessDecorator(Charge charge) {
super(charge);
}
@Override
public void usb() {
super.charge.usb();
System.out.println("采用无线充电...");
}
}
6、测试类
public static void main(String[] args) {
Charge charge = new PhoneCharge();
TypeCDecorator typeCDecorator = new TypeCDecorator(charge);
WirelessDecorator wirelessDecorator = new WirelessDecorator(typeCDecorator);
wirelessDecorator.usb();
}
7、运行结果
案例二
现在假设有一个新的场景,在我们平时网上购买一个商品可以不光使用红包抵扣,同时也有满减优惠,案例二假设一个用户在网上买了10个单价为15元的牙杯,他现在有一个20元的红包和50元的抵扣券,下面通过代码来进行简单的模拟实现。
1、创建订单实体类
import java.math.BigDecimal;
/**
* 订单类
* @author HTT
*/
public class Order {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getGoodsInfo() {
return goodsInfo;
}
public void setGoodsInfo(String goodsInfo) {
this.goodsInfo = goodsInfo;
}
public BigDecimal getGoodsPrice() {
return goodsPrice;
}
public void setGoodsPrice(BigDecimal goodsPrice) {
this.goodsPrice = goodsPrice;
}
public BigDecimal getGoodsCount() {
return goodsCount;
}
public void setGoodsCount(BigDecimal goodsCount) {
this.goodsCount = goodsCount;
}
public Coupon getFullReduction() {
return fullReduction;
}
public void setFullReduction(Coupon couponInfo) {
this.fullReduction = couponInfo;
}
public Coupon getRedPacketInfo() {
return redPacketInfo;
}
public void setRedPacketInfo(Coupon redPacketInfo) {
this.redPacketInfo = redPacketInfo;
}
public BigDecimal getGoodsAmount() {
return goodsAmount;
}
public void setGoodsAmount(BigDecimal goodsAmount) {
this.goodsAmount = goodsAmount;
}
/**
* 订单id
*/
private String id;
/**
* 商品信息
*/
private String goodsInfo;
/**
* 商品价格
*/
private BigDecimal goodsPrice;
/**
* 商品信息
*/
private BigDecimal goodsCount;
/**
* 商品总价
*/
private BigDecimal goodsAmount;
/**
* 满减信息
*/
private Coupon fullReduction;
/**
* 红包信息
*/
private Coupon redPacketInfo;
}
2、创建优惠券实体类
import java.math.BigDecimal;
/**
* 优惠信息
* @author HTT
*/
public class Coupon {
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public BigDecimal getCouponPrice() {
return couponPrice;
}
public void setCouponPrice(BigDecimal couponPrice) {
this.couponPrice = couponPrice;
}
public String getCouponType() {
return couponType;
}
public void setCouponType(String couponType) {
this.couponType = couponType;
}
private int id;
/**
* 优惠金额
*/
private BigDecimal couponPrice;
/**
* 优惠券类型
*/
private String couponType;
}
3、创建一个抽象构建,是所有订单的基本需求,用于计算订单的总额
/**
* 抽象构建 用于计算订单总金额
* @author HTT
*/
public interface OrderDecorator {
public BigDecimal calculateOrderPrice(Order order);
}
4、 抽象构建的基础实现类
/**
* 基础构建实现类 计算订单金额
* @author HTT
*/
public class BaseOrder implements OrderDecorator{
@Override
public BigDecimal calculateOrderPrice(Order order) {
return order.getGoodsPrice().multiply(order.getGoodsCount());
}
}
5、订单的抽象装饰器
/**
* 抽象的订单装饰器
* @author HTT
*/
public abstract class BaseOrderDecorator implements OrderDecorator{
private OrderDecorator orderDecorator;
public BaseOrderDecorator(OrderDecorator orderDecorator){
this.orderDecorator = orderDecorator;
}
@Override
public BigDecimal calculateOrderPrice(Order order) {
return orderDecorator.calculateOrderPrice(order);
}
}
6、红包装饰器
/**
* 红包装饰器
* @author HTT
*/
public class RedPacketDecorator extends BaseOrderDecorator{
public RedPacketDecorator(OrderDecorator orderDecorator) {
super(orderDecorator);
}
@Override
public BigDecimal calculateOrderPrice(Order order) {
order.setGoodsAmount(super.calculateOrderPrice(order));
return calculateRedPacketPrice(order);
}
private BigDecimal calculateRedPacketPrice(Order order){
return order.getGoodsAmount().subtract(order.getRedPacketInfo().getCouponPrice());
}
}
7、满减装饰器
/**
* 满减装饰器
* @author HTT
*/
public class FullReductionDecorator extends BaseOrderDecorator{
public FullReductionDecorator(OrderDecorator orderDecorator) {
super(orderDecorator);
}
@Override
public BigDecimal calculateOrderPrice(Order order) {
order.setGoodsAmount(super.calculateOrderPrice(order));
return calculateRedPacketPrice(order);
}
private BigDecimal calculateRedPacketPrice(Order order){
return order.getGoodsAmount().subtract(order.getFullReduction().getCouponPrice());
}
}
8、测试
public static void main(String[] args) {
//初始化红包信息
Coupon redPacket = new Coupon();
redPacket.setId(1);
redPacket.setCouponType("红包");
redPacket.setCouponPrice(new BigDecimal("20"));
//初始化满减信息
Coupon fullReduction = new Coupon();
fullReduction.setId(2);
fullReduction.setCouponType("满减");
fullReduction.setCouponPrice(new BigDecimal("50"));
//初始化订单信息
Order order = new Order();
order.setId(UUID.randomUUID().toString());
order.setGoodsInfo("牙杯");
order.setGoodsPrice(new BigDecimal("15"));
order.setGoodsCount(new BigDecimal("10"));
order.setRedPacketInfo(redPacket);
order.setFullReduction(fullReduction);
OrderDecorator orderDecorator = new BaseOrder();
BaseOrderDecorator redPacketDecorator = new RedPacketDecorator(orderDecorator);
BaseOrderDecorator fullReductionDecorator = new FullReductionDecorator(redPacketDecorator);
System.out.println(fullReductionDecorator.calculateOrderPrice(order));
}
9、运行结果
四、总结
优点:装饰类和被装饰类可以独立发展,降低了耦合,可以动态去扩展一个实现类的功能
缺点:装饰器模式会增加许多的子类,会使代码繁多增加程序复杂性