装璜者模式
结构型模式
装璜者模式(Decorator Pattern)容许向一个现有的对象增加新的性能,同时又不扭转其构造。它是作为现有的类的一个包装。
这种模式创立了一个装璜类,用来包装原有的类,并在放弃类办法签名完整性的前提下,提供了额定的性能。
介绍
用意: 动静地给一个对象增加一些额定的职责。就减少性能来说,装璜者模式相比生成子类更为灵便。
次要解决: 个别的,咱们为了扩大一个类常常应用继承形式实现,因为继承为类引入动态特色,并且随着扩大性能的增多,子类会很收缩。
何时应用: 在不想减少很多子类的状况下扩大类。
如何解决: 将具体性能职责划分,同时继承装璜者模式。
要害代码: 1、Component 类充当形象角色,不应该具体实现。 2、润饰类援用和继承 Component 类,具体扩大类重写父类办法。
利用实例: 1、孙悟空有 72 变,当他变成”庙宇”后,他的基本还是一只猴子,然而他又有了庙宇的性能。 2、不管一幅画有没有画框都能够挂在墙上,然而通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画能够被蒙上玻璃,装到框子里;这时画、玻璃和画框造成了一个物体。
具体实现
依据一个咖啡厅卖饮料和调味品的问题来解决。
第一步:创立形象Drink类
public abstract class Drink {
/**
* 形容
*/
private String des;
/**
* 价格
*/
private float price = 0.0f;
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
//计算费用的形象办法
public abstract float cost();
}
第二步:创立Coffee类
public class Coffee extends Drink {
@Override
public float cost() {
return super.getPrice();
}
}
第三步:创立不同单品咖啡
public class Espresso extends Coffee {
public Espresso() {
setDes("意大利咖啡");
setPrice(6.0f);
}
}
public class LongBlack extends Coffee {
public LongBlack() {
setDes("LongBlack");
setPrice(5.0f);
}
}
public class ShortBlack extends Coffee {
public ShortBlack() {
setDes("ShortBack");
setPrice(4.0f);
}
}
第四步:创立装璜者
public class Decorator extends Drink {
private Drink obj;
public Decorator(Drink obj) {
this.obj = obj;
}
@Override
public float cost() {
return getPrice() + obj.cost();
}
@Override
public String getDes() {
return super.getDes() + " " + getPrice() + " && " + obj.getDes();
}
}
第五步:创立不同的调味品
public class Chocolate extends Decorator {
public Chocolate(Drink obj) {
super(obj);
setDes("巧克力");
/**
* 调味品的价格
*/
setPrice(3.5f);
}
}
public class Milk extends Decorator {
public Milk(Drink obj) {
super(obj);
setDes("牛奶");
setPrice(2.0f);
}
}
public class Soy extends Decorator{
public Soy(Drink obj) {
super(obj);
setDes("豆浆");
setPrice(1.5f);
}
}
第五步:创立测试类
public class CoffeeBar {
public static void main(String[] args) {
//装璜着模式下的订单:2份巧克力+1份牛奶的LongBlack
//1.点一份LongBlack
Drink order = new LongBlack();
System.out.println("费用=" + order.cost());
System.out.println("形容=" + order.getDes());
//2.退出一份牛奶
order = new Milk(order);
System.out.println("order 退出一份牛奶 费用=" + order.cost());
System.out.println("order 退出一份牛奶 形容=" + order.getDes());
//3.退出一份巧克力
order = new Chocolate(order);
System.out.println("order 退出一份牛奶 又退出一份巧克力 费用=" + order.cost());
System.out.println("order 退出一份牛奶 又退出一份巧克力 形容=" + order.getDes());
//4.再退出一份巧克力
order = new Chocolate(order);
System.out.println("order 退出一份牛奶 又退出一份巧克力 又退出一份巧克力 费用=" + order.cost());
System.out.println("order 退出一份牛奶 又退出一份巧克力 又退出一份巧克力 形容=" + order.getDes());
}
}
运行后果如下:
费用=5.0
形容=LongBlack
order 退出一份牛奶 费用=7.0
order 退出一份牛奶 形容=牛奶 2.0 && LongBlack
order 退出一份牛奶 又退出一份巧克力 费用=10.5
order 退出一份牛奶 又退出一份巧克力 形容=巧克力 3.5 && 牛奶 2.0 && LongBlack
order 退出一份牛奶 又退出一份巧克力 又退出一份巧克力 费用=14.0
order 退出一份牛奶 又退出一份巧克力 又退出一份巧克力 形容=巧克力 3.5 && 巧克力 3.5 && 牛奶 2.0 && LongBlack
阐明:
1、Milk蕴含了LongBlack
2、一份Chocolate蕴含了(Milk+LongBlack)
3、一份Chocolate蕴含了(Chocolate+Milk+LongBlack)
4、这样不论是什么模式的单品咖啡+调料组合,通过递归的形式不便组合和保护。
长处:
1、在该案例中,如果咱们想再增加一种咖啡只须要继承Coffee即可,2、装璜类和被装璜类能够独立倒退,不会互相耦合,装璜模式是继承的一个代替模式,装璜模式能够动静扩大一个实现类的性能。
毛病:
多层装璜比较复杂。