设计模式初探之二------使用装饰者模式

4 篇文章 0 订阅
4 篇文章 0 订阅

上篇博文是对工厂模式的一点理解和示例演示。后续发现其中使用的例子可以使用装饰者模式进行优化。


装饰者模式:23种设计模式之一,英文叫DecoratorPattern,又叫装饰者模式。装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

所谓装饰者,可以在不改变原有代码的前提,拓展一个对象的功能。


先前的项目中有个pizza。

pizza:不同的pizza继承pizza超类,并拓展超类,加上不同的材料成为不同的pizza(番茄肉饼pizza,芝士pizza)

但是这样子就存在一个明显的不足,因为pizza的种类从某种意义上来说应该是可以无限拓展了,可以引入不同的材料,更新款式。


分析pizza类的组成,发现其很适合采用装饰者模式。

Pizza有最基本的Dough(面饼),加上诸如芝士、番茄、火腿等佐料组合而成,可以把面饼作为最基本的被装饰者,而各种佐料作为装饰者,通过采用不同佐料来修饰面饼来达到拓展面饼变成不同pizza的目的。


1、首先,使用一个超类,是的装饰者和被装饰者都继承此类,目的是保持后面对象被装饰者修饰了之后仍然属于同一个超类对象。

/*
 * 原材料的超类
 */
public abstract class Ingredient {
	protected String name = "Unknown ingredient";  //材料名称
	protected String description = "Unknown ingredient";  //说明
	protected Double price = 0.0;  //材料价格
	String getName() {
		return name;
	}
	public abstract double cost();
	public String getDescription(){
		return description;
	}
	void setPrice(Double price) {
		this.price = price;
	};
}

2、创建被装饰者,其具有材料超类的属性。

/*
 * 面团的超类
 */
public abstract class Dough extends Ingredient{
	
	public Dough(String name) {
		this.name = name;
		this.description = "SimpleDough";
	}
}

3、创建修饰者超类,修饰者超类定义了一个修饰者该有的属性,其需要维护一个被修饰者对象。

/*
 * 修饰者 佐料
 */
public abstract class Jardiniere extends Ingredient {

	Ingredient ingredient;
	
	public Jardiniere(String name, Ingredient ingredient) {
		super();
		this.name = name;
		this.ingredient = ingredient;
	}
	
	@Override
	public double cost() {
		// TODO Auto-generated method stub
		return ingredient.cost() + this.price;
	}
	@Override
	public String getDescription(){
		return ingredient.getDescription() + ", " + this.name;
	};
	@Override
	public void setPrice(Double price) {
		this.price = price;
	}
}
注意修饰者类重定义了cost方法和getDescription方法。因为当增加一个佐料的时候,这块pizza的价格是在原先的价格上进行累加,description的原理类似。

4、创建各种佐料,如cheese(芝士)

/*
 * 奶酪
 */
public abstract class Cheese extends Jardiniere{

	public Cheese(String name, Ingredient ingredient) {
		super(name, ingredient);
	}
}

5、材料都准备好了,使用装饰者模式来创建pizza(此处还使用了工厂模式)

/*
 * the Ingredient factory of NewYork
 * use ThinCrustDough, MarinaraSauce, ReggianoCheese, Garlic and so on
 */
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {

	@Override
	public Dough createDough() {
		// TODO Auto-generated method stub
		System.out.println("拿点从NewYork的pizza原料工厂买来的薄皮面团");
		return new ThinCrustDough();
	}

	@Override
	public Sauce createSauce(Ingredient ingredient) {
		// TODO Auto-generated method stub
		System.out.println("拿点从NewYork的pizza原料工厂买来的海鲜酱");
		return new MarinaraSauce(ingredient);
	}

	@Override
	public Cheese createCheese(Ingredient ingredient) {
		// TODO Auto-generated method stub
		System.out.println("拿点从NewYork的pizza原料工厂买来的巴马干酪");
		return new ReggianoCheese(ingredient);
	}

	@Override
	public Veggies createVeggies(Ingredient ingredient) {
		// TODO Auto-generated method stub
		System.out.println("来点蔬菜,蒜头,洋葱,蘑菇,红辣椒");
		Veggies veggies = new Garlic(ingredient);
		veggies = new Onion(veggies);
		veggies = new Mushroom(veggies);
		veggies = new RedPepper(veggies);
		return veggies;
	}
}

6、我们看看如何使用修饰者来生产一个pizza

/*
 * 芝士pizza
 */
public class CheesePizza extends Pizza {

	PizzaIngredientFactory ingredientFactory;
	
	public CheesePizza(PizzaIngredientFactory ingredientFactory) {
		super();
		this.ingredientFactory = ingredientFactory;
	}

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		System.out.println("准备"+name+"所需原材料 ");
		Ingredient ingredient = ingredientFactory.createDough();
		ingredient = ingredientFactory.createSauce(ingredient);
		ingredient = ingredientFactory.createCheese(ingredient);
		this.ingredient = ingredient;
	}

}

这里用到了工厂模式,但是不管这个先,我们看看如何使用修饰者来修饰一个对象。

制作cheesePizza时,我们需要创建一个面饼对象(createDough),然后使用海鲜酱(createSauce)和芝士(createCheese)作为佐料。

注意1:使用createSauce时,实际上是调用NYPizzaIngredientFactory对象新建了一个Sauce类(这就是装饰者模式),并将被装饰者(面饼对象)作为参数传入。

注意2:因为所有装饰者、被装饰者都有一个共同的超类,可以保证对象被装饰后不会发生类型变化。


完整代码见:https://github.com/markey92/HeadFirstPizza/tree/PizzaUseDecoratorPattern


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值