装饰者模式定义
装饰者模式(Decorator Pattern):在不改变原类文件的情况下, 动态地扩展一个对象的功能。通过创造包装对象,来包裹原对象,并给其增加功能。
UML图如下:
Component:装饰类和被装饰类共同的父类
ConcreteComponent:被装饰的对象
Decorator: 装饰类
ConcreteDecoratorA:具体的装饰类A
通常被装饰的对象和装饰类都继承自同一个抽象类或者接口, 然后装饰类会有具体的子类去实现具体的装饰(新的功能)。 文字可能有点抽象, 下面举例来说明。
装饰者模式 代码示例
比如咖啡店有不同的咖啡, 普通的咖啡,然后在普通咖啡的基础上, 可以加不同的配料, 比如 牛奶、糖、奶泡, 加了不同配料的价格也不一样。下面我们就用装饰者模式实现。
首先定义一个Coffice基类(类图中的Compomnent类):
/**
* @ explain:这里Coffee相当于我们的Component,
* 是要装饰的类
*/
public abstract class Coffee {
/**
* @return 返回价格
*/
public abstract int getPrice();
/**
* @return 返回名字
*/
public abstract String getName();
}
然后定义我们的被装饰对象, 普通咖啡类(类图中的ConcreteComponent):
public class SimpleCoffee extends Coffee {
/**
* @return 返回价格
*/
public int getPrice() {
return 10;//普通咖啡10元一杯
}
/**
* @return 返回名字
*/
public String getName() {
return "simple coffee";
}
}
接着定义一个Decorator类继承基类
public abstract class Decorator extends Coffee{
protected Coffee mCoffee;
/**
* 通过组合的方式把Coffee对象传递进来
* @param coffee
*/
public Decorator(Coffee coffee){
mCoffee=coffee;
}
}
再定义具体的装饰类:
public class MilkDecorator extends Decorator {
/**
* 通过组合的方式把Coffee对象传递进来
*
* @param coffee
*/
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public int getPrice() {
return mCoffee.getPrice()+10;
}
@Override
public String getName() {
return mCoffee.getName()+", addMilk";
}
}
加糖,加其他配料的装饰类类似,可以自行展开, 然后在业务代码处具体使用如下:
Coffee mCoffee = new SimpleCoffee();//得到一杯普通咖啡
//得到一杯加糖的咖啡, 这个时候价格、名字都变了,相当于类的功能变了
mCoffee = new SugarDecorator(mCoffee);
//得到一杯加牛奶的咖啡
mCoffee = new MilkDecorator(mCoffee);
mCoffee = new MilkFoamDecorator(mCoffee);
System.out.println("Name="+mCoffee.getName());
System.out.println("price="+mCoffee.getPrice());
通过不断装饰, 使原本的普通咖啡越来越强, 越来越贵,变成加牛奶和糖的咖啡。装饰者模式的作用就是这样, 把原来的对象的功能不断增强。 这在java IO 中使用的特别多。
装饰者模式总结
装饰模式有效的把核心职责和装饰功能分开了。比如上面我们核心是想喝一杯咖啡, 至于是加糖还是加什么, 那是额外的装饰, 是额额外的功能,我们可以根据具体需求再添加。
通过将功能分开在不同的类, 实现了类的单一职责,类的功能更清晰明了。这样就不会使核心类过于臃肿, 相当于对核心功能类实现了细分和解耦。