装饰者设计模式:
简单定义:增强一个类的功能,而且还可以让这些装饰类互相装饰。
应用场景:当要在某个功能的基础上扩充功能,并且扩充的功能具有大量排列组合,通过继承关系会衍生出大量子类,这时候用装饰者模式来解决。
装饰者设计模式的步骤:
1. 在装饰类的内部维护一个被装饰类的引用。
2. 让装饰类有一个共同的父类或者是父接口。
例如:人有一种行为叫“吃水果”,其中水果有4种:苹果、香蕉、鸭梨、橘子
现在有需求如下:
A类人行为:吃苹果
B类人行为:先吃苹果,再吃香蕉
C类人行为:先吃香蕉,再吃苹果
D类人行为:先吃橘子,后吃鸭梨
我们先用子类继承来实现:代码如下
interface IEatFruit{
public void eatFruit();
} class PersonA implements IEatFruit{ @Override
public void eatFruit() {
System.out.println("吃苹果");
} }
class PersonB implements IEatFruit{ @Override
public void eatFruit() {
System.out.println("吃苹果");
System.out.println("吃香蕉");
} }
class PersonC implements IEatFruit{ @Override
public void eatFruit() {
System.out.println("吃香蕉");
System.out.println("吃苹果");
} }
class PersonD implements IEatFruit{ @Override
public void eatFruit() {
System.out.println("吃橘子");
System.out.println("吃鸭梨");
} }
这样当然是没问题的,每一类人对应new出来的对象 都可以实现对应的需求。
但是,当需求改为:
某类人行为:吃上面四种水果,并且要求有先后顺序
这样的排列组合有24种....
这样你还会用继承去做吗?写24个子类去实现接口,明显不合适。
这时候如果用到装饰者模式,代码则会变成:
interface IEatFruit{
public void eatFruit();
} class PersonA implements IEatFruit{
IEatFruit eat;
public PersonA(){
this.eat = this;
}
public PersonA(IEatFruit _eat){
this.eat = _eat;
}
@Override
public void eatFruit() {
if(!(this.eat instanceof PersonA)){
this.eat.eatFruit();
System.out.println("吃苹果");
}else{
System.out.println("吃苹果");
}
} }
class PersonB implements IEatFruit{
IEatFruit eat;
public PersonB(){
this.eat = this;
}
public PersonB(IEatFruit _eat){
this.eat = _eat;
}
@Override
public void eatFruit() {
if(!(this.eat instanceof PersonB)){
this.eat.eatFruit();
System.out.println("吃香蕉");
}else{
System.out.println("吃香蕉");
}
} }
class PersonC implements IEatFruit{
IEatFruit eat;
public PersonC(){
this.eat = this;
}
public PersonC(IEatFruit _eat){
this.eat = _eat;
}
@Override
public void eatFruit() {
if(!(this.eat instanceof PersonC)){
this.eat.eatFruit();
System.out.println("吃鸭梨");
}else{
System.out.println("吃鸭梨");
}
} }
class PersonD implements IEatFruit{
IEatFruit eat;
public PersonD(){
this.eat = this;
}
public PersonD(IEatFruit _eat){
this.eat = _eat;
}
@Override
public void eatFruit() {
if(!(this.eat instanceof PersonD)){
this.eat.eatFruit();
System.out.println("吃橘子");
}else{
System.out.println("吃橘子");
}
} } public class Demo2 { public static void main(String[] args) {
//这样就可以通过上述4类人来相互装饰,就可以随意任意一种组合“吃水果”
//如:吃橘子->吃苹果
PersonD d = new PersonD();
PersonA a = new PersonA(d);
a.eatFruit();
System.out.println("-------我是分割线------------");
//如:吃苹果->吃橘子->吃鸭梨->吃香蕉
PersonA a2 = new PersonA();
PersonD d2 = new PersonD(a2);
PersonC c2 = new PersonC(d2);
PersonB b2 = new PersonB(c2);
b2.eatFruit();
} }
输出结果如下:
吃橘子
吃苹果
-------我是分割线------------
吃苹果
吃橘子
吃鸭梨
吃香蕉
最后总结:
继承实现的增强类和修饰模式实现的增强类有何区别?
继承实现的增强类:
优点:代码结构清晰,而且实现简单.
缺点:对于每一个的需要增强的类都要创建具体的子类来帮助其增强,这样会导致
继承体系过于庞大。
装饰者模式实现的增强类:
优点:内部可以通过多态技术对多个需要增强的类进行增强, 可以使这些装饰类
达到互相装饰的效果。使用比较灵活。
缺点:需要内部通过多态维护需要被增强的类的实例。进而使得代码稍微复杂