Java设计模式之装饰者模式

Posted 红日666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java设计模式之装饰者模式相关的知识,希望对你有一定的参考价值。

Java设计模式之装饰者模式

目录

装饰者模式是结构性设计模式之一,其在不必改变类文件及不使用继承的情况下,动态地扩展一个对象的功能。它通过创建一个包装对象(即装饰)来包裹真实的对象。

一、定义

动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。

装饰着模式的结构图:

如上结构图所示,装饰者模式中有如下角色:

  • Component:可以是接口或者是抽象类,被装饰的最原始的对象。
  • ConcreteComponent:组件具体实现类。Component的具体实现,被装饰的具体对象【即包含原有功能的对象】。
  • Decorator:抽象装饰者,新增装饰类,用来扩展原有Component类的功能,对于Component来说无须知道Decorator的存在,所以在它的属性中必然有一个private变量指向Component抽象组件。
  • ConcreteDecorator:装饰者的具体实现类。

二、具体实现

装饰者模式在生活中有很多例子,我们这里来给一个普通的人【原来只会走路】学运动技能【新学会了游泳 + 拳击】后变大师的例子来说明。

(1)抽象组件
我们先定义一个人的抽象类,里面有运动的抽象方法。

public abstract class Person 
	/**
	 * Person 人有可以运动的抽象方法
 	 */
	public abstract void sport();

(2)组件具体实现类
被装饰的具体对象,这里是具体的一个普通人,作为一个普通人他当然会运动,当然在未被装饰的情况下他只会走路。

public class CommonPerson extends Person 
	@Override
	public void sport() 
		System.out.println("普通人运动只会走路");
	

(3)抽象装饰者:
抽象装饰者保证了一个对抽象组件的引用,方便调用被装饰对象中的方法。在这里运动大师需要持有人(Person)的引用,方便教授他其他运动,最终成为运动健将。

public abstract class Master extends Person 
	private Person mPerson;
	public Master(Person person) 
		mPerson = person;
	
	@Override
	public void sport() 
		mPerson.sport();
	

(4)装饰者具体实现类:
这里有两个装饰者具体实现类,分别是宁泽涛跟邹市明,他们(装饰者)负责向普通人(被装饰者)教授游泳跟拳击。

public class Ningzetao extends Master 
	public Ningzetao(Person person)
		super(person)
	
	@Override
	public void sport() 
		super.sport();
		teachSwimming();
	
	public void teachSwimming()
		System.out.println("宁泽涛教普通人游泳");
	

public class Zoushiming extends Master 
	public Zoushiming(Person person)
		super(person)
	
	@Override
	public void sport() 
		super.sport();
		teachBoxing();
	
	public void teachBoxing()
		System.out.println("邹市明教普通人拳击");
	

(5)客户端调用:
经过宁泽涛跟邹市明的教导后,普通人经过装饰后,除了会走路之外,也学会了游泳跟拳击。

public class Client 
	public static void main (String[] args) 
		//创建普通人,只会走路
		CommonPerson mCommonPerson = new CommonPerson();
		
		//宁泽涛教普通人学游泳,普通人学会了游泳
		Ningzetao mNingzetao = new Ningzetao(mCommonPerson);
		mNingzetao.sport();
		
		//邹市明教普通人学拳击,普通人学会了拳击
		Zoushiming mZoushiming = new Zoushiming(mCommonPerson);
		mZoushiming.sport();
	

三、使用场景

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 需要动态地给一个对象添加功能,这些功能可以动态的撤销。
  • 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

四、优缺点

优点

  • 通过组合而非继承的方式,动态地扩展一个对象的功能,在运行时可以选择不同的装饰器从而实现不同的功能。
  • 有效的避免了使用继承的方式扩展对象功能而带来的灵活性差、子类无限制扩张的问题。
  • 具体组件类与具体装饰类可以独立变化,用户可以根据需要新增具体组件类跟装饰类,在使用时在对其进行组合,原有代码无须改变,符合"开闭原则"。

缺点

  • 因为所有对象均继承于Component,所以如果Component内部结构发生改变,则不可避免地影响到所有子类(装饰者于被装饰者)。如果基类改变,则势必影响对象的内部。
  • 装饰模式比继承更容易出错,拍错也比较困难。对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为繁琐。所以一般只在必要的时候使用装饰者模式。
  • 装饰层数不能过多,否则会影响效率。



后记:
乍一看装饰者模式跟代理模式好像,其实不然,两者最大的区别是:
装饰模式应该为所装饰的对象增强功能;
而代理模式对代理的对象施加控制,并不提供对象本身的增强功能。

可参考:
Java设计模式之代理模式

以上是关于Java设计模式之装饰者模式的主要内容,如果未能解决你的问题,请参考以下文章

JAVA设计模式之装饰者模式

java设计模式之装饰者模式学习

Java设计模式之装饰者模式

JAVA设计模式之装饰者模式

Java设计模式之装饰者模式

Java设计模式之装饰者模式