继承,装饰者模式和动态代理之间的区别

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) ,比装饰者模式更加灵活, 被增强的对象和增强的内容都是可以更换的.

你可能感兴趣的:(源码)