设计模式——装饰者模式:婚纱照收费的简单实现

装饰者模式

在没必要改变原类文件和使用继承的状况下,动态地扩展一个对象的功能。它是经过建立一个包装对象,也就是装饰来包裹真实的对象。java

装饰者模式特色

  1. 装饰者和被装饰对象有相同的超类型。
  2. 你能够用一个或者多个装饰者包装一个对象。 
  3. 既然装饰者和被装饰对象有相同的超类型,因此在任何须要原始对象(被包装的)的场合,能够用装饰过的对象代替它。
  4. 装饰者能够在所委托被装饰者的行为以前与/或以后,加上本身的行为,以达到特定的目的。
  5. 对象能够在任什么时候候被装饰,因此能够在运行时动态的,不限量的用你喜欢的装饰者来装饰对象。

装饰者模式类图

从上图能够看出,装饰者和被装饰者拥有共同的父类Componet,为了方便后面的扩展,咱们加了一个装饰者父类Decorator,让Decorator去继承Componet,而后让众多装饰者去继承Decorator。设计模式

应用场景(婚纱照收费)

生活中符合装饰者模式的应用场景其实还挺多,就拿前阵子去拍婚纱照的经从来说吧,婚纱工做人员通常先会跟你总体说,拍什么样的场景,多少套衣服,怎么去收费,而后在不改变原有收费的前提下,会跟你说精修入册数量,每加一张,就加收多少钱。如今咱们来把这个分级收费模式抽象一下,假如说,咱们拍摄一张照片是40块钱,精修一张40块,入册10块。安插在装饰者模式中,照片自己就成了咱们说的被装饰者(ConcreteComponet),而精修和入册则符合咱们对装饰者的定义,分别为DecoratorA,DecoratorB。接下来咱们来实现一下这个应用场景的类图结构。ide

  照片自己 照片入册 照片精修
费用 40 10 40

场景(婚纱照收费)类图

Format为装饰者父类与WeddingPhoto(被装饰者)共同继承了Photo。IsPhotoAlbum(入册)与PhotoWithPs(精修)为装饰者,共同修饰WeddingPhoto。他们都拥有共同的行为cost(),用于计算出价格,description属性主要用于记录信息,方便查看实现结果,可要可不要。测试

代码实现

共同抽象父类

package decorate.base;
/**
 * 照片父类
 * @author vision
 */
public abstract class Photo {
	private String description="";
	
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	/**
	 * 价格
	 * @param price
	 * @return
	 */
	public abstract Double cost();

}

装饰者抽象父类

package decorate.format;

import decorate.base.Photo;
/**
 * Format(照片规格)装饰者,扩展自Photo父类
 * @author vision
 */
public abstract class Format extends Photo{
	/**
	 * 描述
	 * @param description
	 * @return
	 */
	public abstract String getDescription();
}

被装饰者(婚纱照)

package decorate;

import decorate.base.Photo;
/**
 * 被装饰者:婚纱照
 * @author vision
 */
public class WeddingPhoto extends Photo{
	
	public WeddingPhoto() {
		setDescription(getDescription()+"WeddingPhoto(婚纱照)");
	}
	@Override
	public Double cost() {
		return 40.0;
	}

}

装饰者(入册)

package decorate.format;

import decorate.base.Photo;
/**
 * 装饰者:照片是否入册
 * @author vision
 */
public class IsPhotoAlbum extends Format{
	private Photo photo;
	public IsPhotoAlbum(Photo photo) {
		this.photo=photo;
	}
	@Override
	public String getDescription() {
		return photo.getDescription()+"+IsPhotoAlbum(入册)";
	}

	@Override
	public Double cost() {
		// TODO Auto-generated method stub
		return 10.0+photo.cost();
	}

}

装饰者(精修)

package decorate.format;

import decorate.base.Photo;
/**
 * 装饰者:照片精修
 * @author vision
 */
public class PhotoWithPs extends Format{
	private Photo photo;
	
	public PhotoWithPs(Photo photo){
		this.photo=photo;
	}
	
	@Override
	public String getDescription() {
		return photo.getDescription()+"+PhotoWithPs(精修)";
	}
	/**
	 * 照片精修,每张多加40块
	 */
	@Override
	public Double cost() {
		return 40.0+photo.cost();
	}

}

测试类

package decorate;

import decorate.base.Photo;
import decorate.format.IsPhotoAlbum;
import decorate.format.PhotoWithPs;

public class TestClass {
	public static void main(String[] args) {
		Photo weddingPhoto=new WeddingPhoto();
		//精修
		PhotoWithPs photoWithPs=new PhotoWithPs(weddingPhoto);
		System.out.println("最终选择的照片为:"+photoWithPs.getDescription());
		System.out.println("最终单价为:"+photoWithPs.cost());
		//入册
		IsPhotoAlbum isPhotoAlbum=new IsPhotoAlbum(photoWithPs);
		System.out.println("最终选择的照片为:"+isPhotoAlbum.getDescription());
		System.out.println("最终单价为:"+isPhotoAlbum.cost());
	}
}

输出结果

备注

参考资料:《Head First 设计模式》this

相关文章:《设计模式——观察者模式:天气推送的两种实现》spa

《设计模式——策略模式:会员价格体系的简单实现.net

《福利送上,未满十八岁勿点》设计

相关文章
相关标签/搜索