设计模式初探之装饰模式

来源:互联网 发布:国内有限元软件 编辑:程序博客网 时间:2024/05/16 07:05

之前已经带来两种模式的探究分别为如下,有兴趣的小伙伴可以去看看。

简单工厂模式:http://blog.csdn.net/zsw1017/article/details/78232073

策略模式http://blog.csdn.net/zsw1017/article/details/78310151

一、定义

       今天将带来另一种模式的探究,这种模式就是装饰模式,首先我们先看看装饰模式的定义:

        修饰模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。(维基百科)

       1、这个定义中有几个关键点,动态的,这个点是类继承所不具备的,类的继承在我们实现继承的时候就已经确定了增加的功能。而装饰模式可以在客户代码过程决定新增哪些行为,甚至是新增行为的顺序。

       2、添加新的行为,这个点跟生成子类是一个共同点,子类就是在父类的基础上进行扩展,说明这种装饰模式在某种程度上是可以替代继承,实现对类功能的扩展。

       3、灵活,体现在第一点的动态增加,还可以决定增加的顺序。

看完这个定义是不是有点懵,不要紧,先抛开定义,接着往下看。

二、UML类图


装饰模式的类图可以看到,待装饰类、装饰类是有共同的接口Component,这个Component在我看来

确定了待装饰类可扩展的方法具体的装饰类ConcreteDecoratorA、ConcreteDecoratorB,有一个父类,这

个父类中持有Component引用,这个就是用于存放待装饰类对象。有了待装饰类的对象,就可调用待装饰

类的方法(原有功能),并扩展方法。

具体装饰类ConcreteDecoratorA用于具体扩展行为的实现。
装饰模式就是这样,通过新增装饰类,在装饰类内持有待装饰类对象引用,即包裹待装饰类对象,扩

展待装饰对象。看到这里,你是对装饰模式有更清晰的理解,还是更懵。如果有了进一步的了解,别急着离

开,看个例子巩固一下。如果你更迷糊了,那你肯定更不能此刻离开,看一个例子,再回来看看前面的定

义,还有uml类图,你很可能就能理解了。

三、例子

我们用这个场景,我们要做一个蛋炒饭,分别得往锅里放,饭,鸡蛋,盐,我们就把放食材这些动作
当做行为,在原来锅里什么都没有的情况下,增加这些食材。
首先得有一个Component,这个接口定义了可扩展的方法。
public interface Component {/** * 添加食材 */public void addIngredient();}
接下来是待装饰类,这是一个锅,里面什么都没有,哈哈。
public class Friedrice implements Component {@Overridepublic void addIngredient() {// TODO Auto-generated method stubSystem.out.println("做一道传统美食,蛋炒饭");}}
装饰父类,这里持有了待装饰类的引用,用于调用原有功能。
public class Decorator implements Component{private Component waitForDecorator;//待装饰对象public Decorator(Component waitForDecorator) {super();this.waitForDecorator = waitForDecorator;}@Overridepublic void addIngredient() {// TODO Auto-generated method stubwaitForDecorator.addIngredient(); //调用原来待装饰类已有功能}}
接下来就是具体装饰类,加入大米饭。具体的装饰行为,即新增扩展功能
public class AddRice extends Decorator {public AddRice(Component waitForDecorator) {super(waitForDecorator);// TODO Auto-generated constructor stub}@Overridepublic void addIngredient() {// TODO Auto-generated method stubsuper.addIngredient(); //这里是关键,调用待装饰对象的方法System.out.println("将大米饭放入锅中"); //扩展,有没有?}}
具体装饰类,加入鸡蛋。
public class AddEgg extends Decorator{public AddEgg(Component waitForDecorator) {super(waitForDecorator);// TODO Auto-generated constructor stub}@Overridepublic void addIngredient() {// TODO Auto-generated method stubsuper.addIngredient();System.out.println("往锅中加入鸡蛋");}}
具体装饰类,加入盐。
public class AddSalt extends Decorator{public AddSalt(Component waitForDecorator) {super(waitForDecorator);// TODO Auto-generated constructor stub}@Overridepublic void addIngredient() {// TODO Auto-generated method stubsuper.addIngredient();System.out.println("往锅中加入盐");}}
接下来就是客户端调用了。
public class TestClass {public static void main(String arg[]){Friedrice food = new Friedrice();AddRice addRice = new AddRice(food);//加入大米饭AddSalt addSalt = new AddSalt(addRice);//加入盐AddEgg addEgg = new AddEgg(addSalt);//加入鸡蛋addEgg.addIngredient();}}

运行结果:

什么???你说你非要先加盐,再加饭??随你吧,反正这难不倒装饰模式,将客户端代码修改为如下。
public class TestClass {public static void main(String arg[]){Friedrice food = new Friedrice();AddSalt addSalt = new AddSalt(food);AddEgg addEgg = new AddEgg(addSalt);AddRice addRice = new AddRice(addEgg);addRice.addIngredient();}}


这例子就是装饰模式啦,Friedrice:待装饰类、Component:装饰类待装饰类的共同接口、Decorator:
装饰类父类、AddSalt,AddRice,AddEgg:具体的装饰类。Friedrice的addIngredient扩展为加米饭,加鸡
蛋,加盐。这些动作的顺序也能随时灵活更换。
到这里,你是不是对装饰模式有个大概的了解了??那就多看几遍,哈哈。顺便说下,java提供的io操作
其实也是用到了装饰模式。

四、总结

1、装饰模式是一种用于扩展类功能的设计模式,是一种包裹模式,将待装饰类包裹在装饰类中,在装饰类中
扩展待装饰类。
2、装饰模式相对生成子类的扩展类功能来说,具有动态,灵活等特点。
3、具体的装饰对象只需完成自己的行为,而不需要知道其他具体装饰对象。他们不需要知道对方的存在。只
需专注于自己要扩展的行为。




原创粉丝点击