装饰者模式简述

强颜欢笑 提交于 2020-02-04 11:53:28

装饰者模式

  • 装饰者模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
  • 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
  • 我们通过下面的实例来演示装饰者模式的用法
注意
要实现装饰者模式,注意以下几点内容:
a.装饰者类要实现真实类同样的接口
b.装饰者类内有一个真实对象的引用(可以通过装饰者类的构造器传入)
c.装饰者类对象在主类中接受请求,将请求发给真实的对象(相当于已经将引用传递到了装饰类的真实对象)
d.装饰者可以在传入真实对象后,增加一些附加功能(因为装饰对象和真实对象都有同样的方法,装饰对象可以添加一定的操作在调用真实对象的方法,或者先调用真实对象的方法,再添加自己的方法)
e.不用继承
示例
  • 生产馒头的示例
  • 假设要制造添加糖和玉米面的馒头:
    • 需要一个正常的馒头
    • 添加玉米面和糖
    • 和面,最后生产出馒头
  • 馒头接口
package waking.test.zs;
/**
 * 馒头的接口
 * @author waking
 *
 */
public interface IBread {
	void prepare();//准备
	
	void kneadFlour();//和面
	
	void steamed();//蒸面
	
	void process();//处理
	
}
  • 正常的馒头的生产
package waking.test.zs;
/**
 * 正常实现馒头
 * @author waking
 *
 */
public class NormaIBread implements IBread {

	@Override
	public void prepare() {
		System.out.println("开始准备工作、、、、");
	}

	@Override
	public void kneadFlour() {
		System.out.println("开始和面、、、、、");
	}

	@Override
	public void steamed() {
		System.out.println("开始蒸馒头、、、、");
	}

	@Override
	public void process() {
		prepare();
		kneadFlour();
		steamed();
	}

}
  • 抽象类加工馒头
package waking.test.zs;
/**
 * 加工馒头抽象类
 * @author waking
 *
 */
public abstract class AbstIBread implements IBread{
	private final IBread iBread;

	public AbstIBread(IBread iBread) {
		super();
		this.iBread = iBread;
	}
	
	//重写准备方法
	@Override
	public void prepare() {
		this.iBread.prepare();
	}
	
	//重写和面方法
	@Override
	public void kneadFlour() {
		this.iBread.kneadFlour();
	}
	
	//重写蒸馒头方法
	@Override
	public void steamed() {
		this.iBread.steamed();
	}
	
	//重写最后处理工作
	
	@Override
	public void process() {
		prepare();
		kneadFlour();
		steamed();
	}
}
  • 添加糖
package waking.test.zs;
/**
 * 甜馒头
 * @author waking
 *
 */
public class SweetDecorator extends AbstIBread{

	public SweetDecorator(IBread iBread) {
		super(iBread);
	}
	
	public void sweet() {
		System.out.println("加点糖、、、、");
	}
	
	//添加糖
	@Override
	public void kneadFlour() {
		this.sweet();
		super.kneadFlour();
	}
}
  • 添加玉米面
package waking.test.zs;
/**
 * 玉米馒头
 * @author waking
 *
 */
public class CornDecorator extends AbstIBread {

	public CornDecorator(IBread iBread) {
		super(iBread);
	}
	
	public void addCorn() {
		System.out.println("添加玉米、、、");
	}
	
	@Override
		public void kneadFlour() {
			this.addCorn();
			super.kneadFlour();
		}

}
  • 测试类
package waking.test.zs;

import org.junit.Test;

/**
 * 测试类
 * @author waking
 *
 */

public class Tests {
	
	@Test
	public void Test1() {
		System.out.println("开始装饰馒头、、、");
		IBread iBread = new NormaIBread();
		//添加糖
		iBread = new SweetDecorator(iBread);
		//添加玉米面
		iBread = new CornDecorator(iBread);
		iBread.process();
		System.out.println("装饰完毕");
	}
}

  • 结果
开始装饰馒头、、、
开始准备工作、、、、
添加玉米、、、
加点糖、、、、
开始和面、、、、、
开始蒸馒头、、、、
装饰完毕
总结
  • 意图:动态的给一个对象添加一些额外的职责。就增加功能来说,装饰者模式相比子类更灵活
  • 主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀
  • 优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能
  • 缺点:多层修饰比较复杂
  • 使用场景:
    • 扩展一个类的功能
    • 动态增加功能,动态撤销
  • 注意事项:可以替代继承
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!