装饰器模式-简单实现和(InputStream、ServletRequest)实现分析

设计模式-总览icon-default.png?t=LBL2https://mp.csdn.net/mp_blog/creation/editor/122202507目录

一、装饰器模式实现

二、装饰器模式使用场景分析

1、Jdk的InputStream实现分析

2、ServletRequest


     装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。《HeadFirst设计模式》上的装饰器模式的例子,我觉得还是比较形象的。有很多的饮料种类可以售卖,每种饮料又可以随客户任意加入不同总量和数量的点缀物(比如在茶里加柠檬,糖等),最后肯定是要统计用户点了哪些东西总共多少钱。

一、装饰器模式实现

github地址为:https://github.com/kevin-lihongmin/designpattern/tree/master/src/main/java/com/kevin/designpattern/headfirst/decorator

1)、首先定义饮料接口(价钱和描述):

public abstract class Beverage {

    String description = "我还不知道什么饮料类型,呵呵!";

    public String getDescription() {

        return description;
    }

    /**
     *  饮料当前的总价钱
     *
     * @return 装饰后钱的总和
     */
    public abstract double cost();
}

2)、各种饮料的实现(老外举的饮料例子不是很知道,管他呢)

/**
 *  重炒
 * @author lihongmin
 * @date 2018/9/2 3:18
 */
public class DarkRoast extends Beverage {

    private static final double COST = 3.6;

    public DarkRoast() {
        description = "我的 DarkRoast 哦!";
    }

    @Override
    public double cost() {
        return COST;
    }
}
/**
 *  Espresso饮料
 * @author lihongmin
 * @date 2018/9/2 2:39
 */
public class Espresso extends Beverage {

    private static final double COST = 1.99;

    public Espresso() {
        description = "我是Espresso Espresso饮料哦!";
    }

    @Override
    public double cost() {

        return COST;
    }
}
/**
 *  HouseBlend饮料
 * @author lihongmin
 * @date 2018/9/2 2:42
 */
public class HouseBlend extends Beverage {

    private static final double COST = 0.89;

    public HouseBlend() {
        description = "我的 HouseBlend 哦!";
    }

    @Override
    public double cost() {
        return COST;
    }
}

3)、饮料可以添加的点缀物的抽象(必须实现饮料接口)

/**
 *   调料顶层抽象类,装饰者的类型必须与顶层一致,必须继承(可能是实现){@link Beverage}
 *
 * @author lihongmin
 * @date 2018/9/2 2:34
 */
public abstract class CondimentDecorator extends Beverage{
    /**
     *  覆盖父类的描述方法,并且抽象后让子类实现
     */
    @Override
    public abstract String getDescription();
}

4)、点缀物(调料)的实现

/**
 *   摩卡
 * @author lihongmin
 * @date 2018/9/2 2:48
 */
public class Mocha extends CondimentDecorator {

    private static final double COST = 13.5;
    /**
     *  被装饰者
     */
    Beverage beverage;

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        // 委托的形式得到描述
        final String description = beverage.getDescription();
        String result = description + ", 得到委托描述后, 我又在里面加了些摩卡(装饰)!";
        return result;
    }

    @Override
    public double cost() {
        System.out.println("我现在的价钱是委托之前的,加上Mocha的钱了,切记!");
        return beverage.cost() + COST;
    }
}
/**
 *   豆浆
 * @author lihongmin
 * @date 2018/9/2 3:11
 */
public class Soy extends CondimentDecorator {

    private static final double COST = 3.4;

    Beverage beverage;

    public Soy(Beverage beverage) {

        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        // 委托的形式得到描述
        final String description = beverage.getDescription();
        String result = description + ", 得到委托描述后, 我又在里面加了些豆浆(装饰)!";
        return result;
    }

    @Override
    public double cost() {
        System.out.println("我加上了Soy的钱!");
        return beverage.cost() + COST;
    }
}
public class Whip extends CondimentDecorator {

    private static final double COST = 13.7;

    Beverage beverage;

    public Whip(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        // 委托的形式得到描述
        final String description = beverage.getDescription();
        String result = description + ", 得到委托描述后, 我又在里面加了些奶泡(装饰)!";
        return result;
    }

    @Override
    public double cost() {
        System.out.println("在装饰前时候,我加上了Whip(奶泡)的钱!");
        return beverage.cost() + COST;
    }
}

5)、测试

/**
 *   测试装饰者模式
 *
 * 我单独点了一杯Espresso,什么都不加先尝尝!
 * 我是Espresso Espresso饮料哦! , 花了我1.99 钱
 * ---------------------------------------------------------------------------------------------------
 * 我在点一杯DarkRoast, 但是需要double Mocha,还要加一份Whip,这样比较美味吧!
 * 在装饰前时候,我加上了Whip(奶泡)的钱!
 * 我现在的价钱是委托之前的,加上Mocha的钱了,切记!
 * 我现在的价钱是委托之前的,加上Mocha的钱了,切记!
 * 我的 DarkRoast 哦!, 得到委托描述后, 我又在里面加了些摩卡(装饰)!, 得到委托描述后, 我又在里面加了些摩卡(装饰)!, 得到委托描述后, 我又在里面加了些奶泡(装饰)! , 花了我44.3 钱
 * ---------------------------------------------------------------------------------------------------
 * 我再点一个HouseBlend咖啡,里面多加几样调味品吧,一样来一点,哈哈哈!
 * 我加上了Soy的钱!
 * 在装饰前时候,我加上了Whip(奶泡)的钱!
 * 我现在的价钱是委托之前的,加上Mocha的钱了,切记!
 * 我的 HouseBlend 哦!, 得到委托描述后, 我又在里面加了些摩卡(装饰)!, 得到委托描述后, 我又在里面加了些奶泡(装饰)!, 得到委托描述后, 我又在里面加了些豆浆(装饰)! , 花了我31.49 钱
 *
 * @author lihongmin
 * @date 2018/9/1 19:42
 */
public class TestDecorator {

    public static void main(String[] args) {
        System.out.println("我单独点了一杯Espresso,什么都不加先尝尝!");
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription() + " , 花了我" + beverage.cost() + " 钱");

        System.out.println("---------------------------------------------------------------------------------------------------");

        System.out.println("我在点一杯DarkRoast, 但是需要double Mocha,还要加一份Whip,这样比较美味吧!");
        Beverage beverage1 = new DarkRoast();
        beverage1 = new Mocha(beverage1);
        beverage1 = new Mocha(beverage1);
        beverage1 = new Whip(beverage1);
        System.out.println(beverage1.getDescription() + " , 花了我" + beverage1.cost() + " 钱");

        System.out.println("---------------------------------------------------------------------------------------------------");

        System.out.println("我再点一个HouseBlend咖啡,里面多加几样调味品吧,一样来一点,哈哈哈!");
        Beverage beverage2 = new HouseBlend();
        beverage2 = new Mocha(beverage2);
        beverage2 = new Whip(beverage2);
        beverage2 = new Soy(beverage2);
        System.out.println(beverage2.getDescription() + " , 花了我" + beverage2.cost() + " 钱");
    }
}

    总结分析:装饰对象必须都实现同一个接口,每个装饰者就是接口下的一个实现,各个实现是平级的。创建一个装饰对象就增加一种特有的功能,并且在构造中传入之前的对象(因为实现了同一接口,想起了各种inputSteam)。最后就能拿到想要的最终结果。

二、装饰器模式使用场景分析

1、Jdk的InputStream实现分析

InputStram是一个抽象类,二级的实现类非常的多,看了一下好几十个。

比较常用的如下:

/**
 *  InputStream 装饰器模式
 * @author kevin
 * @date 2019/11/12 16:49
 * @since 1.0.0
 */
public class ImputDecoratorTest {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        InputStream inputStream = new FileInputStream(new File(""));
        // FileInputStream特有的功能
        FileInputStream fileInputStream = (FileInputStream) inputStream;
        fileInputStream.getChannel();
        fileInputStream.getFD();
        // ZipInputStream特有的功能
        inputStream = new ZipInputStream(inputStream);
        ZipInputStream zipInputStream = (ZipInputStream) inputStream;
        zipInputStream.getNextEntry();
        // ObjectInputStream用于反序列化的能力
        inputStream = new ObjectInputStream(zipInputStream);
        ObjectInputStream objectInputStream = (ObjectInputStream) inputStream;
        objectInputStream.readObject();
    }
}

就是同一个对象,传入不同的子类(都直接或者间接的实现了InputStream)构造器中就拥有的不同的功能,和顶层接口的公共方法。

2、ServletRequest

/**
 *  {@link javax.servlet.ServletRequest} 的装饰器模式
 * @author kevin
 * @date 2019/11/12 17:18
 * @since 1.0.0
 */
public class ServletRequestTest {

    public static void main(String[] args) {

        ServletRequest servletRequest = new ServletRequestWrapper(null);

        // 用于上传文件的能力
        StandardMultipartHttpServletRequest multipartRequest = new 
            StandardMultipartHttpServletRequest(null);
        HttpHeaders httpHeaders = multipartRequest.getMultipartHeaders("myFile");
        MultipartFile multipartFile = multipartRequest.getFile("myFile");
        System.out.println("" + httpHeaders + multipartFile);

        ContentCachingRequestWrapper cacheWrapper = new ContentCachingRequestWrapper(null);
        cacheWrapper.getRequestedSessionId();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值