装饰模式

摘要

  本文通过简洁的模式描述,应用场景的详细代码实现,以及匹配的UML,详解介绍了装饰模式的原理及应用。本文可帮助读者快速掌握装饰模式,以便工作学习中使用装饰模式。

一、装饰模式

  在装饰家时,每个人都会选择自己喜欢的物品放在家里,有人喜欢放一副画,有人喜欢放一盆花,有人喜欢放一盘水果等等。所以装饰品让主体呈现不同的式样,同时装饰品并没有改变主体的本质。装饰品与主体之间是解耦的,随时添加、随时拆除装饰品对主体都没有影响。
  在我们代码中,一个类对象有时也需要不同的“呈现样式”,装饰品之间可以随意组合来修饰主体。比如苹果类,带保鲜膜的苹果,系礼品带的苹果、带水果篮的苹果,或者是带保鲜膜、系礼品带的苹果等等。在编程时,若把所有装饰品与主体的组合集合写成具体类,装饰品与主体耦合在一起,那么在增加一种装饰品时,又得写出很多具体类,对其它使用地方也会进行修改,比如先为苹果类增加一个修饰“送一个桃子”,那么就会去写带保鲜膜赠桃子的苹果,系礼品带赠桃子的苹果;带水果篮赠桃子的苹果;或者是带保鲜膜、系礼品带、赠桃子的苹果等等,增加一个修饰品,就增加了很多具体类,降低了代码的重用性,也违背了“开闭原则”。
  装饰模式就是用于解决上面问题的。装饰模式将装饰品分离出来,单独成为一个装饰类,装饰类修饰过的主体仍然是主体,所以装饰类与主体类要有共同的父类,而装饰具体类则是对装饰类的实现。装饰类中持有主体类的句柄,所以需要实现一个具体类时,就将主体类赋给装饰类即可。如苹果类赋给红色类得到红色苹果类,红色苹果类可以视为主体,将红色苹果类赋给保鲜膜类将得到带保鲜膜的红色苹果类。其它装饰品类似。

二、装饰模式的实现

2.1 场景设计

  KFC中有汉堡产品,同时客户可以选择加牛肉、加鱼肉,客户点完餐之后给出菜单并给出总金额。
  汉堡为主体,牛肉、鱼肉为装饰品。

2.2 代码实现

2.2.1 Hamburger 抽象主体类

package ft.patterns.decorator;

public abstract class Hamburger {
	protected String name;
	protected int price;
	
	public void setName(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
	
	public void setPrice(int price) {
		this.price = price;
	}
	public int getPrice() {
		return price;
	}
	
	public abstract int cost();
	public abstract String getMenu();
}

2.2.2 KFCHamburger 具体主体类

package ft.patterns.decorator;

public class KFCHamburger extends Hamburger{	
	KFCHamburger(){
		super.setName("KFC");
		super.setPrice(8);
	}

	@Override
	public int cost() {
		return super.getPrice();
	}

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

2.2.3 DecoratorHamburger 装饰抽象类

package ft.patterns.decorator;

public abstract class DecoratorHamburger extends Hamburger{
	
	private Hamburger hamburger;
	
	public DecoratorHamburger(Hamburger hamburger) {
		this.hamburger = hamburger;
	}

	public Hamburger getHamburger() {
		return hamburger;
	}

	public void setHamburger(Hamburger hamburger) {
		this.hamburger = hamburger;
	}
}

2.2.4 BeefHamburger 具体装饰类

package ft.patterns.decorator;

public class BeefForHamburger extends DecoratorHamburger{

	public BeefForHamburger(Hamburger hamburger) {
		super(hamburger);
		super.setPrice(10);
		super.setName("Beef");
	}

	@Override
	public int cost() {
		return super.getHamburger().cost()+super.getPrice();
	}

	@Override
	public String getMenu() {
		return super.getHamburger().getMenu() + " "+super.getName();
	}
}

2.2.5 FishHamburger 具体装饰类

package ft.patterns.decorator;

public class FishForHamburger extends DecoratorHamburger{
	public FishForHamburger(Hamburger hamburger) {
		super(hamburger);
		super.setPrice(5);
		super.setName("Fish");
	}

	@Override
	public int cost() {
		return super.getHamburger().cost()+super.getPrice();
	}

	@Override
	public String getMenu() {
		return super.getHamburger().getMenu() + " "+super.getName();
	}
}

2.2.6 Main 测试类

package ft.patterns.decorator;

public class Main {
	public static void main(String[] args) {
		Hamburger kfc = new KFCHamburger();
		System.out.println(kfc.getMenu());
		System.out.println(kfc.cost());
		
		kfc = new BeefForHamburger(kfc);
		System.out.println(kfc.getMenu());
		System.out.println(kfc.cost());
		
		kfc = new FishForHamburger(kfc);
		System.out.println(kfc.getMenu());
		System.out.println(kfc.cost());
	}
}

2.2.7 测试结果

KFC
8
KFC Beef
18
KFC Beef Fish
23

三、装饰模式的UML图

装饰器模式UML类图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值