java 装饰者模式
《Head First 设计模式》学习中
装饰者模式
- 动态的将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案
类图
参与者
1.Component(被装饰对象的基类)
定义一个对象接口,可以给这些对象动态地添加职责。
2.ConcreteComponent(具体被装饰对象)
定义一个对象,可以给这个对象添加一些职责。
3.Decorator(装饰者抽象类)
维持一个指向Component实例的引用,并定义一个与Component接口一致的接口。
4.ConcreteDecorator(具体装饰者)
具体的装饰对象,给内部持有的具体被装饰对象,增加具体的职责。
涉及角色
- 抽象组件:定义一个抽象接口,来规范准备附加功能的类
- 具体组件:将要被附加功能的类,实现抽象构件角色接口
- 抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口
- 具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。
举例:
经常去一个饭馆吃牛肉面,可以选择添加鸡蛋,火腿,豆皮等配菜,这就可以使用装饰者模式。
Component(被装饰对象的基类)
package com.Observer.model; public abstract class food { String size; String description; public String getSize() { return size; } public void setSize(String size) { this.size = size; } public String getDescription() { return description; } public abstract double cost(); }
ConcreteComponent(具体被装饰对象)
package com.Observer.model; public class BeefNoodles extends food { public BeefNoodles() { description = "牛肉面小碗"; } @Override public double cost() { if (super.getSize().equals("大碗")) { super.description = "牛肉面大碗"; return 12.0; } super.description = "牛肉面小碗"; return 10.0; } }
package com.Observer.model; public class Casserole extends food { public Casserole(){ description = "砂锅方便面"; } @Override public double cost() { return 12.0; } }
Decorator(装饰者抽象类)
package com.Observer.model; public abstract class Condiment extends food { public abstract String getDescription(); }
ConcreteDecorator(具体装饰者)
package com.Observer.model; public class Ham extends Condiment { food food; public Ham(food food){ this.food = food; } @Override public String getDescription() { return food.getDescription() + ", 火腿"; } @Override public double cost() { return 2.0 + food.cost(); } }
package com.Observer.model; public class Egg extends Condiment { food food; public Egg(food food){ this.food = food; } @Override public String getDescription() { return food.getDescription() + ", 鸡蛋"; } @Override public double cost() { return 1.5 + food.cost(); } }
package com.Observer.model; public class Rosa extends Condiment { food food; public Rosa(food food){ this.food = food; } @Override public String getDescription() { return food.getDescription() + ", 豆皮"; } @Override public double cost() { return 1.0 + food.cost(); } }
测试
package com.Observer.model; public class Test { public static void main(String[] args) { food food = new Casserole(); System.out.println(food.getDescription() + " 价格 ," + food.cost() + "元"); food food1 = new BeefNoodles(); food1.setSize("大碗"); food1 = new Ham(food1); food1 = new Ham(food1); food1 = new Egg(food1); food1 = new Rosa(food1); System.out.println(food1.getDescription() + " 价格 ," + food1.cost() + "元"); food food2 = new BeefNoodles(); food2.setSize("小碗"); food2 = new Ham(food2); food2 = new Ham(food2); food2 = new Egg(food2); food2 = new Rosa(food2); System.out.println(food2.getDescription() + " 价格 ," + food2.cost() + "元"); } }
结果
砂锅方便面 价格 ,12.0元 牛肉面小碗, 火腿, 火腿, 鸡蛋, 豆皮 价格 ,18.5元 牛肉面小碗, 火腿, 火腿, 鸡蛋, 豆皮 价格 ,16.5元
要点:
- 继承属于扩展形式之一,但不见得是达到弹性设计的最佳方案。
- 在我们的设计中,应该允许行为可以被扩展,而不须修改现有的代码。
- 组合和委托可用于在运行时动态地加上新的行为。
- 除了继承,装饰者模式也可以让我们扩展行为。
- 装饰者模式意味着一群装饰者类, 这些类用来包装具体组件。
- 装饰者类反映出被装饰的组件类型(实际上,他们具有相同的类型,都经过接口或继承实现)。
- 装饰者可以在被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的。
- 你可以有无数个装饰者包装一个组件。
- 装饰者一般对组建的客户是透明的,除非客户程序依赖于组件的具体类型。
参考博客:https://www.cnblogs.com/chenxing818/p/4705919.html