设计模式之装饰者模式

Posted by jjx on August 17, 2016

Head first 设计模式-装饰者模式

谈到装饰者模式就要与继承扯上一点关系,想想继承的不好。由此我们可以带来一种对象组合的技巧,在运行时动态的装饰类,一旦你熟悉了装饰的技巧,就能够在不修改任何底层代码的情况下,给你的(或别人)对象赋予新的职责。

引入

一句话,运行时扩展的威力比编译时扩展的威力大,编译时扩展就是利用继承。我们可以利用装饰的技巧在不修改任何底层代码的情况下,来给人家赋予新的功能。

另外设计的初衷,一般是用继承来扩充父类的功能,但是子类如果种类很多,那么就会有很多类出来,增加了系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的。最后一句话是抄来的,不能理解,静态带来的坏处?

静态的东西就是编译期间预先加载到内存,如果你一个大程序,所有都用静态,你想,当你一运行该程序,你看看内存,占用率极高,那么性能就会降低。

上面是百度过来的,很有道理昂。

实例

// 定义被装饰者
interface Human{

        public void wearClothes();
        public void walkToWhere();
}

// 定义装饰者
abstract class Decorator implements Human{
        // 该类持有接口对象
        private Human human;

        public Decorator(Human human) {
            this.human = human;
        }

        @Override
        public void wearClothes() {
            human.wearClothes();
        }

        @Override
        public void walkToWhere() {
            human.walkToWhere();
        }
}   

// 下面定义三种装饰,功能依次细化,即装饰者的功能越来越多
class Decorator_zero extends Decorator{

        public Decorator_zero(Human human) {
            super(human);
        }

        public void goHome(){
            System.out.println("进房子,找一件衣服穿穿");
        }

        public void findMap(){
            System.out.println("拿起你的地图");
        }

        @Override
        public void wearClothes() {
            super.wearClothes();
            goHome();
        }

        @Override
        public void walkToWhere() {
            super.walkToWhere();
            findMap();
        }
}   

// 定义被装饰者,被装饰者有自己的初始状态
class Person implements Human{

        @Override
        public void walkToWhere() {
            System.out.println("去哪里呢");
        }

        @Override
        public void wearClothes() {
            System.out.println("穿什么呢");
        }


    }
    public class DecoratorTest {

        public static void main(String[] args) {
            Human person = new Person();
            Decorator decorator = new Decorator_zero(person);
            decorator.walkToWhere();
            decorator.wearClothes();
        }
}       

上面这个只是一个小例子,我们还可以一层层的继续装饰:

Decorator decorator = new Decorator_zero(Decorator_one(Decorator_two(person)));

一层一层的装饰它,给它添加新的功能。

装饰者模式:动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的方案。

装饰者模式很简单,其在 java 中应用,也有 java 的 i/o 装饰者,代码 Demo 如下:

// FilterInputStream 是所有InputStream的抽象装饰类。
class LowerCaseInputStream extends FilterInputStream{

    public LowerCaseInputStream(InputStream in) {
        super(in);
    }

    public int read() throws IOException{
        int c = super.read();
        return (c == -1?c:Character.toLowerCase((char)c));
    }

    public int read(byte[] b,int offest,int len) throws IOException{
        int result = super.read(b,offest,len);
        for (int i = offest;i < offest+result;i++){
            b[i] = (byte)Character.toLowerCase((char)b[i]);
        }
        return result;
    }
}

//测试类
public class InputTest {

    public static void main(String[] args) throws IOException {
        int c;
        try {
            InputStream in =
                    new LowerCaseInputStream(
                            new BufferedInputStream( //看这里包裹着各种修饰
                                    new FileInputStream("G:\\JavaTest\\src\\ttt.txt")));
            while((c = in.read())>=0){
                System.out.print((char)c);
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

总结

  • 继承属于扩展形式之一,但是不是最佳的弹性设计方式,带来的问题也有许多。
  • 组合和委托可以在运行时动态的加上新的行为。
  • 除了继承,装饰者模式也可以让我们扩展行为。
  • 当然,装饰者会导致设计中出现许多小类,如果使用过度,程序会变得很复杂。

参考链接
装饰者模式