DecoratorPattern(23种设计模式之一)


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

书中写到,装饰者模式的意图是动态的给对象添加一些额外的职责。就增加功能来说,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("
第二种装扮:");
		zs.wearSuit();
		zs.wearTrousers();
		zs.wearLeatherShoes();
		zs.show();
	}
}

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

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

类图

新的人类

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("
第二种装扮:");
		Finery xz = new Suit();
		Finery xk = new Trousers();
		Finery bx = new LeatherShoes();	
		xz.show();
		xk.show();
		bx.show();
		zs.show();
	}
}

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

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

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

装饰者模式结构

参与者

Component:组件
ConcreteComponent:具体组件
Decorator:抽象装饰类
ConcreteDecorator:具体装饰类

类图

外观抽象类

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();
	}
}


待续


原文地址:https://www.cnblogs.com/1996jiwei/p/6711283.html