设计模式之装饰者模式

读书笔记:headfirst 设计模式 ,大话设计模式


装饰者模式概念

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

装饰模式结构图

image

装饰模式结构代码
// 顶层组件抽象
public abstract class Component {
    public abstract void operation();
}

// 装饰者抽象
public  class Decorator extends Component {

    protected Component component;

    public Decorator(Component component) {
        // 通过构造方法(也可以通过set方法)设置被包装类
        this.component=component;
    }

    @Override
    public void operation() {
        // 实现抽象方法实际运行的是通过构造方法传入的被包装compobent类的operation方法
        component.operation();
    }
}

// 顶层抽象的实现类
public class ConcreteComponent extends Component {

    @Override
    public void operation() {
        System.out.println("实现类(被包装类)执行操作");
    }
}

// 包装类A
public class ConcreteDecoratorA extends Decorator {
    // 包装A类独有的域
    private String addedState="init state";

    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        addedState = "new state";
        System.out.println("包装A类设置"+addedState+"状态");
        // 调用被包装类的方法
        component.operation();
    }
}

// 包装类B
public class ConcreteDecoratorB extends Decorator {

    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        // 调用被包装类的方法
        component.operation();
        addedBehavior();
    }
    // 包装类B增加的行为
    private void addedBehavior() {
        System.out.println("包装类B执行独有行为方法");
    }
}

测试代码

public class DecoratorClient {

    public static void main(String[] args) {
        // 创建一个实现类
        ConcreteComponent component = new ConcreteComponent();
        // 执行方法行为
        component.operation();
        System.out.println("-----------------");

        // 创建包装类A包装实现类
        ConcreteDecoratorA decoratorA = new ConcreteDecoratorA(component);
        // 执行包装过后的方法行为
        decoratorA.operation();
        System.out.println("-----------------");

        // 创建包装类B包装经过A包装实现类后的类
        ConcreteDecoratorB decoratorB = new ConcreteDecoratorB(decoratorA);
        decoratorB.operation();
    }
}

执行结果

实现类(被包装类)执行操作
-----------------
包装A类设置new state状态
实现类(被包装类)执行操作
-----------------
包装A类设置new state状态
实现类(被包装类)执行操作
包装类B执行独有行为方法
  • 装饰模式利用构造方法(或setCompoent)来对对象进行包装,这样每个包装对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链中
  • 如果只有一个ConcreteCompoent类而没有抽象的Compoent类,那么Decorator类可以是ConcreteComponet的一个子类,同理,如果只有一个ConcreteDecortor类,那么就没有必要建立一个单独的Decorator类,把Decorator和ConcreteDecorator的责任合并成一个类
  • 装饰模式是为已有功能动态的添加更多功能的一种方式
  • 装饰模式有效地把类的核心职责和装饰功能区分开了,可以去除相关类中重复的逻辑装饰
  • 装饰类之间彼此独立,才可以以任意顺序进行组合

装饰模式应用之java.io类

java.io类结构图
image

代码样例

需求:编写一个装饰者,把输入流内的所有大写字符转成小写

大写转小写包装类

public class LowerCaseReader extends FilterReader {

    protected LowerCaseReader(Reader in) {
        super(in);
    }

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

    @Override
    public int read(char[] cbuf, int off, int len) throws IOException {
        int read = super.read(cbuf, off, len);
        for (int i = off; i < read+off; i++) {
            cbuf[i] =Character.toLowerCase((char)cbuf[i]);
        }
        return read;
    }
}

测试

public class InputTest {

    public static void main(String[] args) throws Exception {
        byte[] bytes = "大写英文字母转化成小写 I LOVE YOU ".getBytes();
        ByteArrayInputStream byteIn = new ByteArrayInputStream(bytes);
        int c;
        // 小写转化包装
        Reader in = new LowerCaseReader(
                // 缓冲区包装
                new BufferedReader(
                        // 字节转字符流包装
                        new InputStreamReader(byteIn)));
        while ((c = in.read()) >= 0) {
            System.out.print((char) c);
        }
        in.close();
    }
}

结果

大写英文字母转化成小写 i love you 

装饰模式要点

  • 继承属于扩展形式之一,但不见得是达到弹性设计的最佳方案
  • 在我们设计中,应该允许行为可以被扩展,而无需修改现有代码(开闭原则)
  • 组合和委托可以用于在运行时动态地加上新的行为
  • 除了继承,装饰模式也可以让我们扩展行为
  • 装饰模式意味着一群装饰者类,这些类用来包装具体组件
  • 装饰者类反映出被装饰的组件类型(通过接口或继承实现)
  • 装饰者可以在被装饰者的行为前面或后面加上自己的行为,甚至替换而达到特殊特定目的
  • 可以用无数个装饰者包装一个组件
  • 装饰者一般对组件的客户是透明的,除非客户端程序依赖于组件的具体类型
  • 装饰者会导致设计中出现许多小对象,如果过度使用会让程序变得复杂
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值