读书笔记:headfirst 设计模式 ,大话设计模式
装饰者模式概念
装饰者模式:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活
装饰模式结构图
装饰模式结构代码
// 顶层组件抽象
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类结构图
代码样例
需求:编写一个装饰者,把输入流内的所有大写字符转成小写
大写转小写包装类
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
装饰模式要点
- 继承属于扩展形式之一,但不见得是达到弹性设计的最佳方案
- 在我们设计中,应该允许行为可以被扩展,而无需修改现有代码(开闭原则)
- 组合和委托可以用于在运行时动态地加上新的行为
- 除了继承,装饰模式也可以让我们扩展行为
- 装饰模式意味着一群装饰者类,这些类用来包装具体组件
- 装饰者类反映出被装饰的组件类型(通过接口或继承实现)
- 装饰者可以在被装饰者的行为前面或后面加上自己的行为,甚至替换而达到特殊特定目的
- 可以用无数个装饰者包装一个组件
- 装饰者一般对组件的客户是透明的,除非客户端程序依赖于组件的具体类型
- 装饰者会导致设计中出现许多小对象,如果过度使用会让程序变得复杂