装饰者模式
定义
:动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的代替方案。
装饰者模式遵循了OO设计原则:类应该对扩展开放,对修改关闭。
设计初衷:通常可以使用继承来
实现功能的拓展
,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性。同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的。如果扩展的功能有什么变动,我们就得修改源码。
这样也违反了 OO设计原则: 01.运行时扩展,远比编译时期的继承威力大。02.多用组合,少用继承。
下面这个例子帮助理解 装饰者模式的流程和作用:
现在我们需要出售一个汉堡并计算它的价格,它的价格主要是根据汉堡的价格+配料的价格。
注:代码未验证,如有bug自行修复,此处只是为了帮助理解装饰者模式。
汉堡基类 — 被装饰者
public abstract class Humburger {
protected String description;
pubic String getDescription(){
return description;
}
public abstract double cost();
}
鸡腿堡 – 被装饰者的初始化状态,有些自己的特征(汉堡是基类,而顾客点餐会点具体种类的汉堡)
public class ChickenHuburger extends Humburger{
public ChickenHuburger (){
description= "鸡腿堡";
}
@override
public double cost() {
return 8;
}
}
巨无霸堡
public class BigHumburger extends Humburger {
public BigHumburger(){
description = "巨无霸堡";
}
@override
public double cost(){
return 12;
}
}
配料基类
public abstract class Condiment extends Humburger{
public abstract String getDescription();
}
生菜(装饰者,用来对汉堡进行装饰) – 蔬菜可以对不同的多个种类的汉堡进行装饰
public class Lettuce extends Condiment{
Humburger humburger;
public Lettuce(Humburger humburger){
this.humburger = humburger;
}
@Override
public String getDescription() {
return humburger.getDescription()+" 加生菜";
}
@Override
public double cost() {
return humburger.cost()+1.5;
}
}
酱料(装饰者)
public class Sauce extends Condiment {
Humburger humburger;
public Sauce(Humburger humburger){
this.humburger = humburger;
}
@override
public String getDescription(){
return humburger.getDescription + " 加酱料";
}
@Override
public double cost() {
return humburger.cost()+2.0;
}
}
测试类
public class Test {
public static void main(String[] args) {
//鸡腿堡
Humburger humburger = new ChickenBurger();
System.out.println(humburger.getDescription()+" 价钱:"+humburger.cost());
//巨无霸堡
Humburger bigHumburger = new BigHumburger();
System.out.println(bigHumburger .getDescription()+" 价钱:"+bigHumburger .cost());
//鸡腿堡 + 生菜
Lettuce lettuce = new Lettuce(humburger);
System.out.println(lettuce.getDescription()+" 价钱:"+lettuce.cost());
//鸡腿堡 + 酱料
Sauce sauce = new Sauce (humburger);
System.out.println(sauce.getDescription()+" 价钱:"+sauce.cost());
//鸡腿堡 + 生菜 + 酱料
Sauce sauce2 = new Sauce (lettuce);
System.out.println(sauce2.getDescription()+" 价钱:"+sauce2.cost());
//巨无霸堡 + 生菜 + 酱料
Sauce sauce3 = new Sauce(new Lettuce(bigHumburger));
System.out.println(sauce3.getDescription()+" 价钱:"+sauce3.cost());
}
}
输出:
鸡腿堡 价钱:8.0
巨无霸堡 价格:12.0
鸡腿堡 加生菜 价钱:9.5
鸡腿堡 加酱料 价钱:10.0
鸡腿堡 加生菜 加酱料 价钱:11.5
巨无霸堡 加生菜 加酱料 价钱:15.5
重点总结
:
- 装饰者与被装饰者拥有共同的超类,继承的目的是继承类型,而不是行为。
- 你可以用一个或者多个装饰者包装一个对象。
- 因为装饰者和被装饰者对象有着相同的超类型,所以在任何需要原始对象(被包装)的场合,可以用装饰过的对象代替它。
- 对象可以在任何时候被装饰,所以可以在运行时动态的,不限量的用喜欢的装饰者来装饰对象。
缺点:使用装饰者模式。常常会造成设计中有大量的小类,会造成使用API程序员的困扰。
版权声明:本文为Archer_M原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。