Java中,需要对对象进行增强时,我们常用的三种方法是 继承, 装饰者模式和动态代理.现在,举个例子来描述这三者之间的区别.
在星巴克喝咖啡时, 可以选择各种调味品, 黑咖啡中可以选择加糖,加奶,加蜂蜜. 这样咖啡的味道被改变,我们可以说黑咖啡被"增强"了.用java代码这样表示:
/**
* 创建一个咖啡的类,里面有黑咖啡
*/
class Coffee{
void blankCoffee(){
System.out.println("黑咖啡");
}
}
/**
* 现在要对黑咖啡加糖
*/
class Sugar extends Coffee {
void blankCoffee() {
super.blankCoffee();
System.out.println("加糖");
}
}
/**
* 现在要对黑咖啡加奶
*/
class Milk extends Coffee {
void blankCoffee() {
super.blankCoffee();
System.out.println("加奶");
}
}
/**
* 现在要对黑咖啡加蜂蜜
*/
class Honey extends Coffee {
void blankCoffee() {
super.blankCoffee();
System.out.println("加蜂蜜");
}
}
这样子我们得到了三种不同口味的黑咖啡. 现在又有了新的问题, 要求要加奶又加糖的咖啡,需要给加奶的咖啡加上糖,用继承这样子来实现
/**
* 现在需要加奶加糖咖啡
*/
class SugarMilke extends Milk {
void blankCoffee() {
super.blankCoffee();
System.out.println("加糖");
}
}
...
可能还需要加奶加蜂蜜的咖啡... 多种排列组合就会出现很多类, 出现了新的一种口味又需要增加很多的类.
这时候我们用装饰者模式来解决这个问题
/**
* 首先定义一个接口来规范咖啡.
*/
interface Coffee {
void coffee();
}
/*
* 实现这个上面这个接口中的方法.
*/
class CoffeeImpl implements Coffee {
public void coffee(){
System.out.println("黑咖啡");
}
}
/*
* 在给黑咖啡添加调味品之前,我们先定义一个类,这个类是所有添加调味品咖啡的父类,进行包装
*/
class CoffeeWrapper implements Coffee {
private Coffee cof;
public CoffeeWrapper(Coffee cof){
this.cof = cof;
}
public void coffee(){
cof.coffee();
}
}
/**
* 加糖咖啡
*/
class Sugar extends CoffeeWrapper {
public Sugar(Coffee cof) {
super(cof);
}
public void coffee(){
super.coffee();
System.out.println("加糖");
}
}
/**
* 加奶咖啡
*/
class Milk extends CoffeeWrapper {
public Milk(Coffee cof) {
super(cof);
}
public void coffee(){
super.coffee();
System.out.println("加奶");
}
}
/**
* 蜂蜜咖啡
*/
class Honey extends CoffeeWrapper {
public Honey(Coffee cof) {
super(cof);
}
public void coffee(){
super.coffee();
System.out.println("加蜂蜜");
}
}
/**
* 演示
*/
public class Demo() {
public static void main(String[] args) {
//首先创建一个黑咖啡
Coffee cof = new CoffeeImpl();
//加糖咖啡
Coffee sugar = new Sugar(cof);
sugar.coffee();
//加糖又加奶咖啡
Coffee milk = new Milk(sugar);
sugar.coffee();
}
}
这样我们就解决了这个问题.
* 继承
被增强的对象固定的
增强的内容也是固定的
* 装饰者模式
被增强的对象是可以切换的
增强的内容是固定的
还有一种更加灵活的方式,面向切面编程(AOP) ,比装饰者模式更加灵活, 被增强的对象和增强的内容都是可以更换的.