Java装饰者模式 (Decorator Pattern),入门,介绍。

 为什么要讲装饰者模式?
首先,我们要了解java面向对象的6个基本原则:

1,开放封闭原则。
2,里氏替换原则。
3,依赖导致原则。
4,合成/聚合原则。
5,知道最少原则。
6,接口隔离原则。
这里,如果你不了解这6个原则,最好抽个时间学一学这六个基本原则,理解完这六个基本原则,对你的设计模式的思想将提供很大的帮助,关于装饰者模式就是偏重于开放封闭原则的一种设计模式。它可以动态的增加新的需求。
什么是装饰者模式?
所谓的装饰者模式的大致介绍是:在不改变原有类和继承类的情况下,动态的增加修改类的功能,其实就是建立一个同类型的包装对象来动态的增改原有类的功能。话说什么是包装?商品包装知不知道,就是在对象上面加多一层。如果你平时觉得自己滥用继承,那么装饰者模式将是你的福音。
装饰者模式可以做什么?
装饰者模式的缺点?
缺点就是拥有更多的小类,增加代码的逻辑结构,如果程序员不是对装饰者理解的话,会造成一定程度的理解问题。这方面的问题可以搭配工厂模式和建造者模式来优化。
装饰者例子?
场景介绍: 真功夫,我们去过了吧,就以他那间店为例子,我们知道,那个菜单上有很多的菜单,腊味含汤套餐,腊味饮料套餐,排骨套餐,鸡腿套餐。假如我们首先声明一个Food抽象类,这个类有describe,和cost两个方法。然后每个套餐继承与food这个方法,这样每次我们新加一个菜单就得新加一个了。这里我用一个类图表示一下

Main 

我们可以看到,没一个套餐就有一个子类来实现,如果套餐不多,十几个二十几个还没有问题,每次我们继承一个就行了,但是,如果一百两百怎么办,假如,现在真功夫新增了一个排骨含汤套餐怎么办,或者消费者想来一份双倍饭的排骨套餐怎么办,难道又要重新继承一个类,这时候我们可以想,那个腊肉含汤,里面已经有个含汤了,是不是可以利用。

这时候我们就可以想到装饰者模式了,我们可以我们把这些食物的配菜都抽离出来,让他们成为一个包装对象,消费者想吃什么,想点什么,只要一层层往外面包装就可以了。举个例子,假如消费者想点一个鸡腿排骨加汤套餐。我们只需在白饭上面包装一个鸡腿,再包装一个排骨,再包装一个加汤就可以实现了,我们就可以使用现有的对象,来完成一个新的功能。这样也比较符合我们设计的原理。

dmMain   话说,手残党,写的图有点难以理解,用实际代码来描述比较清楚。
1,首先构建一个食物抽象类
Food

/**
 *
 * @author studyjun
 * 食物抽象类
 *
 */
public abstract class Food {
     
     
    /**
     * 描述
     * @return
     */
    public abstract String getDescription();
 
    /**
     * 费用
     * @return
     */
    public abstract float getCost();
     
     
}

2,构建配菜类
套餐基类

/**
 * 
 * @author studyjun 
 * 套餐
 *
 */
public class Taocan extends Food {
 
    public String getDescription() {
        return "";
    }
 
    public float getCost() {
        return 0;
    }
 
}

白饭

/**
 * 
 * @author studyjun
 *  白饭
 * 
 */
public class Baifan extends Food {
 
    private Food food;
 
    public Baifan(Food food) {
        this.food = food;
    }
 
    public String getDescription() {
         
        return food.getDescription() + "白饭";
    }
     
 
     
    public float getCost() {
        return food.getCost() + 3.0f;
    }
}

腊味

/**
 * 
 * @author studyjun
 *  腊味
 *
 */
public class Lawei extends Food{
 
    private Food food;
     
    public Lawei(Food food) {
        this.food = food;
    }
     
    public String getDescription() {
        return food.getDescription()+"腊味";
    }
     
    public float getCost() {
        return food.getCost()+5f;
    }
}

排骨

/**
 * 
 * @author studyjun
 *  排骨
 *
 */
public class Paigu extends Food{
 
    private Food food;
     
    public Paigu(Food food) {
        this.food = food;
    }
     
    public String getDescription() {
        return food.getDescription()+"排骨";
    }
     
    public float getCost() {
        return food.getCost()+5f;
    }
}

饮料

/**
 * 
 * @author studyjun
 *  饮料
 *
 */
public class Yinliao extends Food{
 
    private Food food;
     
    public Yinliao(Food food) {
        this.food = food;
    }
     
    public String getDescription() {
        return food.getDescription()+"饮料";
    }
     
    public float getCost() {
        return food.getCost()+5.0f;
    }
}

加汤

/**
 * 
 * @author studyjun
 *  加汤
 *
 */
public class Jiatang extends Food{
 
    private Food food;
     
    public Jiatang(Food food) {
        this.food = food;
    }
     
    public String getDescription() {
        return food.getDescription()+"加汤";
    }
     
    public float getCost() {
        return food.getCost()+8.0f;
    }
}

3,测试

public class OrderTest {
     
    public static void main(String[] args) {
         
        //腊味套餐
        Taocan fo = new Taocan();
        Food baifan= new Baifan(fo);
        Food lawei = new Lawei(baifan);
        System.out.println("套餐:"+lawei.getDescription());
        System.out.println("价格:"+lawei.getCost());
        System.out.println("+++++++++++++++++++++++++++++++");
         
        //腊味加汤套餐
        Taocan fo1 = new Taocan();
        Food baifan1= new Baifan(fo1);
        Food lawei1 = new Lawei(baifan1);
        Food jiatang1 = new Jiatang(lawei1);
        System.out.println("套餐:"+jiatang1.getDescription());
        System.out.println("价格:"+jiatang1.getCost());
        System.out.println("+++++++++++++++++++++++++++++++");
         
        //排骨饮料套餐
        Taocan fo2 = new Taocan();
        Food baifan2= new Baifan(fo2);
        Food paigu2 = new Paigu(baifan2);
        Food yinliao2= new Yinliao(paigu2);
        System.out.println("套餐:"+yinliao2.getDescription());
        System.out.println("价格:"+yinliao2.getCost());
        System.out.println("+++++++++++++++++++++++++++++++");
         
    }
     
}

运行结果:

runderestult

jdk中有使用装饰者模式的例子?

在我们熟悉的jdk中也有不少装饰者模式的应用,比如我们平时所用的输入输出流就是一个典型的装饰者模式,我们梳理下jdk有哪些输入输出流,我查了一下jdk 1.7的api,发现有很多不同的输入输出流,具体没数多少个,这里我们就可以看出装饰者模式下的一些小缺陷了,这么多的输入输出流我们平时用的时候就得查一下文档,不然根本记不住这么多,理解装饰者模式的话,我们就知道这些知识对input对象的包装,实现动态增加功能的一种方法,这里这列举了几个即便常用的输入流,输出流和输入流是对应存在的,这里就不列举了(其实其他的我也没用过)。

InputStream

============================
这里是小例子源码,不要太用力戳我

转载于:https://my.oschina.net/studyjun/blog/349407

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值