Java设计模式之装饰者模式
装饰者模式
本篇博客主要论述一下几个问题:
- 什么 是装饰者模式?
- 装饰者模式的优缺点?
- 怎样实现装饰者模式?
- 案例描述
什么是装饰者模式?
装饰者模式(Decorator Pattern):动态地给一个对象增加一些额外的职责,增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。
在装饰者模式中,为了让系统具有更好的灵活性和可扩展性,我们通常会定义一个抽象装饰类,而将具体的装饰类作为它的子类。
角色
Component(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
ConcreteComponent(具体构件):它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
Decorator(抽象装饰类):它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。
由于具体构件类和装饰类都实现了相同的抽象构件接口,因此装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任,换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。
装饰模式的核心在于抽象装饰类的设计。
特点:
1.装饰对象和包装对象有相同的接口,这样客户端对象就能以和真实对象相同的方式和装饰对象进行交互。
2.装饰对象包含一个真实对象的引用
3.装饰对象接受所有来自客户的请求,它把这些请求会发给真实的对象
4.装饰对象可以在转发这些请求以前或者以后增加一些附加功能。这样就能确保在运行时,
不必修改给定对象的结构,可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现给定类的功能扩展
适用性:
1.需要扩展一个类的功能,或给定一个类添加附加职责
2.需要动态地给一个类添加功能,这些功能还可以动态地撤销
3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。 4.当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
优缺点:
优点:1.装饰着模式与继承关系的目的就是扩展对象的功能,装饰着模式可以提供比继承更多的灵活性
2.通过使用不同的具体修饰类以及这些装饰类的排列组合,设计师可以提供比继承跟多的灵活性。
缺点:1.这种比继承更加灵活的特性,同时增加了更多的复杂性
2.装饰模式会导致很多的设计中出现许多小类,过多使用会使程序变得更加复杂
3.装饰模式是针对抽象组件,类型的编程。但是如果要针对具体组件进行编程时候就要重新考虑应用架构,以及装饰者是否合适。
案例演示:
-
制作蛋糕,由于用户需求的不同需要制作不同的巧克力蛋糕
-
并且再已经制作好的蛋糕基础之上也可以添加额外的装饰品
-
在已经制作好的蛋糕的基础上添加了装饰品之后,还可以继续添加装饰品
-
达到用户需求、
例如我们做一份抹茶蛋糕并且添加卡片的基础上再添加一个钻石,我们可以先创建一个接口,里面有make()方法,由于现在要做蛋糕,所有实现类cake实现接口的方法make(),到这里我们知道了这个cake实现类是做蛋糕的,但是我们由于需求的改变不知道该做什么蛋糕,所以这里这个cake是一个抽象类,到最后才是具体制作蛋糕的具体实现类,我们想做巧克力蛋糕,因此chocolatecake实现类只需继承cake这个制作蛋糕的抽象类就可以了。这样我们如果做巧克力蛋糕,直接调用制作巧克力蛋糕的方法就行了。
我们做好了巧克力蛋糕,但是我们还没有完成最初的需求,添加装饰品,这里同样的道理需求是多变的永远不知道客户每时每刻做什么样子的,这里所以首先完成一个装饰的抽象类,比如成一个装饰器Decorator,现在我们要添加钻戒和卡片,则实现添加钻戒和添加卡片的类,Decard和DecDiamond两个子类,在和这个类中需要利用多态的思想,利用各自的构造器,分别将制作蛋糕的抽象类作为数据类型,用于接收已经制作好的各种蛋糕,并且调用其制作蛋糕的方法,调用的同时,添加卡片或者钻戒,即新创建一个方法,在调用make方法的时候调用。
这里如果还不理解,请看下面清晰易懂的图示和代码演示:
代码示例:
- 类说明 :蛋糕类实现做蛋糕的接口------装饰着模式
*/
public abstract class Cake implements MakeCake{
@Override
public abstract void make() ;
}
- 类说明 :制作蛋糕的接口------装饰着模式
*/
public interface MakeCake {
void make();//做蛋糕
}
- 类说明 :巧克力蛋糕------装饰着模式
*/
public class ChocolateCake extends Cake{
@Override
public void make() {
System.out.println("制作巧克力蛋糕");
}
}
- 类说明 :抹茶蛋糕------装饰着模式
*/
public class MatChaCake extends Cake{
@Override
public void make() {
System.out.println("制作抹茶蛋糕类");
}
}
- 类说明 :向蛋糕中添加一个卡片------装饰着模式
*/
public class DecCard extends Decorator{
public DecCard(MakeCake mc) {
super(mc);
}
@Override
public void make() {
super.make();
add();
}
//加卡片的方法
public void add(){
System.out.println("向蛋糕中藏一个卡片!");
}
}
- 类说明 :向蛋糕中加一个钻戒------装饰着模式
*/
public class DecDiamond extends Decorator{
public DecDiamond(MakeCake mc) {
super(mc);
}
@Override
public void make() {
super.make();
add();
}
//添加钻戒的方法
public void add() {
System.out.println("向蛋糕中添加一个钻戒");
}
}
- 类说明 :装饰类------装饰着模式
*/
public class Decorator implements MakeCake{
private MakeCake mc;
public Decorator(MakeCake mc) {
this.mc=mc;
}
@Override
public void make() {
mc.make();
}
}
- 类说明 :测试类------装饰着模式
*/
public class Test {
public static void main(String[] args) {
//需求:制作巧克力蛋糕
ChocolateCake cc = new ChocolateCake();
//cc.make();
//在巧克力蛋糕上添加卡片
DecCard dc = new DecCard(cc);
//dc.make();
//在巧克力+卡片巧克力的基础上添加一个
DecDiamond dd = new DecDiamond(dc);
dd.make();
}
}
博主技术刊:[大数据领域]https://blog.****.net/Mirror_w/article/details/89190381
最新行业资讯:AI开放共享,“中国力量”全球化加速http://www.cnit5.com/a/yulezixun/2019/0318/14695.html