设计模式之装饰者模式
一、概念
1、什么是装饰者模式
装饰模式是在不使用继承和不改变原类文件的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
这一个解释,引自百度百科,我们注意其中的几点。
1,不改变原类文件。
2,不使用继承。
3,动态扩展。
2、装饰模式的优点
在讲优点之间,我们知道一个类的功能扩展我们可以通过继承的方式重写父类的方法来达到增强功能。那我们来看下这两种方式。
(1) 类的继承 ( 高耦合,会产生更多的子类,从而引起类的爆炸 )
(2) 对象组合即装饰模式 ( 降耦,不会创造更多的子类 ) 动态的为对象添加功能) 所以类应该对扩展开放,对修改关闭 。
那么总结下装饰者优点:
1. 装饰者模式与继承关系的目的都是要扩展对象的功能,但是装饰者可以提供比继承更多的灵活性。
2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
3、装饰者特点
主要来自一下四点(来自百度百科)
(1) 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。
(2) 装饰对象包含一个真实对象的引用(reference)
(3) 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
(4) 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。
4、参与者
1) Component(抽象组件又叫被装饰对象的基类)
定义一个对象接口,可以给这些对象动态地添加职责。
2) ConcreteComponent(具体组件又叫具体被装饰对象)
定义一个对象,可以给这个对象添加一些职责。
3) Decorator(装饰者抽象类)
维持一个指向Component实例的引用,并定义一个与Component接口一致的接口。
4)ConcreteDecorator(具体装饰者)
具体的装饰对象,给内部持有的具体被装饰对象,增加具体的职责。
5、装饰者代理模式的区别
不得不说装饰者模式和代理模式实现方式非常的像比如:
1) 代理模式中代理类和被代理类都要实现统一接口,而装饰者模式中被装饰对象和装饰者抽象类都要实现统一接口。
2)代理模式中被代理类中构造函数中需要传入一个代理类对象,而装饰者模式中装饰者抽象类中也许传入具体装饰对象。
3)它们都可以对方法在不使用继承的情况下对方法进行功能加强。
但是要注意一点区别:代理类中被代理类中仅一个被代理类(没有代理接口,和代理实现类之分),而装饰着模式中有装饰者抽象类和具体装饰者。
那这有什么用呢?其实很关键。
那就说明装饰者模式可以做到层层增加功能,比如IO流使用的装饰者模式。代理模式可以用于增加特殊的功能。 但它很难支持多层嵌套。
看下面图片后,有助于更加理解。
装饰者模式
代理模式
二、案例说明
下面举一个案例。
抽象组件
public interface Person { void eat();
}
具体组件
public class Man implements Person { public void eat() {
System.out.println("男人在吃");
}
}
抽象装饰者
public abstract class Decorator implements Person { protected Person person; public void setPerson(Person person) {
this.person = person;
} public void eat() {
person.eat();
}
}
具体装饰者
//具体装饰者A
public class ManDecoratorA extends Decorator { public void eat() {
super.eat();
reEat();
System.out.println("ManDecoratorA类");
} public void reEat() {
System.out.println("再吃一顿饭");
}
} //具体装饰B
public class ManDecoratorB extends Decorator { public void eat() {
super.eat();
System.out.println("===============");
System.out.println("ManDecoratorB类");
}
}
测试类
public class Test { public static void main(String[] args) {
Man man = new Man();
ManDecoratorA md1 = new ManDecoratorA();
ManDecoratorB md2 = new ManDecoratorB(); md1.setPerson(man);
md2.setPerson(man);
md2.eat();
}
}
总结
OO原则:动态地将责任附加到对象上。想要扩展功能, 装饰者提供有别于继承的另一种选择。
参考
想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。中校【6】