【前言】
通过以前对设计模式的学习和最近软考对设计模式的研究,有的设计模式如果用“内存分析”来辅助,我觉得更加容易理解,下面举职责链模式和装饰模式的例子说明。
【装饰模式】
类图:
装饰模式以“星巴兹咖啡”为例,其类图为:
代码如下:
<span style="font-size:18px;">public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
</span>
Beverage类很简单,让我们也来实现Condiment(调料)抽象类,也就是装饰者类:
<span style="font-size:18px;">public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
</span>
现在已经有了基类,让我们开始实现一些饮料吧。别忘了我们需要为具体的饮料设置描述,而且还必须实现cost()方法:
<span style="font-size:18px;">public class Espresso extends Beverage {
public Espresso() {
description = "Espresso Coffee";
}
@Override
public double cost() {
return 1.99;
}
}
</span>
饮料类DarkRoast、Decaf、HouseBlend与类Espresso 类似,此处省略。
如果你回头看类图,现在我们已经实现了抽象组件(Beverage),有了具体组件(HouseBlend。。。),也有了抽象装饰者(CondimentDecorator),现在让我们来实现具体装饰者:<span style="font-size:18px;">public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
@Override
public double cost() {
return 0.20 + beverage.cost();
}
}
</span>
调料类Milk、Soy、Whip与类Mocha类似,此处省略。
下来些客户端代码:
public class StarbuzzCoffee {
public static void main(String args[]) {
Beverage beverage = new Espresso(); //内存分析从这里开始,对应下图的线1
beverage= new Soy(beverage); //对应下图的线2,第一个"beverage3"是调料Soy,第二个“ beverage3”是饮料Espresso
beverage = new Mocha(beverage);//对应下图的线3,第一个"beverage3"是调料Mocha,第二个“ beverage3”是调料Soy
beverage = new Whip(beverage);//对应下图的线4,第一个"beverage3"是调料Whip,第二个“ beverage3”是饮料Mocha
System.out.println(beverage.getDescription()
+ " $" + beverage.cost()); //分析这句代码:运行beverage3.getDescription()方法,从以上三句代码分析,此时的“beverage3”代表的是Whip对象,当你调用Whip的getDescription()方法时,(观看以上Whip具体实现代码),此时”beverage.getDescription()“中的“beverage”代表的是Mocha(这对应着线4),以此类推,最后出现结果:Espresso, Soy, Mocha, Whip 。价格方法也是一样
}
}
运行结果如下:
内存分析图:
【职责链模式】
类图:
软考例题:
阅读以下说明以及Java程序,将应填入 (n) 处的字句写在答题纸的对应栏内。
【说明】
已知某企业的采购审批是分级进行的,即根据采购金额的不同由不同层次的主管人员来审批,主任可以审批5万元以下(不包括5万元)的采购单,副董事长可以审批5万元至10万元(不包括10万元)的采购单,董事长可以审批10万元至50万元(不包括50万元)的采购单,50万元及以上的采购单就需要开会讨论决定。
采用责任链设计模式(Chain of Responsibility)对上述过程进行设计后得到的类图如图7-1所示。
<span style="font-size:18px;">class PurchaseRequest {
public double Amount; // 一个采购的金额
public int Number; // 采购单编号
public String Purpose; // 采购目的
}
class Approver { // 审批者类
public Approver(){ successor = null; }
public void ProcessRequest(PurchaseRequest aRequest){
if (successor != null){ successor.(ProcessRequest(aRequest)); }
}
public void SetSuccessor(Approver aSuccesssor){ successor = aSuccesssor; }
private (Approver) successor;
}
class Congress extends Approver { //例会类
public void ProcessRequest(PurchaseRequest aRequest){
if(aRequest.Amount >= 500000){ /* 决定是否审批的代码省略 */ }
else (super) .ProcessRequest(aRequest);
}
}
class Director extends Approver { //主任类
public void ProcessRequest(PurchaseRequest aRequest){ /* 此处代码省略 */ }
}
class President extends Approver { //董事长类
public void ProcessRequest(PurchaseRequest aRequest){ /* 此处代码省略 */ }
}
class VicePresident extends Approver { 副董事长类
public void ProcessRequest(PurchaseRequest aRequest){ /* 此处代码省略 */ }
}</span>
客户端代码:
public class rs {
public static void main(String[] args) throws IOException {
Congress Meeting = new Congress(); //实例化对象在堆中开辟空间,对应线1。不确定之处:实例化多个子类,有多少个子类实例化就开辟 多少个父类内存空间,如下图中,每个子类中都有一个父类
President Tammy = new President(); //对应线2
VicePresident Sam = new VicePresident(); //对应线3
Director Larry = new Director(); //对应线4
// 构造责任链
Meeting.SetSuccessor(null); //对应线8,如果采购单自己处理不了,通过父类里边的审批 者引用来指定下一个对象(NULL)来处理。
Sam.SetSuccessor( (Tammy) ); //对应线6,如果采购单自己处理不了,通过父类里边的审 批者引用来指定下一个对象(Tammy)来处理。
Tammy.SetSuccessor( (Meeting) ); //对应线7,如果采购单自己处理不了,通过父类里边的审批 者引用来指定下一个对象(Meeting )来处理。
Larry.SetSuccessor( (Sam) ); //对应线5,如果采购单自己处理不了,通过父类里边的审批者 引用来指定下一个对象(Sam)来处理。
// 构造一采购审批请求 PurchaseRequest aRequest = new PurchaseRequest();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
aRequest.Amount = Double.parseDouble(br.readLine());
//对以下这句代码,如果说采购单是50万以上的,这句代码的执行是:Larry(任). ProcessRequest(Sam(副董事长). ProcessRequest(Tammy(董事长). ProcessRequest(Congress(例会). ProcessRequest(aRequest))))
(Larry) .ProcessRequest(aRequest); // 开始审批
return ;
}
}
内存分析图:
【总结】
总之,我觉得刚开始时,模糊的地方通过内存分析,变得很是清晰,希望能对大家有所帮助。
通过各种方式来学习,来帮助自己了解,这也是知识网的体现。