1、继承带来的问题
源代码地址:http://download.youkuaiyun.com/detail/kai46385076/7870073
、
会产生类爆炸
2、装饰着模式概述
在不影响对象的情况下,以动态、透明的方式给单个对象添加职责。
比如上图,如果添加一个种类,可能需要增加很多类,产生类暴躁,类似网络游戏,打游戏的时候,可以给角色增加很多装备,比如盔甲,头盔,宝石,装饰品,武器,都是增强了功能,但是不改变本身。
第一个Component是一个组件,concretecompnent是一个具体的组件,豆浆是一个饮料的一种,也可以是酸梅汤等等,Decorator有两个子类继承,也可能有很多子类,这样分开可以有很多组合,比如鸡蛋,糖,比如喝豆浆的时候需要添加配料的时候添加实体装饰类就可以了。
涉及角色
抽象构建组件:定义一个抽象接口,来规范准备附加功能的类。
具体构建组件:将要被附加功能的类,实现抽象构件角色功能。
抽象装饰着角色:持有对具体构件角色的引用并定义域抽象构件组件一致的接口、
具体装饰角色:实现抽象装饰者角色,负责为具体构件添加额外功能。
抽象构建组件
package com.zkq.decorator;
/*** 被装饰者对象的接口
* @author Administrator
*
*/
public interface Drink {
//饮料的描述信息
public String description();
//计算价格
public float cost();
}
具体构建组件
package com.zkq.decorator;
/**
* 具体的被装饰者:纯豆浆
* @author Administrator
*
*/
public class SoyaBeanMilk implements Drink {
@Override
public String description() {
// TODO Auto-generated method stub
return "纯豆浆";
}
@Override
public float cost() {
// TODO Auto-generated method stub
return 5f;
}
}
抽象装饰着角色
package com.zkq.decorator;
/**
* 装饰着父类
* @author Administrator
*
*/
public abstract class Decorator implements Drink{
private Drink drink;//要装饰的对象
public Decorator(Drink drink)
{
this.drink=drink;
}
@Override
public String description() {
// TODO Auto-generated method stub
return drink.description();
}
@Override
public float cost() {
// TODO Auto-generated method stub
return drink.cost();
}
}
具体装饰角色
package com.zkq.decorator;
/**
*具体的装饰者对象,糖
* @author Administrator
*
*/
public class SugarDecorator extends Decorator{
public SugarDecorator(Drink drink) {
super(drink);
// TODO Auto-generated constructor stub
}
@Override
public String description() {
// TODO Auto-generated method stub
return super.description()+"糖";
}
@Override
public float cost() {
// TODO Auto-generated method stub
return super.cost()+0.5f;
}
}
具体装饰角色
package com.zkq.decorator;
/**
* 具体的装饰着对象:鸡蛋
* @author Administrator
*
*/
public class EggDecorator extends Decorator{
public EggDecorator(Drink drink) {
super(drink);
// TODO Auto-generated constructor stub
}
@Override
public String description() {
// TODO Auto-generated method stub
return super.description()+"鸡蛋";
}
@Override
public float cost() {
// TODO Auto-generated method stub
return super.cost()+2.0f;
}
}
具体装饰角色
package com.zkq.decorator;
/**
* 具体的装饰者:黑豆
* @author Administrator
*
*/
public class BlackBeanDecorator extends Decorator{
public BlackBeanDecorator(Drink drink) {
super(drink);
// TODO Auto-generated constructor stub
}
@Override
public String description() {
// TODO Auto-generated method stub
return super.description()+"黑豆";
}
@Override
public float cost() {
// TODO Auto-generated method stub
return super.cost()+3.0f;
}
}
测试
package com.zkq.decorator;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//生产一个豆浆
Drink soya=new SoyaBeanMilk();
//在豆浆中加鸡蛋
EggDecorator eggSoya=new EggDecorator(soya);
//在加了鸡蛋中的豆浆中加糖
SugarDecorator sugarEggSoya=new SugarDecorator(eggSoya);
//加了糖了豆浆中加黑豆
BlackBeanDecorator blackbeansugarEggSoya=new BlackBeanDecorator(sugarEggSoya);
System.out.println("你点了"+blackbeansugarEggSoya.description());
System.out.println("一共"+blackbeansugarEggSoya.cost());
}
}
实现结果为:
你点了纯豆浆鸡蛋糖黑豆
一共10.5
下面可以举个生动的例子,大家应该见过打印咧PrintStream,这个就算是装饰着模式。
OutputStream out=new FileutputStream("d:\\1.txt");
BufferedOutputStream bos=new BufferedOutputStream(out);
PrintStream ps=new PrintStream(bos);
等于豆浆加上鸡蛋,加上糖。相当于具备了很好输出功能的输出流。实现了装饰着模式
OO原则:动态地将责任附加到对象上。想要扩张功能,装饰者提供有别于继承的另一种选择。
注意要点:
1、继承属于扩展形式之一,但不见得是弹性设计的最佳方案。
2、在我们的设计中,应该允许行为可以被扩展,而不须修改现有的代码。
3、组合和委托可用于在运行时动态地加上新的行为。
4、除了继承,装饰着模式也可以让我们扩展行为。
5、装饰着模式意味着一群装饰着类,这些类用来包装具体组件。
6、装饰着类反映出被装饰的组件类型(实际上,他们具有相同的类型,都通过接口和继承实现)。
7、装饰着可以在在被装饰者的行为前面与或后面加上自己的行为,甚至将装饰者行为整个取代掉,而达到特定的目的。
8、你可以有无数个装饰者包装一个组件。
9、装饰着一般对组件的客户是透明的。
除非客户程序依赖于组件的具体类型。
源代码地址:http://download.youkuaiyun.com/detail/kai46385076/7870073