六一儿童节到了,今天我来为大家讲解一下DecoratorPattern!我觉得用这个例子来讲解这个模式再合适不过了!
我们先来看看装饰模式的概念:动态地给一个对象添加一些额外的职责。就增加功能而言,Decorator模式比生成子类更加灵活。
我们来进入场景:
明天就是儿童节了,你准备给你邻居的孩子准备了一个玩具汽车!多么激动人心的礼物啊!买这个汽车,我们需要花费一定的费用,下图是汽车的对象:
其中descreption是对该类的一个描述,这里是"car",cost是对该类的一个花费的金额,为250元。
但是,光送一个车总会显得不够高大上,所以,我们需要给他一个包装盒子,盒子的对象如下:
盒子的描述是"box",价值是5元(软妹币符号忘记画了,无伤大雅)。
现在,我们需要将汽车装入盒子中,那么怎么装入呢??
也许我们会想到:1.现有汽车类,2.让盒子类继承汽车类,这样,我们可以在盒子类中重写description和cost了,如下图:
此时的description和cost都是 盒子+汽车 后形成的。此时的description是"car with box ",cost是255元。
当然,你送礼物给邻居小孩,光一个盒子抱住汽车总感觉单调了一些,因此,你想增加一点东西:在盒子外面系上一条彩带打成蝴蝶结的样子!
那么,彩带的对象如下图:
此时,desription="car with box with ribbon"; cost= 255.5 ;
这样我们的礼物就包装好了!!
但是回到程序中,如果有一个程序是让你制作礼物,提供给你一个car类和许许多多其他的装饰类,如ribbon,box,flower....等等,,不同的人需要不同的包装成分,加上如果装饰类过多,这会使得我们的最终礼物要不停继承,不停继承。并且最终的礼物只能静态地生成,无法动态地“包装”。那么我们如何做到动态地包装呢??
下面,我们用到了装饰模式!
我们以这个六一儿童节礼物为例画个类图:
最上面是一个Gift礼物的抽象类,他里面有description()和cost()两个方法。MainGift类是我们要送的主要的礼物,比如这里的汽车,还有decorator类是用来包装的装饰类,它们都继承自Gift,这样可以让装饰品在装饰我们汽车的时候,它仍然是一个Gift。
下面我们看看代码部分:
我们先定义Gift类:
public abstract class Gift{
String description="null";
public Strinig Description(){
return description;//返回对象的描述
}
public abstract double cost();//抽象方法,子类中实现
}
下面是装饰类:
public abstract class Decorator extends Gift{//定义抽象类--装饰类
public abstract String Description();//此时继承了Gift,但是又把该方法变成抽象的,为了在定义包装的时候,重写描述!!不懂可以继续看下面
}
下面,我们的第一个礼物
public class Car extends Gift{
public Car(){
description="a car";//注意,这里修改了description属性!!
}
public double cost(){
return 250;//车的价格
}
}
这个MainGift这里就是Car,它继承Gift类,很简单。下面我们来看看装饰类!要注意思考!
首先是box对象
public class Box extends Decorator{
Gift gift;//用来实例化MainGift的变量!
public Box(Gift gift){
this.gift = gift;//可以在构造的时候就包装一个Gift!
}
public String Description(){
return gift.Description()+" with a box";
}
public double cost(){
return 5+gift.cost();//返回盒子的价格加上它所包装的MainGift的价格
}
}
ribbon彩带是一样的,代码如下:
public class Ribbon extends Decorator{
Gift gift;//用来实例化MainGift的变量!
public Box(Gift gift){
this.gift = gift;//可以在构造的时候就包装一个Gift!
}
public String Description(){
return gift.Description()+" with a ribbon";
}
public double cost(){
return 0.5+gift.cost();//返回彩带的价格+它所包装的Gift的价格(这里后面也会讲到,包装的是car+box)
}
}
下面我们在看看如何使用这些类:使用它们的代码如下:
public static void main(String args[]){
Gift gift = new Car();//这里的类型上转我不在多叙述,不懂得可以先看看这方面的知识再回头看我们这个。(我还是多叙述一下:可以将抽象类的具体实现类的对象赋值给抽象类对象)
System.out.println(gift.Description()+" 价格:"+gift.cost());
gift = new Box(gift);//将gift自己(Car)包装给box
System.out.println(gift.Description()+" 价格:"+gift.cost());
gift = new Ribbon(gift);//将car+box 为一个整体,包装给ribbon
System.out.println(gift.Description()+" 价格:"+gift.cost());
}
上面就是我们的装饰模式。它可以很灵活的动态添加新的功能。通过在装饰类里面添加一个组件(gift),每次包装只管自己的任务和它所包装的一个整体,而不去关心它所包装的整体里面又具体有什么。
以上就是装饰模式了,不懂得欢迎大家留言提问。祝大家六一儿童节快乐!!!!