定义:
动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性
的替代方案。
相信大家应该都吃过火锅了,火锅中锅底是必须的,至于其他的配菜就需要自己点了。
下面以火锅来谈谈装饰者模式。
首先需要创建一个火锅的对象,后面鸳鸯火锅,麻辣火锅,清汤火锅等都继承它
abstract class Pot {
//锅底名
public String name = "锅底";
public String getName() {
return name;
}
//价格,由子类实现
public abstract double price();
}
因为每个锅底的价格都不一样,所以写一个抽象的price()方法,由子类决定价格。
然后定义定义火锅的实例: 清汤锅底、鸳鸯锅底等。
清汤锅底:
class ClearSoupPot extends Pot {
public ClearSoupPot(){
name = "清汤锅底";
}
@Override
public double price() {
return 29;
}
}
鸳鸯锅底
class YuanYangPot extends Pot {
public YuanYangPot(){
name = "鸳鸯锅底";
}
@Override
public double price() {
return 39;
}
}
锅底已经键好了,现在我们需要加配菜了。首先创建一个配菜的抽象类,所有配菜都继承自它。
abstract class Garnish extends Pot{
public abstract String getName();
}
因为我们的配菜是来搭配火锅的,所以要继承Pot类。
//蔬菜类
class GarnishVegetables extends Garnish {
private Pot mPot;
public GarnishVegetables(Pot pot){
mPot = pot;
}
@Override
public String getName() {
return mPot.getName() + " +蔬菜";
}
@Override
public double price() {
return mPot.price() + 12;
}
}
为了让配菜类能够引用到火锅对象,所以在初始化的时候传入火锅对象。
同理创建GarnishDuckBlood、GarnishShrimp鸭血和虾的类。
现在我们可以点一份喜欢的火锅了。
public static void main(String[] args){
//点一份鸳鸯锅底
Pot pot = new YuanYangPot();
//加鸭血
pot = new GarnishDuckBlood(pot);
//加蔬菜
pot = new GarnishVegetables(pot);
//打印菜单
System.out.println(pot.getName());
//打印价格
System.out.println(pot.price());
//点一份清汤锅底
Pot soupPot = new ClearSoupPot();
//加虾
soupPot = new GarnishShrimp(soupPot);
//加蔬菜
soupPot = new GarnishVegetables(soupPot);
//打印菜单
System.out.println(soupPot.getName());
//打印价格
System.out.println(soupPot.price());
}
执行结果如下:
鸳鸯锅底 +鸭血 +蔬菜
57.0
清汤锅底 + 虾 +蔬菜
77.0
这里我们可以把火锅当初一个被装饰的对象,它初始时只有对应的锅底。而各种配菜则是装饰品,添加到火锅中,使其具有不同的配菜。
通过装饰者模式,可以动态的给对象添加一些额外的职责。
装饰者模式的通用结构
Component 是一个接口或抽象对象,是我们定义的最基本、最核心的组件。是被修饰的对象父类,如上面的火锅类pot。
ConcreteComponent 是组件Component 的实现类,是我们要装饰的具体对象,如上面的鸳鸯锅,清汤锅。
一般是一个抽象类,继承自Component。
继承自Decorator 类,是装饰者Decorator 的实例。如上面的蔬菜,鸭血,虾都是装饰者
抽象组件代码清单
Component :组件定义
abstract class Component {
//抽象方法,可有可无
abstract void operate();
}
ConcreteComponent 组件的实例对象定义
class ConcreteComponent extends Component {
@Override
void operate() {
System.out.println("做一些事");
}
}
Decorator 抽象装饰者
abstract class Decorator extends Component{
private Component mComponent = null;
//通过构造函数传递被修饰者
public Decorator(Component component){
this.mComponent = component;
}
//委托给被修饰者执行
@Override
void operate() {
this.mComponent.operate();
}
}
ConcreteDecoratorA、ConcreteDecoratorB具体的装饰类定义
class ConcreteDecoratorA extends Decorator {
//定义被修饰者
public ConcreteDecoratorA(Component component) {
super(component);
}
//定义自己的修饰方法
private void m1(){
System.out.println("方法1 修饰");
}
//重写父类方法
@Override
void operate() {
this.m1();
super.operate();
}
}
class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
public void m2(){
System.out.println("方法2 修饰");
}
//重写父类方法
@Override
void operate() {
this.m2();
super.operate();
}
}
执行装饰者模式:
public static void main(String[] args){
Component component = new ConcreteComponent();
//第一次修饰
component = new ConcreteDecoratorA(component);
//第二次修饰
component = new ConcreteDecoratorB(component);
//修饰后运行
component.operate();
}
执行结果:
方法2 修饰
方法1 修饰
做一些事
优缺点
装饰者模式可以动态的增加类的功能,但如果使用过量会增加会出现很多小对象,让程序变得复杂。
参考:《Head First设计模式》