设计模式之装饰模式

来源:互联网 发布:淘宝大连博哲贸易 编辑:程序博客网 时间:2024/05/20 19:33


参考资料:《大话设计模式》


1.装饰模式

装饰模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

Component:抽象组件角色,定义一组抽象的接口,规定这个被装饰组件都有哪些功能。

ConcreteComponent:实现这个抽象组件的所有功能。

Decorator:装饰器抽象类,继承了Component,它持有一个Component对象实例的引用,定义一个与抽象组件一致的接口,从外类来扩展Compoent类的功能,但对于Component来说,是无需知道Decorator的存在的。

ConcreteDecorator:具体的装饰器实现者,负责实现装饰器角色定义的功能,起到给Component添加职责的功能。


/** * @author  * @date 2017.12.05 * @function  */public interface Component {public void operation();}
/** * @author  * @date * @function  */public class ConcreteComponent implements Component{@Overridepublic void operation() {// TODO Auto-generated method stubSystem.out.println("具体对象的操作");}}
/** * @author  * @date * @function  */public class Decorator implements Component{private Component compoent;public Decorator(Component compoent){this.compoent=compoent;}@Overridepublic void operation() {// TODO Auto-generated method stubcompoent.operation();}}
/** * @author  * @date * @function  */public class ConcreteDecoratorA extends Decorator{public ConcreteDecoratorA(Component compoent) {super(compoent);// TODO Auto-generated constructor stub}@Overridepublic void operation() {super.operation();operA();}public void operA(){System.out.println("这是对象A的额外方法,用来装饰待目标对象");}}
public class ConcreteDecoratorB extends Decorator{public ConcreteDecoratorB(Component compoent) {super(compoent);// TODO Auto-generated constructor stub}@Overridepublic void operation() {super.operation();operB();}public void operB(){System.out.println("这是对象B的额外方法,用来装饰待目标对象");}}
/** * @author  * @date * @function  */public class Client {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubComponent a1 = new ConcreteComponent();  //都必须向上转型为ComponentComponent a2 = new ConcreteDecoratorA(a1);Component a3 = new ConcreteDecoratorB(a2);a3.operation();System.out.println("另一种调用方法:");Component a4 = new ConcreteDecoratorB(new ConcreteDecoratorA(new ConcreteComponent()));a4.operation();}}

2. 例子

下面举一个简单的服装搭配的例子。

/** * @author  * @date * @function 相当于Component类 */public abstract class Human {protected String name; //子类不能访问父类的私有属性,所以这里不能用privatepublic String getName(){return name;}public abstract void show();}
/** * @author  * @date * @function 相当于ConcreteComponent类 */public class Coder extends Human{public Coder(){name = "程序员";}@Overridepublic void show() {// TODO Auto-generated method stubSystem.out.println("程序员出场:");}}
/** * @author  * @date * @function 相当于ConcreteComponent类 */public class Manager extends Human{public Manager(){name = "经理";}@Overridepublic void show() {// TODO Auto-generated method stubSystem.out.println("经理出场:");}}
/** * @author  * @date * @function 相当于Decorator类 */public abstract class Finery extends Human{protected Human human;public Finery(Human human){this.human=human;}public void show(){human.show();}public abstract void dress();}
/** * @author  * @date * @function 相当于ConcreteDecorator类 */public class Jeans extends Finery{/** * @param human */public Jeans(Human human) {super(human);// TODO Auto-generated constructor stub}@Overridepublic void dress() {// TODO Auto-generated method stubSystem.out.println("牛仔裤");}public void show(){human.show();dress();}}
/** * @author  * @date * @function 相当于ConcreteDecorator类 */public class Shirt extends Finery{public Shirt(Human human) {super(human);// TODO Auto-generated constructor stub}public void show(){human.show();dress();}@Overridepublic void dress() {// TODO Auto-generated method stubSystem.out.println("衬衫");}}
/** * @author  * @date * @function 相当于ConcreteDecorator类 */public class Suit extends Finery{/** * @param human */public Suit(Human human) {super(human);// TODO Auto-generated constructor stub}/* (non-Javadoc) * @see com.DecoratorPattern.Finery#dress() */@Overridepublic void dress() {// TODO Auto-generated method stubSystem.out.println("西装");}public void show(){human.show();dress();}}
/** * @author  * @date * @function 相当于ConcreteDecorator类 */public class Sweater extends Finery{public Sweater(Human human) {super(human);// TODO Auto-generated constructor stub}@Overridepublic void dress() {// TODO Auto-generated method stubSystem.out.println("毛衣");}public void show(){human.show();dress();}}
/** * @author  * @date * @function 客户端类 */public class Client {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubHuman guest1 = new Jeans(new Sweater(new Shirt(new Coder())));guest1.show();Human guest2 = new Suit(new Shirt(new Manager()));guest2.show();}}


3.装饰模式总结

装饰模式是为已有功能动态地添加更多功能的一种方式。当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为,它们在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。装饰模式的优点就是,把类中的装饰功能从类中搬移去除,这样可以简化原有的类。这样做更大的好处就是有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。

注意,装饰模式的装饰顺序很重要,比如加密数据和过滤词汇都可以是数据持久化前的装饰功能,但若先加密了数据再用过滤功能就会出问题。

4. Java I/O中的装饰器模式

在Java I/O类库中有很多不同的功能组合情况,这些不同的功能组合都是使用装饰器模式实现的,比如FilterInputStream。


如上图,FilterInputStream是装饰器类,它实现了InputStream类的所有接口,并且持有InoutStream的对象实例的引用。BufferedInputStream是具体的装饰器实现者,它给InputStream类附加了功能,这个装饰器类的作用就是使得InputStream读取的数据保存在内存中,而提高读取的性能。与这个装饰器类有类似功能的还有LineNumberInputStream类,它的作用就是提高按行读取数据的功能,它们都使InputStream类增强了功能,或者提升了性能。

下面截了FilterInputStream类的源码:

public class FilterInputStream extends InputStream {    /**     * The input stream to be filtered.     */    protected volatile InputStream in;    protected FilterInputStream(InputStream in) {        this.in = in;    }    public int read() throws IOException {        return in.read();    }

5. 适配器模式与装饰器模式的区别

装饰器与适配器模式都有一个别名——包装模式(Wrapper),它们看似都是起到包装一个类或对象的作用,但是使用它们的目的很不一样。

  • 适配器模式的意义是要将一个接口转变成另外一个接口,它的目的是通过改变接口来达到重复使用的目的
  • 装饰器模式不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能,或者改变原有对象的处理方法而提升性能。



















原创粉丝点击