为什么要讲装饰者模式?
首先,我们要了解java面向对象的6个基本原则:
1,开放封闭原则。
2,里氏替换原则。
3,依赖导致原则。
4,合成/聚合原则。
5,知道最少原则。
6,接口隔离原则。
这里,如果你不了解这6个原则,最好抽个时间学一学这六个基本原则,理解完这六个基本原则,对你的设计模式的思想将提供很大的帮助,关于装饰者模式就是偏重于开放封闭原则的一种设计模式。它可以动态的增加新的需求。
什么是装饰者模式?
所谓的装饰者模式的大致介绍是:在不改变原有类和继承类的情况下,动态的增加修改类的功能,其实就是建立一个同类型的包装对象来动态的增改原有类的功能。话说什么是包装?商品包装知不知道,就是在对象上面加多一层。如果你平时觉得自己滥用继承,那么装饰者模式将是你的福音。
装饰者模式可以做什么?
装饰者模式的缺点?
缺点就是拥有更多的小类,增加代码的逻辑结构,如果程序员不是对装饰者理解的话,会造成一定程度的理解问题。这方面的问题可以搭配工厂模式和建造者模式来优化。
装饰者例子?
场景介绍: 真功夫,我们去过了吧,就以他那间店为例子,我们知道,那个菜单上有很多的菜单,腊味含汤套餐,腊味饮料套餐,排骨套餐,鸡腿套餐。假如我们首先声明一个Food抽象类,这个类有describe,和cost两个方法。然后每个套餐继承与food这个方法,这样每次我们新加一个菜单就得新加一个了。这里我用一个类图表示一下
我们可以看到,没一个套餐就有一个子类来实现,如果套餐不多,十几个二十几个还没有问题,每次我们继承一个就行了,但是,如果一百两百怎么办,假如,现在真功夫新增了一个排骨含汤套餐怎么办,或者消费者想来一份双倍饭的排骨套餐怎么办,难道又要重新继承一个类,这时候我们可以想,那个腊肉含汤,里面已经有个含汤了,是不是可以利用。
这时候我们就可以想到装饰者模式了,我们可以我们把这些食物的配菜都抽离出来,让他们成为一个包装对象,消费者想吃什么,想点什么,只要一层层往外面包装就可以了。举个例子,假如消费者想点一个鸡腿排骨加汤套餐。我们只需在白饭上面包装一个鸡腿,再包装一个排骨,再包装一个加汤就可以实现了,我们就可以使用现有的对象,来完成一个新的功能。这样也比较符合我们设计的原理。
话说,手残党,写的图有点难以理解,用实际代码来描述比较清楚。
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("+++++++++++++++++++++++++++++++");
}
}
运行结果:
jdk中有使用装饰者模式的例子?
在我们熟悉的jdk中也有不少装饰者模式的应用,比如我们平时所用的输入输出流就是一个典型的装饰者模式,我们梳理下jdk有哪些输入输出流,我查了一下jdk 1.7的api,发现有很多不同的输入输出流,具体没数多少个,这里我们就可以看出装饰者模式下的一些小缺陷了,这么多的输入输出流我们平时用的时候就得查一下文档,不然根本记不住这么多,理解装饰者模式的话,我们就知道这些知识对input对象的包装,实现动态增加功能的一种方法,这里这列举了几个即便常用的输入流,输出流和输入流是对应存在的,这里就不列举了(其实其他的我也没用过)。
============================这里是小例子源码,不要太用力戳我哦