设计模式(十一)—装饰模式

最后更新于:2022-04-01 16:26:16

**英文名称:(Decorator Pattern)** **定义**:动态的给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更加灵活。 ## 装饰模式的一般模式 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340a94974.jpg) Component抽象构件 ---|Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象。 ConcreteComponent具体构件 ---|ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,要装饰的就是它。 Decorator装饰角色 ---|一般是一个抽象类,实现接口或者抽象方法,它的属性里必然有一个private变量指向Component抽象构件 具体装饰角色 ---|要把最原始的、最基本的、最核心的东西装饰成其他东西。 ~~~ public class DecoratorPattern { public static void main(String[] args) { //拿到原始构件 Component origin = new ConcreteComponent(); origin = new ConcreteDecorator1(origin); origin = new ConcreteDecorator2(origin); origin.doSomething(); } } abstract class Component{ //抽象的方法,定义一些核心的方法。让子类去实现 public abstract void doSomething(); } class ConcreteComponent extends Component{ @Override public void doSomething() { System.out.println("我是抽象构件的具体实现...."); } } abstract class Decorator extends Component{ //有一个私有方法,指向Component类 private Component component; public Decorator(Component component) { this.component = component; } @Override public void doSomething() { //让Component的实现类去执行方法。 this.component.doSomething(); } } /** * 1号修饰类 * @author admin * */ class ConcreteDecorator1 extends Decorator{ //指向父类的方法 public ConcreteDecorator1(Component component) { super(component); } private void decorator1(){ System.out.println("-----开始之前先修饰-----------"); } @Override public void doSomething() { System.out.println("-111111111111111111111-"); //修饰方法 this.decorator1(); //执行原始方法 super.doSomething(); } } /** * 2号修饰类 * @author admin * */ class ConcreteDecorator2 extends Decorator{ //指向父类的方法 public ConcreteDecorator2(Component component) { super(component); } private void decorator2(){ System.out.println("-----结束之后再修饰-----------"); } @Override public void doSomething() { System.out.println("-2222222222222222222222-"); //执行原始方法 super.doSomething(); //修饰方法 this.decorator2(); } } ~~~ ## 一个例子: 老师把我的成绩单发下来,让家长签字。因为成绩考的不好,所以不能直接把成绩单拿给爸爸看, 因此我得在拿出成绩单前加一些修饰语。例如:告诉爸爸班里同学的最高分,我的分数是多少。 之后再说我在班里的名次。这样就能避免一场海骂了。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340ab09c1.jpg) ~~~ public class DecoratorTest { public static void main(String[] args) { //拿着自己的原始成绩单。 SchoolScore mScore = new ConcreteStudent(); //加上一层修饰,最高分的修饰。 mScore = new HighScoreDecorator(mScore); //再加上第二次修饰,我的排名的修饰。 mScore = new SortDecorator(mScore); //做出报告说明 mScore.report(); //可以让家长签字了 mScore.sign("lzl"); } } abstract class SchoolScore{ //定义一个成绩单的接口,共每个学生去实现 //每个学生报告给家长,自己的成绩。 public abstract void report(); //要求家长签字。 public abstract void sign(String name); } class ConcreteStudent extends SchoolScore{ @Override public void report() { System.out.println("我的语文成绩是 89,数学成绩是 78,英语成绩是 77."); } @Override public void sign(String name) { System.out.println("家长签字:"+name); } } /** * 因为怕父亲看到成绩被他骂,所以我要来个装饰类。 * @author admin */ abstract class MyDecorator extends SchoolScore{ //定义学生的成绩 private SchoolScore score; //用构造函数,实例化学生成绩类。 public MyDecorator(SchoolScore score) { this.score = score; } //抽象方法,为学生提交成绩单时,添加一些修饰方法。 public void report(){ this.score.report(); } //重写父类的方法。让家长签字 @Override public void sign(String name) { this.score.sign(name); } } /** * 首先添加一个全班最高成绩的说明, * 让父亲知道我这个成绩还算可以。 * @author admin */ class HighScoreDecorator extends MyDecorator{ public HighScoreDecorator(SchoolScore score) { super(score); } private void highScoreSchool() { System.out.println("语文最高分:99,数学最高分:88,英语最高分:77"); } @Override public void report() { //先说明最高成绩 this.highScoreSchool(); //再报自己的成绩 super.report(); } } class SortDecorator extends MyDecorator{ public SortDecorator(SchoolScore score) { super(score); } private void getSort() { System.out.println("我在班里的排名是:第十..."); } @Override public void report() { //先报完成绩 super.report(); //再说明名次。 this.getSort(); } } ~~~ **装饰模式的优点**: ---|装饰类和被装饰类可以独立的发展,不会相互耦合。 ---|装饰模式是继承关系的一种替代方案。Decorator不管修饰多少层,返回的对象还是Component,实现的还是is-a的关系。 ---|装饰模式可以动态的扩展一个实现类的功能。 **装饰模式的缺点**: ---|多层的装饰模式是比较复杂的。 **装饰模式的使用场景**: ---|扩展一个类的功能,或给一个类增加附加的功能 ---|动态的给一个对象增加功能,这些功能可以动态的撤销 ---|为一批的兄弟类进行改装或者加装功能,首选装饰模式。
';