装饰者模式
-
透明和半透明
在实际开发过程中,由于新增的行为可能需要单独使用,所以装饰者模式分为两种。
-
半透明模式:为了能够调用新增加的行为,要用具体类型来定义修改后的对象,而具体构件类型还是可以使用抽象构件类型来定义。
-
透明模式:要求客户端完全针对抽象编程,透明性对客户端要求对象声明不应该为具体构件类型或者具体装饰类型,应该全部声明为抽象构件类型。
半透明装饰模式可以给系统带来更多的灵活性,设计相对简单,使用起来也非常方便;但是其最大的缺点在于不能实现对同一个对象的多次装饰,而且客户端需要有区别地对待装饰之前的对象和装饰之后的对象。
-
-
定义:
装饰者模式可以动态的给对象添加一些额外的属性和行为。相对于使用继承,装饰者模式更加的灵活。装饰者模式的核心在于抽象装饰类的设计。
-
使用场景:
- 在不影响其他对象的情况下,以动态、透明的方式给对象添加职责。
- 当不采用继承对系统扩展时或者继承不利于系统的扩展时,可以使用装饰者模式。
-
UML:
-
Component(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
-
ConcreteComponent(具体构件):它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
-
Decorator(抽象装饰类):它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
-
ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。
-
-
优点:
- 在扩展功能方面,装饰者模式比继承更加的灵活,不会导致类的个数急剧增加。
- 动态扩展类的功能,可以通过配置文件在运行时选择不同的装饰对象,从而实现不同的功能。
- 可以一个对象多次修饰,创造出不同的组合,得到功能强大的对象。
- 符合开闭原则,无需改变源代码,只需要增加新的具体构件类和具体装饰类。
-
缺点:
- 使用装饰者模式会产生很多小的对象,大量的小对象会占用更多的内存资源,在一定程度上影响性能。
- 装饰者模式比继承来的更加灵活,但是出错率会更高。
-
样例:
public interface PorgramMonkey{
void skills() ;
}
public class AndriodProgramMomkey implements ProgramMonkey{
@Override
public void skills(){
System.out.println("技能:Andriod开发");
}
}
public class PhpProgramMonkey implements ProgramMonkey{
@Override
public void skills(){
System.out.println("技能:Php开发");
}
}
public class ProgramMonkeyDecorator implements ProgramMonkey{
protected ProgramMonkey mProgramMonkey ;
public ProgramMonkeyDecorator(ProgramMonkey mProramMonkey){
this.mProgramMonkey = mProgramMonkey ;
}
@Override
public void skills(){
mProgramMonkey.skills() ;
}
}
public class PattenDecorator extends ProgramMonkeyDecorator{
public PattenDecorator(ProgramMonkey mProgramMonkey){
super(mPorgramMonkey) ;
}
@Override
public void skills(){
super.skills() ;
System.out.println("技能:设计模式");
}
}
public class Main{
public static void main(String args[]){
ProgramMonkey programMonkey = new AndriodProgramMonkey() ;
programMonkey.skills() ;
programMonkey = new PattenDecorator(programMonkey) ;
programMonkey.skills() ;
programMonkey = new PhpProgramMonkey() ;
programMonkey.skills() ;
}
}