一、概念
装饰者模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰者模式比生成子类更为灵活。
Component:定义一个对象接口,可以给这些对象动态地添加职责
ConcreteComponent:定义一个具体的类。可以定义初始状态,然后在此基础上一步步点缀装饰。
Decorator:装饰抽象类,拥有Component接口,同时可以调用子类:具体装饰对象。
ConcreteComponentA:具体装饰对象。
二、代码实现
例子:某人要吃饭和学习,那么吃饭有不同的品类,学习有不同的类别,使用装饰者模式,使点缀到一个人身上。
对象接口:
/*
* 对象接口
*/
public interface Person {
public void eat();
public void study();
}
被装饰者:
/*
* 被装饰类
*/
public class Xiaoming implements Person {
@Override
public void eat() {
System.out.println("中午吃什么呢?");
}
@Override
public void study() {
System.out.println("下午学些什么呢");
}
}
装饰抽象类:
/*
* 装饰抽象类
*/
public class Decorator implements Person {
private Person person;
public Decorator(Person person){
this.person=person;
}
@Override
public void eat() {
person.eat();
}
@Override
public void study() {
person.study();
}
}
装饰具体类1:
/*
* 装饰具体类1
*/
public class DecoratorFirst extends Decorator {
public DecoratorFirst(Person person) {
super(person);
}
public void eat(){
super.eat();
eatRice();
}
public void study(){
super.study();
studyMain();
}
public void eatRice(){
System.out.println("饭食:米饭");
}
public void studyMain(){
System.out.println("专业课:电子");
}
}
装饰具体类2:
/*
* 装饰具体类2
*/
public class DecoratorSecond extends Decorator {
public DecoratorSecond(Person person) {
super(person);
// TODO Auto-generated constructor stub
}
public void eat(){
super.eat();
eatDish();
}
public void study(){
super.study();
studyOther();
}
public void eatDish(){
System.out.println("菜类:西红柿炒鸡蛋");
}
public void studyOther(){
System.out.println("课余:历史类");
}
}
测试类:
public class demo {
public static void main(String[] args) {
Person xiaoming = new Xiaoming();
//将具体被装饰者对象传入
Decorator decorator = new DecoratorSecond(new DecoratorFirst(xiaoming));
decorator.eat();
decorator.study();
}
}
测试结果:
三、分析
装饰者模式对扩展开放,对修改封闭。无须修改装饰者的抽象类,只需继承装饰者的抽象类,实现一些额外功能。所以扩展体现在继承,而修改体现在子类,体现了依赖倒转原则,细节依赖于抽象。
装饰者模式是为已有功能动态地添加更多的功能,把类中的装饰功能从类中搬离,简化原有类,有效把类的核心功能和装饰功能区分开来,去除相关类中重复装饰逻辑。
变化:如果只有一个具体被装饰类对象,那么装饰抽象类,可以是它的子类;如果只有一个具体装饰类,那么可以把抽象装饰类和具体装饰类合并。
小结:装饰者模式自己看书的时候会有很大的问题,老师讲也有一些问题,真的需要自己敲代码,然后一步步调试,看里面的代码具体是怎么走的,然后再理解UML图的意义,否则很多东西都是不清楚的。多敲多练才是真理。