在我们的工作中,往往会这样的需求,就是动态地将责任附加到对象上,来达到拓展对象功能的目的。例如,对于做饼这件事来说,往往在做好一个饼之后,会有加糖,加盐,加鸡蛋这样类似的客户需求,不同的需求价格当然不同。我们通常的做法创建基类(Cake),然后让其他的子类继承它,试想下,如果如果有很多的类,岂不是会造成类爆炸,新出一款新的饼,就会构造一个类,计算不同的价格。而装饰者模式应用在这上面就非常的好。你想加糖,那我在外面包装一层,把额外的价格加上去。以后如果有几种配料的叠加,不用创造新的类,由原来的子类通过装饰者模式包装起来就行。
2. 如何实现装饰者模式how)
- 定义一个饼的基类,其他的饼的种类继承它。12345678910public abstract class Cake {public String message="CAKE";public float cost;public String getMessage(){return message;}//每个实现类自己实现public abstract float getCost();}
油饼,和糖饼分别实现饼
可以分别加糖或者加盐,因此先来个装饰器接口
123public abstract class CakeDecorator extends Cake {}分别实现通过装饰器加糖和加盐
12345678910111213141516171819202122/*** Created by maskwang on 2017/10/15 0015.* 饼加盐*/public class SaltDecorator extends CakeDecorator{Cake cake;public SaltDecorator(Cake cake) {this.cake = cake;}public String getMessage() {return cake.getMessage()+" with salt ";}public float getCost() {return cake.getCost()+0.3f;}}
|
|
- 测试一下通过装饰器既加糖又加盐123456789public class Test {public static void main(String[] args) {Cake cake = new OilCake();cake = new SaltDecorator(cake);cake=new SugerDecorator(cake);System.out.println(cake.getMessage());System.out.println(cake.getCost());}}
结果如下:
这里解释一下,最后的2.0如何出来,构造出OilCake,cost就是1.5,
cake = new SaltDecorator(cake),那么cost就是1.8。cake=new SugerDecorator(cake),那么就是2.0。
- 我们常见到的IO包下,就运用到装饰者模式,例如BufferedInputStream,DataInputStream等。也可以实现一个装饰器,把字母转化成小写。如下:12345678910111213141516171819202122232425262728293031package com.designpattern.decoratorpattern;import java.io.FilterInputStream;import java.io.IOException;import java.io.InputStream;/*** Created by maskwang on 2017/10/15 0015.*/public class UperCaseInputStream extends FilterInputStream {public UperCaseInputStream(InputStream in) {super(in);}public int read() throws IOException {int c=super.read();return (c==-1?c:Character.toUpperCase((char)c));}public int read(byte[] b, int off, int len) throws IOException {int result=super.read(b,off,len);for(int i=off;i<off+result;i++){b[i]=(byte)Character.toUpperCase((char)b[i]);}return result;}}
测试IO装饰类
3. 总结(conclution)
- 从上述我们可以看出来 ,装饰者模式用于已经存在的类添加额外的功能,但是它也有缺点,就是它要在设计中加入大量的小类,会造成额外的空间占用。其核心思想还是如下:
多用组合,少用继承。针对接口编程,不针对实现编程。对拓展开放,对修改关闭。
github地址:github.com/maskwang520