设计模式之装饰者模式

装饰者模式的概念

装饰者模式的基本形式:把一个类对象的引用作为参数传入另一个类的对象的构造方法中,然后以此类推,形成一条引用链,实现对象的多层包装,实现了把有限的类包装成众多有复杂功能的类,实现更多丰富的功能。
Java中的例子:在Java中比较常见的装饰者模式是Java的util包中的IO类库,比如IO字节流的超类InputSream可以包装为文件字节流FileInputStream,缓冲输入流BufferedInputStream等多种类,实现一些特殊的功能。

装饰者模式的原则

类应该对扩展开放,对修改关闭:对扩展开放和对修改关闭这个概念看似矛盾,其实并不矛盾,对扩展开放是指,代码有适应未来在使用中不断更新和变化的能力;对修改关闭是指,Java代码在编写完之后就应该尽量避免修改,因为一旦修改源代码,可能会对原本的代码结构造成破坏,之前辛辛苦苦调的bug可能也前功尽弃了。在编写代码的时候,我们应该尽量避免写“硬代码”,把那些稳定的代码保护起来,把需要修改的部分独立出来。代码的扩展性可以通过后期增删独立出来的类实现,运用装饰者模式的设计理念,可以在外部实现不同的包装层次,获得不同的功能和属性,这样代码的扩展性很强,在实现不同包装的时候也没有修改代码。

咖啡厅点餐(装饰者模式)

写一个咖啡厅的点餐代码。
实现的功能
1、可以选择饮料的种类和大、中、小杯。
2、可以选择添加的配料及其数量。
3、输出具体点单信息和总价格。
一、饮料(抽象类)

public abstract class Drink {	
	public abstract String getName();
	public abstract void setName(String name);
	public abstract int getPrice();
	public abstract void setPrice(int price);
}

二、配料(抽象类)

public abstract class Decorator extends Drink {	
	public abstract String getName();
	public abstract void setName(String name);
	public abstract int getPrice();
	public abstract void setPrice(int price);	
}

三、咖啡类(一种饮料)

public class Coffee extends Drink{
	private String name;
	private int price;
	private String size; 	
	public Coffee(String size){
		this.size=size;
		name="咖啡加";
		price=20;
	}
	public void setName(String name){
		this.name=name;
	}	
	public String getName(){
		return size+name;
	}			
	public void setPrice(int price){
		this.price=price;
	}	
	public int getPrice(){
		return price;
	}	
	public void setSize(String size){
		this.size=size;
	}	
	public String getSize(){
		return size;
	}	
}

四、摩卡(一种配料)

public class Mocha extends Decorator{
    Drink drink;
	private String name;
	private int price;
	private String count;
	public Mocha(Drink drink,String count){
		this.drink=drink;
		this.count=count;
		name="摩卡";
		price=5;
	}	
	public Mocha(Drink drink){
		this.drink=drink;
		this.count="";
		name="摩卡";
		price=5;
	}
	public String getName() {		
		return drink.getName()+count+name;
	}
	public void setName(String name) {
		this.name=name;
	}
	public int getPrice() {		
		return drink.getPrice()+price;
	}	
	public void setPrice(int price) {
        this.price=price;
	}
}

五、糖(一种配料)

public class Sugar extends Decorator{
    Drink drink;
	private String name;
	private int price;
	private String count;	
	public Sugar(Drink drink,String count){
		this.count=count;
		this.drink=drink;
		name="糖";
		price=3;
	}	
	public Sugar(Drink drink){
		this.count="";
		this.drink=drink;
		name="糖";
		price=3;
	}	
	public String getName() {		
		return drink.getName()+count+name;
	}
	public void setName(String name) {
		this.name=name;
	}
	public int getPrice() {		
		return drink.getPrice()+price;
	}	
	public void setPrice(int price) {
        this.price=price;
	}
}

六、奶泡(一种配料)

public class Whip extends Decorator{
    Drink drink;
	private String name;
	private int price;
	private String count;
	public Whip(Drink drink,String count){
		this.count=count;
		this.drink=drink;
		name="奶泡";
		price=7;
	}	
	public Whip(Drink drink){
		this.count="";
		this.drink=drink;
		name="奶泡";
		price=7;
	}	
	public String getName() {		
		return drink.getName()+count+name;
	}
	public void setName(String name) {
		this.name=name;
	}
	public int getPrice() {		
		return drink.getPrice()+price;
	}	
	public void setPrice(int price) {
        this.price=price;
	}
}

七、运行结果
第一杯饮料
点了一杯:小杯咖啡加少糖摩卡
价格是:28¥
第二杯饮料
点了一杯:中杯咖啡加奶泡双倍摩卡半糖
价格是:35¥
八、程序分析
1、实现效果:所有信息都在测试类中输入,可以根据任意的组合配出不同口味的饮料,输出了点单信息和价格。
2、包装的实现:通过对饮料类对象进行多层的配料对象包装,实现给出外层对象引用,得到所有对象的信息并组合输出。内存对象的引用通过外层对象的构造方法传入外层对象。
3、引用链:例如调用最外层对象的getPrice()方法,同时会调用其内一层对象的getPrice()方法,最终实现多层price的叠加。
4、继承:饮料都继承自饮料的抽象类,配料都继承自配料的抽象类,为了实现在包装时的自动转型,让配料类继承饮料类。

小结

装饰者模式使得基础类的任意组合方案得到实现,使得一个最终得到的对象集成了别的一些类的属性和方法,实现更加复杂的功能。装饰者模式的设计遵守了OO设计原则,在对源代码不修改的情况下实现了丰富的扩展功能。但它也有一些自身固有的不足,因为使用到了继承,限制了程序设计的灵活性,如果想要继承别的类,可能需要重新设计新的方案了。对象的包装确实可以实现功能和属性的复合,但是容易因为内容繁杂而不利于理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值