设计模式:装饰模式
程序员文章站
2022-05-17 17:26:08
...
装饰模式是Java IO中使用到的一个主要的设计模式,又称为包装(Wrapper)模式。
装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,以对客户端透明的方式动态的给一个对象附加上更多的责任和功能,但在添加这些额外的职责时不会控制该类的执行逻辑。
装饰模式可以在不创造更多的子类的模式下,将对象的功能加以扩展。那么,装饰模式与类继承有何区别呢?!区别有以下两点:
●装饰模式是一种动态行为,是对已有类的组合;而类的继承是一种静态的行为,一个类定义成什么样的,该类的对象便具有什么样的功能,无法动态的改变;
●装饰模式扩展的是在不改变由于对象的情况下扩展对象功能,而不增加类的数量,不会导致类爆炸;而类继承扩展是类的功能,在继承的关系中,如果我们想增加一个对象的功能,我们只能通过继承关系,在子类中增加两个方法。
装饰模式符合OOP六个设计原则中的“开闭原则”,即对修改关闭,对扩展开放。
还有,装饰模式和之前学习过的动态代理模式很像,但是二则的意图是不同的:动态代理模式是由代理对象对外部提供对被代理对象的访问控制,如权限控制、事物控制和其他的一些前置或后置控制;而装饰模式是在不改变对象的逻辑行为的情况下一通明的方式给对象附加上更多的责任和功能。
下面我们来看一下装饰模式的类图:
装饰模式的构成:
●抽象构建角色(Component):给出一个抽象的接口,以规范准备接受附加责任的对象。相当于i/o流里面InputStream/OutputStream和Reader/Writer。
●具体的构建角色(ConcreteComponent):定义一个将要接受附加责任的类。相当于i/o里面的FileOutputStream和FileInputStream。
●装饰角色(Docorator):持有一个抽象构建(Component)角色的引用,并定义一个与抽象构件一致的接口。相当于i/o里面的FilerOutputStream和FilterInputStream。
●具体的装饰角色(ConcreteDecorator):负责给构建对象“贴上”附加的责任。相当于i/o流里面的BufferedOutputStream和BufferedInputStream以及DataOutputStream和DataInputSrtream。
再看DocoratorExample的执行结果:
装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,以对客户端透明的方式动态的给一个对象附加上更多的责任和功能,但在添加这些额外的职责时不会控制该类的执行逻辑。
装饰模式可以在不创造更多的子类的模式下,将对象的功能加以扩展。那么,装饰模式与类继承有何区别呢?!区别有以下两点:
●装饰模式是一种动态行为,是对已有类的组合;而类的继承是一种静态的行为,一个类定义成什么样的,该类的对象便具有什么样的功能,无法动态的改变;
●装饰模式扩展的是在不改变由于对象的情况下扩展对象功能,而不增加类的数量,不会导致类爆炸;而类继承扩展是类的功能,在继承的关系中,如果我们想增加一个对象的功能,我们只能通过继承关系,在子类中增加两个方法。
装饰模式符合OOP六个设计原则中的“开闭原则”,即对修改关闭,对扩展开放。
还有,装饰模式和之前学习过的动态代理模式很像,但是二则的意图是不同的:动态代理模式是由代理对象对外部提供对被代理对象的访问控制,如权限控制、事物控制和其他的一些前置或后置控制;而装饰模式是在不改变对象的逻辑行为的情况下一通明的方式给对象附加上更多的责任和功能。
下面我们来看一下装饰模式的类图:
装饰模式的构成:
●抽象构建角色(Component):给出一个抽象的接口,以规范准备接受附加责任的对象。相当于i/o流里面InputStream/OutputStream和Reader/Writer。
●具体的构建角色(ConcreteComponent):定义一个将要接受附加责任的类。相当于i/o里面的FileOutputStream和FileInputStream。
●装饰角色(Docorator):持有一个抽象构建(Component)角色的引用,并定义一个与抽象构件一致的接口。相当于i/o里面的FilerOutputStream和FilterInputStream。
●具体的装饰角色(ConcreteDecorator):负责给构建对象“贴上”附加的责任。相当于i/o流里面的BufferedOutputStream和BufferedInputStream以及DataOutputStream和DataInputSrtream。
package org.pattern.decorator; /** * 接口,具体的装饰类和被装饰则都要这几该接口 * @author JackyChen * */ public interface Component { /** * 化妆操作 */ void makeup(); }
package org.pattern.decorator; /** * 具体的原始功能类,要被其他类装饰 * @author JackyChen * */ public class ConcreteComponent implements Component { @Override public void makeup() { System.out.println("化妆!"); } }
package org.pattern.decorator; /** * 装饰角色(Docorator):持有一个抽象构建(Component)角色的引用, * 并定义一个与抽象构件一致的接口 * @author JackyChen * */ public class Decorator implements Component{ private Component component; public Decorator(Component component){ this.component = component; } @Override public void makeup() { this.component.makeup(); } }
package org.pattern.decorator; /** * 具体装饰角色,给被装饰则添加”换衣服“的功能 * @author JackyChen * */ public class DressUpDecorator extends Decorator{ public DressUpDecorator(Component component) { super(component); } @Override public void makeup() { super.makeup(); this.dressUp(); } private void dressUp(){ System.out.println("换衣服!"); } }
package org.pattern.decorator; /** * 具体装饰角色,给被装饰则添加”撒香水儿“的功能 * @author JackyChen * */ public class PerfumeDecorator extends Decorator{ public PerfumeDecorator(Component component) { super(component); } @Override public void makeup() { super.makeup(); this.perfume(); } private void perfume(){ System.out.println("撒香水儿!"); } }
package org.pattern.decorator; public class DocoratorExample { public static void main(String[] ags){ //1,本来ConcreteComponent对象只是想化化妆 //2,通过DressUpDecorator包装类给ConcreteComponent对象添加了“换装”功能 //3,又通过PerfumeDecorator包装类给ConcreteComponent对象添加了“撒香水儿”功能 Component component = new PerfumeDecorator( new DressUpDecorator(new ConcreteComponent())); component.makeup(); } }
再看DocoratorExample的执行结果:
化妆! 换衣服! 撒香水儿!
上一篇: Vue.js相对于Angular.js来说有哪些进步?
下一篇: 仿途牛旅游网广告动画特效教程