好久没写笔记了,原因是最近在帮老师写一个项目的android客户端,算是我第二个比较正式的android软件吧。我觉得知识得一块一块的学习并加以应用才能完全的理解它,就拿android来说,首先了解整个android大体框架,当做应用时需要实现什么功能时就会深刻的去学习并运用那个模块相关的知识,这时候你才能叫做学以致用。其实实践是最好的学习方式,别说你会了,当你真的亲手去做一个项目时你才会深切体会到知识的缺乏,所以别说什么抄袭不好,当你真正模仿出一个应用时你的水平就不差了。
话不多说,今天来讲讲装饰模式(Decorator Pattern),以前也学习过装饰模式,而学习的例子就是jdk的io包,由于当时水平有限没怎么能够理解它,现在看《Head First》他讲解的倒是让我有些恍然大悟的感觉的,按照常例本章的例子是星巴克咖啡计费问题。按照书中一开始的设计思路导致了类继承的泛滥,很多很多的子类造成项目工程浩大且难以维护,而且违反了两个设计原则:
1.针对接口编程而不是针对实现变成
2.少用继承,多用组合
所以自然而然我们就可以以这两条设计原则而设计我们的类。
星巴克咖啡的价钱算法:总价格=底料价+各调料价格
底料价是固定不变的,而由于每个客户的调料种类和份数不一所以是动态的,这里底料就相当于被装饰者,而这些调料就是装饰者去装饰这杯咖啡。 所以我们可以设计一个超类接口(饮料类),底料类实现此接口,抽象调料类继承自接口,具体调料类就实现抽象类,从而达到了不变部分与变化部分分开。于是一个装饰模式的模型就出现了:
装饰模式定义:
动态的将责任附加到对象上。若要扩展功能,装饰着提供了比继承更有弹性的替代方案
下面是书中针对星巴克咖啡计费问题的最终代码
//抽象饮料类,对应图中的Component
public abstract class Beverage{
String description="Beverage";
public String getDescription(){
return description;
}
public abstract double cost();
}
//具体咖啡类,被装饰的类,对应图中的ConcreteCompolent
public class Espresso extends Beverage{
public Espresso(){
description="Espresso";
}
public double cost(){
return .10;//返回不加料的咖啡的价格
}
}
//调料抽象类 继承自饮料类 抽象装饰者类,对应图中的Decorator
public abstract class CondimentDecorator extends Beverage{
public abstract String getDescription();
}
//具体调料类 ,具体装饰者 ,摩卡调料 ,图中的ConcreteDecorator
public class Mocha extends CondimentDecorator{
Beverage beverage;
public Mocha(Beverage beverage){
this.beverage=beverage;
}
public String getDescription(){
return beverage.getDescription()+",Mocha";
}
public double cost(){
return beverage.cost()+.20;//价格就是各个价格的和
}
}
//具体调料类 奶泡调料,具体装饰者类,图中的ConcreteDecorator
public class Whip extends CondimentDecorator{
Beverage beverage;
public Whip(Beverage beverage){
this.beverage=beverage;
}
public String getDescription(){
return beverage.getDescription()+",Whip";
}
public double cost(){
return beverage.cost()+.10;
}
}
public class Decorator{
public static void main(String args[]){
Beverage espresso=new Espresso();
System.out.println(espresso.getDescription()+" $"+espresso.cost());
Beverage beverage=new Mocha(espresso);
beverage=new Mocha(espresso);
beverage=new Whip(espresso);
System.out.println(beverage.getDescription()+" $"+beverage.cost());
}
}
JDK自己的装饰模式是io包中的InputStream等一系列类集,也是互相装饰的原理,在这里就不多说了。