装饰者模式—Head First 设计模式

在读代码时,你是否注意到有一种这样格式的代码:
Object o = new Object( new Object1( …));

       需要做出解释的是:这行代码中的Object并不是实际意义上的Java Object 类型的对象,而只是在这里的一种替代性的写法。 直观上来说就是Object对象中保持有一个Object1对象的成员对象,并且在Object对象的构造方法中传入一个Object1对象做参数初始化Object对象所拥有的Object1类型的成员变量。 这样,我们在Object对象中就可以在它的方法中操作我们刚刚初始化过的Object1对象的各个属性了,这样有什么作用呢?看下面这个例子:
Object o = new Object( new Object1( new Object2( new Object3(…))));
       当然能实现这种层层包装的关键在于,其中的Object类型,Object1类型,Object2类型…题目的动态类型应该是一样的。不妨让他们继承自同样父类:
在这里插入图片描述

       这里给出一个具体的例子,而且这个例子会贯穿整篇文章,调料作为父类,摩卡,牛奶和豆浆作为具体的调料继承自调料的父类。那这个模式就可以大展身手了:设想你现在身处一个咖啡店,你想要点这样一杯咖啡,它的主体是DarkRoast,然后你还想在自己的咖啡中加一份奶,再加两份摩卡…情况就有点像上面层层嵌套的模式了。在调料类中实现一个方法cost(),因为每一份调料的价格各不相同,并且只有具体的子类知道自己的什么价格,子类中就可以重写父类中的cost( )方法,返回自己的价格加上自己所拥有的成员变量调用cost()方法所得的价格。如果这样说比较模糊,那么我们根据具体实际来讲。一杯加了牛奶和两份摩卡的DarkRoast,它的价格应该怎么计算呢。首先我们创建一个摩卡对象,如下:
Mocha m = new Mocha ( );
       根据上文所述,如果想实现一种层次性递归计算价格的模式,Mocha对象中应该有一个调料类型的成员变量,这样这个Mocha对象应该这样创建:
Mocha m = new Mocha ( new Imegrent() ); //Imegrent是调料的意思
       在具体实际中我们需要的是两份摩卡和一份牛奶,所以,创建第一份Mocha对象的时候传入的应该是另一份摩卡,也就是这样的:
Mocha m = new Mocha ( new Mocha () );
       接下来:
Mocha m = new Mocha ( new Mocha ( new Milk(…)) );
       怎么结束这个嵌套计算的过程呢?或者说怎么将我们咖啡的主体DarkRoast的价格加进去呢,事到如今,看上去只能在最内层再创建一个DarkRoast对象作为参数传递进去了。前面说过,每个具体的调料中的成员变量应该是他们父类类型的,这样根据面向对象语言的多态性,会在运行时完成动态的类型变换,那我们的DarkRoast明显不应该作为调料对象的子类,它是咖啡的主体呢!,那只能让我们的层次再向上增长一层啦!就是让DarkRoast和调料具有相同的动态类型(这里所描述的动态类型是OO里面多态性所导致的),这样,就让调料类和DarkRoast类继承同一个父类,不妨将这个父类叫做饮料,得到我们的整个设计模式的类图如下:

在这里插入图片描述

这样我们今天计算一杯加了很多调料的咖啡的问题就迎刃而解了。
我们的装饰者模式在你的脑海中应该是一幅这样的情景(可以说是很生动形象了!):

在这里插入图片描述
装饰者模式的定义是:
       动态的将责任加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

       好了,什上面说到了装饰者模式是一种具有弹性的设计模式,假设我们不采用装饰着模式来尝试解决这个问题,我们的常规方法是,先建立一个饮料的父类,提供了计算价格的cost()方法,不同类型的咖啡主体继承该父类,并改写属于自己的cost()方法完成价格的计算,当有顾客需要一杯DarkRoast加摩卡的时候,我们就以DarkRoast作为父类建立一个DarkRoastWithMocha的子类…这样,有多少种顾客需求,就应该建立对少种对应的子类,(没案发,谁让顾客就是上帝了),这样,会产生一种子类的爆炸式数量增长的情况:
在这里插入图片描述
这样的设计怕是每个人都不愿意遇到的。装饰者模式通过一种更为巧妙的方法就解决了类爆炸的现象,不得不说是一种我们需要掌握的好的设计模式,实际上在JAVA语言的内部有很多采用了装饰者模式设计模式而设计出来的库函数,仔细查看库函数的具体实现,尤其在JAVA I/O中这种现象更加明显。

今天,我们学到的一个OO设计原则是:
对拓展开放,对修改关闭!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值