设计模式初探之装饰模式

之前已经带来两种模式的探究分别为如下,有兴趣的小伙伴可以去看看。

简单工厂模式:http://blog.csdn.net/zsw1017/article/details/78232073

策略模式http://blog.csdn.net/zsw1017/article/details/78310151

一、定义

       今天将带来另一种模式的探究,这种模式就是装饰模式,首先我们先看看装饰模式的定义:

        修饰模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。(维基百科)

       1、这个定义中有几个关键点,动态的,这个点是类继承所不具备的,类的继承在我们实现继承的时候就已经确定了增加的功能。而装饰模式可以在客户代码过程决定新增哪些行为,甚至是新增行为的顺序。

       2、添加新的行为,这个点跟生成子类是一个共同点,子类就是在父类的基础上进行扩展,说明这种装饰模式在某种程度上是可以替代继承,实现对类功能的扩展。

       3、灵活,体现在第一点的动态增加,还可以决定增加的顺序。

看完这个定义是不是有点懵,不要紧,先抛开定义,接着往下看。

二、UML类图


装饰模式的类图可以看到,待装饰类、装饰类是有共同的接口Component,这个Component在我看来

确定了待装饰类可扩展的方法具体的装饰类ConcreteDecoratorA、ConcreteDecoratorB,有一个父类,这

个父类中持有Component引用,这个就是用于存放待装饰类对象。有了待装饰类的对象,就可调用待装饰

类的方法(原有功能),并扩展方法。

具体装饰类ConcreteDecoratorA用于具体扩展行为的实现。
装饰模式就是这样,通过新增装饰类,在装饰类内持有待装饰类对象引用,即包裹待装饰类对象,扩

展待装饰对象。看到这里,你是对装饰模式有更清晰的理解,还是更懵。如果有了进一步的了解,别急着离

开,看个例子巩固一下。如果你更迷糊了,那你肯定更不能此刻离开,看一个例子,再回来看看前面的定

义,还有uml类图,你很可能就能理解了。

三、例子

我们用这个场景,我们要做一个蛋炒饭,分别得往锅里放,饭,鸡蛋,盐,我们就把放食材这些动作
当做行为,在 原来锅里 什么都没有的情况下,增加这些食材。
首先得有一个Component,这个接口定义了可扩展的方法。
public interface Component {

	/**
	 * 添加食材
	 */
	public void addIngredient();
}
接下来是待装饰类,这是一个锅,里面什么都没有,哈哈。
public class Friedrice implements Component {

	@Override
	public void addIngredient() {
		// TODO Auto-generated method stub
		System.out.println("做一道传统美食,蛋炒饭");
	}

}
装饰父类,这里持有了待装饰类的引用,用于调用原有功能。
public class Decorator implements Component{

	private Component waitForDecorator;//待装饰对象
	
	public Decorator(Component waitForDecorator) {
		super();
		this.waitForDecorator = waitForDecorator;
	}

	@Override
	public void addIngredient() {
		// TODO Auto-generated method stub
		waitForDecorator.addIngredient(); //调用原来待装饰类已有功能
	}

}
接下来就是具体装饰类,加入大米饭。具体的装饰行为,即新增扩展功能
public class AddRice extends Decorator {

	public AddRice(Component waitForDecorator) {
		super(waitForDecorator);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void addIngredient() {
		// TODO Auto-generated method stub
		super.addIngredient(); //这里是关键,调用待装饰对象的方法
		System.out.println("将大米饭放入锅中"); //扩展,有没有?
	}

}
具体装饰类,加入鸡蛋。
public class AddEgg extends Decorator{

	public AddEgg(Component waitForDecorator) {
		super(waitForDecorator);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void addIngredient() {
		// TODO Auto-generated method stub
		super.addIngredient();
		System.out.println("往锅中加入鸡蛋");
	}

}
具体装饰类,加入盐。
public class AddSalt extends Decorator{

	public AddSalt(Component waitForDecorator) {
		super(waitForDecorator);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void addIngredient() {
		// TODO Auto-generated method stub
		super.addIngredient();
		System.out.println("往锅中加入盐");
	}
	
}
接下来就是客户端调用了。
public class TestClass {

	public static void main(String arg[]){
		Friedrice food = new Friedrice();
		AddRice addRice = new AddRice(food);//加入大米饭
		AddSalt addSalt = new AddSalt(addRice);//加入盐
		AddEgg addEgg = new AddEgg(addSalt);//加入鸡蛋
		addEgg.addIngredient();
	}
}

运行结果:

什么???你说你非要先加盐,再加饭??随你吧,反正这难不倒装饰模式,将客户端代码修改为如下。
public class TestClass {

	public static void main(String arg[]){
		Friedrice food = new Friedrice();
		AddSalt addSalt = new AddSalt(food);
		AddEgg addEgg = new AddEgg(addSalt);
		AddRice addRice = new AddRice(addEgg);
		addRice.addIngredient();
	}
}


这例子就是装饰模式啦,Friedrice:待装饰类、Component:装饰类待装饰类的共同接口、Decorator:
装饰 类父类、AddSalt,AddRice,AddEgg:具体的装饰类。 Friedrice的addIngredient扩展为加米饭,加鸡
蛋,加 盐。这些动作的顺序也能随时灵活更换。
到这里,你是不是对装饰模式有个大概的了解了??那就多看几遍,哈哈。顺便说下,java提供的io操作
其实也是用到了装饰模式。

四、总结

1、装饰模式是一种用于扩展类功能的设计模式,是一种包裹模式,将待装饰类包裹在装饰类中,在装饰类中
扩展待装饰类。
2、装饰模式相对生成子类的扩展类功能来说,具有动态,灵活等特点。
3、具体的装饰对象只需完成自己的行为,而不需要知道其他具体装饰对象。他们不需要知道对方的存在。只
需专注于自己要扩展的行为。




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值