「补课」进行时:设计模式系列
2. 小明起床记小明每天早晨都是起床困难大户,大冬天的太冷了,温暖的被窝紧紧的拉住小明,阻止小明每天早晨的起床。
闹钟响了一遍又一遍,如果再不起床就要迟到了,迟到了就要扣钱,扣了钱就要喝西北风了。
每天早晨督促小明起床的根本不是闹钟,而是贫穷。
起床第一件事儿是穿衣服,先传衣服,再传裤子,然后穿鞋子,最后穿上一件外套,出门上班。
首先,定义一个抽象的小明,小明是个人,所以定义一个人:
public abstract class Person { abstract void dress(); }每个人早晨起床都要穿衣服,这里定义一个穿衣服的方法。
具体的小明上线:
public class Man extends Person { @Override void dress() { System.out.println("先穿衣服"); } }接下来我们要定义一个抽象的装饰器了,小明要穿的是衣服,我们将衣服抽象成一个类:
public abstract class Clothes extends Person { private Person person; public Clothes(Person person) { this.person = person; } @Override void dress() { this.person.dress(); } }接下来是具体的衣服:
public class Trousers extends Clothes { public Trousers(Person person) { super(person); } @Override void dress() { super.dress(); this.dressTrousers(); } private void dressTrousers() { System.out.println("穿上裤子啦!!!"); } } public class Shoes extends Clothes { public Shoes(Person person) { super(person); } @Override void dress() { super.dress(); this.dressShoes(); } private void dressShoes() { System.out.println("穿上鞋子啦!!!"); } } public class Coat extends Clothes { public Coat(Person person) { super(person); } @Override void dress() { super.dress(); this.dressCoat(); } private void dressCoat() { System.out.println("穿上外套啦!!!"); } }最后是一个测试类:
public class Test1 { public static void main(String[] args) { Person person = new Man(); person.dress(); System.out.println("--------------"); System.out.println("增加裤子适配器"); person = new Trousers(person); person.dress(); System.out.println("--------------"); System.out.println("增加鞋子适配器"); person = new Shoes(person); person.dress(); System.out.println("--------------"); System.out.println("增加外套适配器"); person = new Coat(person); person.dress(); } }测试结果如下:
先穿衣服 -------------- 增加裤子适配器 先穿衣服 穿上裤子啦!!! -------------- 增加鞋子适配器 先穿衣服 穿上裤子啦!!! 穿上鞋子啦!!! -------------- 增加外套适配器 先穿衣服 穿上裤子啦!!! 穿上鞋子啦!!! 穿上外套啦!!!上面这么写有点麻烦,我们可以稍微缩减一下测试类,使用装饰器嵌套,一次性直接把所有的衣服都穿好:
public class Test2 { public static void main(String[] args) { Person person = new Coat(new Shoes(new Trousers(new Man()))); person.dress(); } } 3. 装饰器模式 3.1 定义装饰模式(Decorator Pattern)是一种比较常见的模式,其定义如下:
Attachadditional responsibilities to an object dynamically keeping the sameinterface.Decorators provide a flexible alternative to subclassing forextending functionality.(动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。)
Component: 抽象构件,是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象。
ConcreteComponent: 具体构件,是最核心、最原始、最基本的接口或抽象类的实现。
Decorator: 通用的装饰 ConcreteComponent 的装饰器,其内部必然有一个属性指向 Component 抽象组件;其实现一般是一个抽象类,主要是为了让其子类按照其构造形式传入一个 Component 抽象组件,这是强制的通用行为(当然,如果系统中装饰逻辑单一,并不需要实现许多装饰器,那么我们可以直接省略该类,而直接实现一个 具体装饰器(ConcreteDecorator) 即可)。
ConcreteDecorator: Decorator 的具体实现类,理论上,每个 ConcreteDecorator 都扩展了 Component 对象的一种功能。
通用代码:
public abstract class Component { abstract void operate(); } public class ConcreteComponent extends Component { @Override void operate() { System.out.println("do Something"); } } public abstract class Decorator extends Component { private Component component = null; // 通过构造函数传递被修饰者 public Decorator(Component component) { this.component = component; } // 委托给被修饰者执行 @Override void operate() { this.component.operate(); } } public class ConcreteDecorator1 extends Decorator { // 定义被修饰者 public ConcreteDecorator1(Component component) { super(component); } private void method1() { System.out.println("method1 修饰"); } @Override void operate() { this.method1(); super.operate(); } } public class ConcreteDecorator2 extends Decorator { public ConcreteDecorator2(Component component) { super(component); } private void method2() { System.out.println("method2 修饰"); } @Override void operate() { super.operate(); this.method2(); } } public class Test { public static void main(String[] args) { Component component = new ConcreteComponent(); // 第一次修饰 component = new ConcreteDecorator1(component); // 第二次修饰 component = new ConcreteDecorator2(component); // 修饰后运行 component.operate(); } } 3.2 优点