二哈谈设计模式之装饰模式

装饰模式



前言

  • 动态的为一个对象增加新的功能。

  • 装饰模式是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。


一、实现细节

  • Component抽象构件角色:
    真实对象和装饰对象有相同的接口。这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互。
  • ConcreteComponent 具体构件角色(真实对象):
    io流中的FileInputStream、FileOutputStream
  • Decorator装饰角色:
    持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样,就能在真实对象调用前后增加新的功能。
  • ConcreteDecorator具体装饰角色:
    负责给构件对象增加新的责任。

二、具体实现

以咖啡为例,可以在咖啡中加糖、加奶…但是无论加什么,它仍然是一杯咖啡,只是对咖啡进行了味觉上的装饰。

1.实现抽象构件

/**
 * 抽象构件
 */
public interface Component {

    void showCoffee();
    double showPrice();
}

2.实现具体构件

/**
 * 具体构件
 */
public class Coffee implements Component{

    private String name ;
    private Double price;

    public Coffee(String name, Double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Override
    public void showCoffee() {
        System.out.println("的"+this.getName()+"咖啡");
    }

    @Override
    public double showPrice() {
        return this.getPrice();
    }
}

3.实现装饰角色

/**
 * 装饰抽象角色
 */
public abstract class Decorator implements Component{

    private Component component;

    public void setComponent(Component component) {
        this.component = component;
    }

    @Override
    public void showCoffee() {
        component.showCoffee();
    }

    @Override
    public double showPrice() {
        return component.showPrice();
    }
}

4.具体装饰角色

/**
 * 具体装饰角色(加奶)
 */
public class Milk extends Decorator{
    @Override
    public void showCoffee() {
        System.out.print("加奶");
        super.showCoffee();
    }

    @Override
    public double showPrice() {
        return 15.0 + super.showPrice();
    }
}
/**
 * 具体装饰角色(加糖)
 */
public class Sugar extends Decorator{
    @Override
    public void showCoffee() {
        System.out.print("加糖");
        super.showCoffee();
    }

    @Override
    public double showPrice() {
        return 10.0 + super.showPrice();
    }
}

5.测试类

/**
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        Coffee coffee = new Coffee("拿铁",55.0);
        Decorator sugar = new Sugar();
        Decorator milk = new Milk();

        sugar.setComponent(coffee);
        milk.setComponent(sugar);
        milk.showCoffee();
        System.out.println(milk.showPrice());
    }

}

结果:
在这里插入图片描述

三、应用场景

  • IO中输入流和输出流的设计
  • Swing包中图形界面构件功能
  • Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper类,增强了request对象的功能。
  • Struts2中,request,response,session对象的处理

总结

装饰模式(Decorator)也叫包装器模式(Wrapper)

  • 装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。
  • 优点
    – 扩展对象功能,比继承灵活,不会导致类个数急剧增加
    – 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象
    – 具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类。
  • 缺点
    – 产生很多小对象。大量小对象占据内存,一定程度上影响性能。
    – 装饰模式易于出错,调试排查比较麻烦。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值