是什么?
场景案例:想必大家都吃过手抓饼吧,我们在点手抓饼的时候可以选择加培根、鸡蛋、火腿、肉松等等这些配菜,当然这些配菜的价格都不一样,那么计算总价就比较麻烦;
装饰者模式就是指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即额外功能);
结构
抽象构件:定义一个抽象接口以规范准备接收附加责任的对象;
具体构件:实现抽象构件,通过装饰角色为其添加一些职责;
抽象装饰:继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能;
具体装饰:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任;
实现
通过继承
抽象构件
public abstract class HandGraspStore {
//手抓饼店铺==>抽象构建
private float price;
private String desc;
public HandGraspStore() {
}
public HandGraspStore(float price, String desc) {
this.price = price;
this.desc = desc;
}
public Float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public abstract float cost();
}
具体构件
public class HandGraspCake extends HandGraspStore{
//手抓饼===>具体构件
public HandGraspCake() {
super(10,"手抓饼");
}
@Override
public float cost() {
return super.getPrice();
}
}
抽象装饰
public abstract class Decorator extends HandGraspStore {
//抽象装饰
private HandGraspStore handGraspStore;
public HandGraspStore getHandGraspStore() {
return handGraspStore;
}
public void setHandGraspStore(HandGraspStore handGraspStore) {
this.handGraspStore = handGraspStore;
}
public Decorator(HandGraspStore handGraspStore,float price,String desc) {
super(price,desc);
this.handGraspStore=handGraspStore;
}
}
具体装饰
public class Egg extends Decorator{
//鸡蛋===>具体装饰
public Egg(HandGraspStore handGraspStore) {
super(handGraspStore,1,"加一个鸡蛋");
}
@Override
public float cost() {
return getPrice()+ getHandGraspStore().cost();
}
@Override
public String getDesc() {
return super.getDesc()+getHandGraspStore().getDesc();
}
}
public class Ham extends Decorator{
//培根===>具体装饰
public Ham(HandGraspStore handGraspStore) {
super(handGraspStore,3,"加一个火腿");
}
@Override
public float cost() {
return getPrice()+ getHandGraspStore().cost();
}
@Override
public String getDesc() {
return super.getDesc()+getHandGraspStore().getDesc();
}
}
用户使用
public class Customer {
public static void main(String[] args) {
HandGraspCake handGraspCake = new HandGraspCake();
System.out.println(handGraspCake.getDesc()+handGraspCake.getPrice()+"元");
System.out.println("==============================");
Egg egg = new Egg(handGraspCake);
System.out.println(egg.getDesc()+egg.cost()+"元");
System.out.println("===============================");
Ham ham = new Ham(egg);
System.out.println(ham.getDesc()+ham.cost()+"元");
}
}
通过接口
抽象构件
public interface IHandGraspCakeStore {
float price();
String desc();
float cost();
}
具体构件
public class IHandGraspStore implements IHandGraspCakeStore {
@Override
public float price() {
return 10;
}
@Override
public String desc() {
return "手抓饼";
}
@Override
public float cost() {
return price();
}
}
抽象装饰
public interface IDecoratorStore extends IHandGraspCakeStore {
}
具体装饰
public class IEggStore implements IDecoratorStore {
private IHandGraspCakeStore handGraspCake;
public IEggStore(IHandGraspCakeStore handGraspCake) {
this.handGraspCake=handGraspCake;
}
@Override
public float price() {
return 1;
}
@Override
public String desc() {
return handGraspCake.desc()+"加鸡蛋";
}
@Override
public float cost() {
return price()+ handGraspCake.cost();
}
}
用户使用
public class ICustomerDemo {
public static void main(String[] args) {
IHandGraspStore iHandGrasp = new IHandGraspStore();
System.out.println(iHandGrasp.desc()+iHandGrasp.cost()+"元");
System.out.println("================================");
IEggStore iEgg = new IEggStore(iHandGrasp);
System.out.println(iEgg.desc()+iEgg.cost()+"元");
IEggStore eg = new IEggStore(iEgg);
System.out.println(eg.desc()+eg.cost()+"元");
}
}
我们可以发现,这其实是一个反向控制,也就是说用户最终得到的是一个具体装饰类,而非我们的具体构建类,因为最终的金额计算或者说其他的操作逻辑,都是在具体装饰中进行统计并完成的;
优点
1.装饰者模式可以带来比继承更加灵活性的扩展功能,使用更加方便,可以通过组合不同的装饰者对象来获取具有不同行为状态的多样化的结果,装饰者模式比继承更具有良好的扩展性,完美的尊姓开闭原则,继承是静态的附加责任,装饰者则是动态的附加责任;
2.装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能;
使用场景
1.当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时;
不能采用继承的情况主要有以下两种:
第一种是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;
第二种是因为类不能继承(例如final类)
2.在不影响其他对象的情况下,需要以动态、透明的方式给单个对象添加职责;
3.当对象的功能要求可以动态地添加,也可以再动态地撤销时;