Java设计模式之装饰模式

Java设计模式之装饰模式

要学习并理解Java I/O,那么首先要学习Java设计模式中的装饰设计模式。

顾名思义,装饰设计模式的核心概念为通过"装饰"来扩展原有类的功能,而不是通过继承。

其要解决的主要问题是:

在某些特定情况下,需要对原有类的功能进行扩展,扩展方式有很多类型,并且相互之间存在很多组合

如果采用继承的方式来实现这个需求,那么将会产生大量的子类,整个类设计的体系结构将显得十分臃肿。

装饰的思想是:在原有类的基础上,通过将原有类对象通过构造函数传入装饰类中,装饰类在原有类功能的基础上进行增强,提供增强功能。

需要注意的是:装饰类和被装饰类应该实现同样的接口(或至少继承自同一父类),装饰类中构造函数参数的类型应写成接口形式,以便利用多态的思想,

由接口调用方法时,执行的是具体实现子类的覆盖方法。从而形成一种连锁的、链式的装饰。


下面用一个具体的例子来说明:

/**
 * 具体被装饰者要实现的接口
 * 装饰类要与被装饰类实现同样的接口
 * @author Administrator
 *
 */
public interface Hamberger {
	public String getName();
	public float getPrice();
}

/**
 * 具体的被装饰类
 * 即被装饰主体是 ¥15.00 的 鸡腿堡
 * @author Administrator
 *
 */
public class ChickenHamberger implements Hamberger {
	@Override
	public String getName() {
		return "鸡腿堡";
	}
	@Override
	public float getPrice() {
		return 15.0f;
	}
}

/**
 * 定义一个装饰类
 * @author Administrator
 *
 */
public abstract class Decorator implements Hamberger {
	private Hamberger hamberger;
	public Decorator(Hamberger hamberger){
		this.hamberger = hamberger;
	}

	@Override
	public String getName() {
		return hamberger.getName();
	}
	@Override
	public float getPrice() {
		return hamberger.getPrice();
	}
}

/**
 * 定义一种具体的装饰
 * 鸡腿堡+生菜+¥5.0
 * @author Administrator
 *
 */
public class DecoratorA extends Decorator {


	public DecoratorA(Hamberger hamberger) {
		super(hamberger);
	}
	
	public String addLettuce(){
		return "加生菜";
	}
	
	public float addPrice(){
		return 5f;
	}


	@Override
	public String getName() {
		return super.getName()+addLettuce();
	}


	@Override
	public float getPrice() {
		return super.getPrice()+addPrice();
	}
}
/**
 * 定义一种具体的装饰
 * 鸡腿堡+生菜+¥2.0
 * @author Administrator
 *
 */
public class DecoratorB extends Decorator {

	public DecoratorB(Hamberger hamberger) {
		super(hamberger);
	}
	
	public String addPepper(){
		return "加辣椒";
	}
	
	public float addPrice(){
		return 2f;
	}

	@Override
	public String getName() {
		return super.getName()+addPepper();
	}

	@Override
	public float getPrice() {
		return super.getPrice()+addPrice();
	}
}
/**
 * 进行测试
 * @author Administrator
 *
 */
public class DecoratorTest {
	@Test
	public void test(){
		Hamberger hamberger = new ChickenHamberger();
		Decorator decorator = new DecoratorB(new DecoratorA(hamberger));
		String name = decorator.getName();
		float price = decorator.getPrice();
		System.out.println(name);
		System.out.println(price);
	}
}
结果是:

鸡腿堡加生菜加辣椒
22.0

可以看到,通过

Decorator decorator = new DecoratorB(new DecoratorA(hamberger));
这种方式,成功地对原来的”汉堡“,增加了”生菜“和”辣椒“,如果只需要加”生菜“或者”辣椒“中的一种、或者调整其顺序的话,也只需要在这行代码中更改要用的装饰类型,并根据需要调整顺序即可。

有必要对结果的产生过程做一个分析,以

String name = decorator.getName();
为例。

通过装饰抽象类Decorator来调用getName()方法,decorator引用类型变量指向的是DecoratorB装饰类对象,将调用DecoratorB中的getName()方法。

	public String getName() {
		return super.getName()+addPepper();
	}
要调用此方法,首先要调用其父类 Decorator的getName()方法,

	@Override
	public String getName() {
		return hamberger.getName();
	}
这里的hamberger对象指向的是 DecoratorB类型对象初始化时向其构造函数传入的DecoratorA的实例,即将执行DecoratorA的实例对象的getName()方法,

	@Override
	public String getName() {
		return super.getName()+addLettuce();
	}
同样的,也将执行 DecoratorA对象父类的getName()方法, DecoratorA类型对象初始化直接依赖的是ChickenHamberger对象,

通过构造函数向其父类传入的是ChickenHamberger对象,即此时父类的hamberger引用指向的是ChickenHamberger对象。

调用其getName()方法将打印”鸡肉堡“,然后执行addLettuce()方法,”加生菜“,最后执行addPepper()方法,加”辣椒“。


价格的过程也以此类推。


总结几点:

1、可以看到,采用装饰设计模式,在避免大量子类继承的同时,增加了灵活性与动态性。即,采用子类继承,必须预先想好要扩展的功能并写死!但是采用装饰设计模式

则大可不必,根据需要,选取合适的装饰进行组合即可。

2、同时,装饰设计模式可扩展性也很好,只需要继承抽象装饰基类,定义新的装饰类型即可。





























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值