设计模式-装饰模式

一、概念

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

二、结构图


三、使用场景

1. 需要扩展一个类的功能,或给一个类添加附加职责。
2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

四、实例一

    饮料店里卖多种饮品,有可乐、啤酒、奶茶等等。

1、先建一个component

/**
 * <p>标题:Drinks  </p>
 * <p>描述: 饮料接口</p>
 */
public abstract class Drinks {
	
	String name;
	
	public abstract int price();
	
	public String getName(){
		return name;
	}
}

2、建三个concreteComponent

(1)、奶茶实现类

/**
 * <p>标题: MilkyTeaComponent</p>
 * <p>描述: 奶茶实现类</p>
 */
public class MilkyTeaComponent extends Drinks{
	
	/**
	 * @Title:构造方法   
	 */
	public MilkyTeaComponent() {
		name="奶茶";
	}
	
	/*
	 * 奶茶的价格  
	 */
	@Override
	public int price() {
		return 10;
	}
}

(2)、可乐实现类

/**
 * <p>标题: ColaComponent</p>
 * <p>描述: 可乐实现类</p>
 */
public class ColaComponent extends Drinks{
	
	/**
	 * @Title:构造方法   
	 */
	public ColaComponent() {
		name="可乐";
	}
	
	/*
	 * <p>描述:可乐价格 </p>   
	 */
	@Override
	public int price(){
		return 5;
	}
}

(3)、啤酒实现类

/**
 * <p>标题: BeerComponent</p>
 * <p>描述: 啤酒实现类</p>
 */
public class BeerComponent extends Drinks{

	/**
	 * @Title:构造方法   
	 */
	public BeerComponent() {
		name="啤酒";
	}
	
	/*
	 * <p>啤酒的价格</p>   
	 */
	@Override
	public int price() {
		return 3;
	}
}

3、创建Decorator

/**
 * <p>标题: Decorator</p>
 * <p>描述:装饰抽象类 </p>
 */
public abstract class Decorator extends Drinks{

	protected Drinks drinks;
	public Decorator(Drinks yp){
		this.drinks=yp;
	}
}

4、创建concreteDecorator

(1)、加冰饮料

/**
 * <p>标题: IceDecorator</p>
 * <p>描述: 加冰饮料</p>
 */
public class IceDecorator extends Decorator{

	/**
	 * @Title:构造方法   
	 * @param drinks
	 */
	public IceDecorator(Drinks drinks) {
		super(drinks);
	}

	public void 加冰(){
		System.out.println("饮料加冰,夏天喝最爽口哦");
	}
	
	/*
	 * <p>描述:加冰饮料的价格,比普通饮料贵三块</p>   
	 */
	@Override
	public int price() {
		return 3+drinks.price();
	}
	
	/*
	 * <p>描述: 饮料名</p>   
	 * @return   
	 */
	@Override
	public String getName() {
		加冰();
		return "加了冰的"+ drinks.getName();
	}
}

(2)、加水饮料

/**
 * <p>标题: Water水Decorator</p>
 * <p>描述: 加水饮料</p>
 */
public class WaterDecorator extends Decorator{

	/**
	 * @Title:构造方法
	 * @param drinks
	 */
	public WaterDecorator(Drinks drinks) {
		super(drinks);
	}
	
	public void 兑水(){
		System.out.println("饮料兑水。。。");
	}

	/*
	 * <p>加水饮料价格,比普通饮料贵2块 </p>   
	 */
	@Override
	public int price() {
		return 2+drinks.price();
	}

	/*
	 * <p>饮料名</p>   
	 */
	@Override
	public String getName() {
		兑水();
		return "对了水的"+drinks.getName();
	}
}

5、测试

public static void main(String[] args) {
		Drinks drink1=new ColaComponent();
		drink1=new WaterDecorator(drink1);
		System.out.println("饮品名:"+drink1.getName()+";价格:"+drink1.price());
		
		Drinks drink2=new BeerComponent();
		drink2=new IceDecorator(drink2);
		System.out.println("饮料名:"+drink2.getName()+";价格:"+drink2.price());
		
		Drinks drink3=new MilkyTeaComponent();
		drink3=new IceDecorator(drink3);
		System.out.println("饮料名:"+drink3.getName()+";价格:"+drink3.price());
				
	}

运行结果:

饮料兑水。。。
饮品名:对了水的可乐;价格:7
饮料加冰,夏天喝最爽口哦
饮料名:加了冰的啤酒;价格:6
饮料加冰,夏天喝最爽口哦
饮料名:加了冰的奶茶;价格:13

五、实例二

人穿衣服,不同的搭配是不同的装饰。

1、创建concreteDecorator,由于只有一个创建concreteDecorator,因此不需要抽象component

/**
 * <p>标题: Person</p>
 * <p>描述: 具体的concreteComponent,由于只有个concreteComponent,因此不需要创建Component</p>
 */
public class Person {

	public Person(){}
	
	private String name;
	public Person(String name){
		this.name=name;
	}
	
	public void show(){
		System.out.println("装扮的:"+name);
	}
}

2、创建Decorator:Finery

/**
 * <p>标题: Finery</p>
 * <p>描述: 装饰类</p>
 */
public class Finery extends Person{
	protected Person person;
	
	public Finery(Person person){
		this.person=person;
	}
	
	/*
	 * <p>展示</p> 
	 */
	@Override
	public void show() {
		person.show();
	}
}
3、创建concreteDecorator

(1)、T恤

/**
 * <p>标题: TShirt</p>
 * <p>描述: T恤</p>
 */
public class TShirt extends Finery{

	/**
	 * @Title:构造方法   
	 * @param person
	 */
	public TShirt(Person person) {
		super(person);
	}

	/*
	 * <p>描述: 展示 </p>      
	 */
	@Override
	public void show() {
		System.out.println("穿T-shirt");
	}
}

(2)、短裤

/**
 * <p>标题: BigTrouser</p>
 * <p>描述: 短裤</p>
 */
public class BigTrouser extends Finery{

	/**
	 * @Title:构造方法   
	 * @param person
	 */
	public BigTrouser(Person person) {
		super(person);
	}

	/*
	 * <p>描述:展示</p>      
	 */
	@Override
	public void show() {
		System.out.println("穿短裤");
	}
}

(3)、西装

/**
 * <p>标题: WearSuit</p>
 * <p>描述: 西装</p>*/
public class WearSuit extends Finery{

	/**
	 * @Title:构造方法   
	 * @param person
	 */
	public WearSuit(Person person) {
		super(person);
	}

	/*
	 * <p>描述:展示 </p>      
	 */
	@Override
	public void show() {
		System.out.println("西装");
	}
}

4、测试

public static void main(String[] args) {
		Person person=new Person("小明");
		Finery tshirts=new TShirt(person);
		Finery bigTrouser=new BigTrouser(person);
		tshirts.show();
		bigTrouser.show();
		person.show();
	}

运行结果:

穿T-shirt
穿短裤
装扮的:小明

六、装饰模式的优点

    装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。通过使用装饰模式,设计者可以设计出不同的组合。

七、装饰模式的缺点

  由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值