DecoratorPattern(23种设计模式之一)

时间:2021-12-31 04:51:51

参考书籍:设计模式-可复用面向对象软件基础(黑皮书)

书中写到,装饰者模式的意图是动态的给对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。装饰者模式的另一个别名是包装器Wrapper

学习知识常常需要摆脱抽象的理论带给我们的不便,那么最好的方式就是从实践中去理解知识,下面我从传统模式一步一步变换到装饰者模式,这样装饰者模式的好处暴露无遗

模拟QQ秀这一穿衣功能

先看一组代码

传统类

package DecoratorPattern;
public class Person {
private String name;
public Person(String name){
this.name = name;
}
public void wearTshirt(){
System.out.println("T恤");
}
public void wearJeans(){
System.out.println("牛仔裤");
}
public void wearSneakers(){
System.out.println("球鞋");
}
public void wearSuit(){
System.out.println("西装");
}
public void wearTrousers(){
System.out.println("西裤");
}
public void wearLeatherShoes(){
System.out.println("皮鞋");
}
public void show(){
System.out.println("装扮的" + name);
}
}

测试类(客户端类)

package DecoratorPattern;
public class Test {
public static void main(String[] args) {
Person zs = new Person("张三");
System.out.println("第一种装扮:");
zs.wearTshirt();
zs.wearJeans();
zs.wearSneakers();
zs.show();
System.out.println("\n第二种装扮:");
zs.wearSuit();
zs.wearTrousers();
zs.wearLeatherShoes();
zs.show();
}
}

上述代码存在着明显的缺陷,如果现需要不断添加新的衣服,那么就需要频繁的更改原有类Person,这不符合设计原则

现在做一个简单的变化,将展示与穿衣服分开

类图

DecoratorPattern(23种设计模式之一)

新的人类

package DecoratorPattern;
public class NewPerson {
private String name;
public NewPerson(String name){
this.name = name;
}
public void show(){
System.out.println("装扮的" + name);
}
}

抽象服饰类

package DecoratorPattern;
public abstract class Finery {
public abstract void show();
}

具体服饰类

package DecoratorPattern.FineryImpl;
import DecoratorPattern.Finery;
public class Jeans extends Finery{
public void show() {
System.out.println("牛仔裤");
}
}
package DecoratorPattern.FineryImpl;
import DecoratorPattern.Finery;
public class LeatherShoes extends Finery {
public void show() {
System.out.println("皮鞋");
}
}
package DecoratorPattern.FineryImpl;
import DecoratorPattern.Finery;
public class Sneakers extends Finery {
public void show() {
System.out.println("球鞋");
}
}
package DecoratorPattern.FineryImpl;
import DecoratorPattern.Finery;
public class Suit extends Finery {
public void show() {
System.out.println("西装");
}
}
package DecoratorPattern.FineryImpl;
import DecoratorPattern.Finery;
public class Trousers extends Finery {
public void show() {
System.out.println("西裤");
}
}
package DecoratorPattern.FineryImpl;
import DecoratorPattern.Finery;
public class TShirts extends Finery{
public void show() {
System.out.println("T恤");
}
}

测试类

package DecoratorPattern;
import DecoratorPattern.FineryImpl.Jeans;
import DecoratorPattern.FineryImpl.LeatherShoes;
import DecoratorPattern.FineryImpl.Sneakers;
import DecoratorPattern.FineryImpl.Suit;
import DecoratorPattern.FineryImpl.TShirts;
import DecoratorPattern.FineryImpl.Trousers;
public class Test1 {
public static void main(String[] args) {
NewPerson zs = new NewPerson("张三");
System.out.println("第一种装扮:");
Finery tx = new TShirts();
Finery nzk = new Jeans();
Finery ax = new Sneakers();
tx.show();
nzk.show();
ax.show();
zs.show();
System.out.println("\n第二种装扮:");
Finery xz = new Suit();
Finery xk = new Trousers();
Finery bx = new LeatherShoes();
xz.show();
xk.show();
bx.show();
zs.show();
}
}

上述解决方式,虽然实现了设计模式的开闭原则,但是依然存在着严重的问题

  • 类繁多,这样每增加一个服饰就要增加一个类,不方便
  • 展示复杂,我们期望的是内部组装完毕再展示出来

应用装饰者模式,解决如上问题

装饰者模式结构

DecoratorPattern(23种设计模式之一)

参与者

Component:组件

ConcreteComponent:具体组件

Decorator:抽象装饰类

ConcreteDecorator:具体装饰类

类图

DecoratorPattern(23种设计模式之一)

外观抽象类

package DecoratorPattern;
public abstract class Appearance {
public abstract void show();
}

package DecoratorPattern;
public class Person extends Appearance {
private String name;
public Person(String name){
this.name = name;
}
public void show() {
System.out.println("装扮的" + name);
}
}

抽象装饰

package DecoratorPattern;
public abstract class Finery extends Appearance {
protected Appearance component;
public void Decorate(Appearance component){
this.component = component;
}
public void show(){
if(component != null){
component.show();
}
}
}

具体装饰

package DecoratorPattern.FineryImpl;
import DecoratorPattern.Finery;
public class Jeans extends Finery {
public void show(){
super.show();
System.out.println("牛仔裤");
}
}
package DecoratorPattern.FineryImpl;
import DecoratorPattern.Finery;
public class Sneakers extends Finery {
public void show(){
super.show();
System.out.println("球鞋");
}
}
package DecoratorPattern.FineryImpl;
import DecoratorPattern.Finery;
public class TShirt extends Finery {
public void show(){
super.show();
System.out.println("T恤");
}
}

测试类

package DecoratorPattern;
import DecoratorPattern.FineryImpl.Jeans;
import DecoratorPattern.FineryImpl.Sneakers;
import DecoratorPattern.FineryImpl.TShirt;
public class Test {
public static void main(String[] args) {
Person xc = new Person("小菜");
System.out.println("第一种装扮:"); Sneakers ax = new Sneakers();
Jeans nzk = new Jeans();
TShirt tx = new TShirt(); tx.Decorate(xc);
nzk.Decorate(tx);
ax.Decorate(nzk); ax.show();
}
}


待续