|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
专门做了这个例子;而java的这个例子好像就是为了教学而写的,很多教学目的的例子是不考虑优化、性能的。
1、引子
关于体系中一个已完成的类条理布局,我们已给它供应了满意需求的接口。可是面临新增添的需求,我们应当怎样做呢?假如这是为数未几的几回变化,并且你不必为了一个需求的调剂而将全部类条理布局一切地修正一遍,那末间接在原有类条理布局上修正大概是个不错的主张。
可是常常我们碰到的倒是:如许的需求变化大概会一直的产生;更主要的是需求的任何变化大概都要让你将全部类条理布局修正个底朝天……。这类相似的操纵散布在分歧的类内里,不是一个好征象,我们要对这个布局重构一下了。
那末,会见者形式大概是你很好的选择。
2、界说与布局
会见者形式,望文生义利用了这个形式后就能够在不修正已有程序布局的条件下,经由过程增加分外的“会见者”来完成对已有代码功效的提拔。
《计划形式》一书关于会见者形式给出的界说为:暗示一个感化于某对象布局中的各元素的操纵。它使你能够在不改动各元素的类的条件下界说感化于这些元素的新操纵。从界说能够看出布局对象是利用会见者形式必需前提,并且这个布局对象必需存在遍历本身各个对象的办法。这便相似于java中的collection观点了。
以下是会见者形式的构成布局:
1)会见者脚色(Visitor):为该对象布局中详细元素脚色声明一个会见操纵接口。该操纵接口的名字和参数标识了发送会见哀求给详细会见者的详细元素脚色。如许会见者就能够经由过程该元素脚色的特定接口间接会见它。
2)详细会见者脚色(ConcreteVisitor):完成每一个由会见者脚色(Visitor)声明的操纵。
3)元素脚色(Element):界说一个Accept操纵,它以一个会见者为参数。
4)详细元素脚色(ConcreteElement):完成由元素脚色供应的Accept操纵。
5)对象布局脚色(ObjectStructure):这是利用会见者形式必备的脚色。它要具有以下特性:能列举它的元素;能够供应一个高层的接口以同意该会见者会见它的元素;能够是一个复合(组合形式)或是一个汇合,如一个列表或一个无序汇合。
来张类图就可以加倍明晰的看清会见者形式的布局了。
那末像弁言中设想的。我们应当做些甚么才干让会见者形式跑起来呢?起首我们要在原本的类条理布局中增加accept办法。然后将这个类条理中的类放到一个对象布局中往。如许再往创立会见者脚色……
3、举例
自己经历其实不幸,没能找到会见者形式在实践使用中的例子。只好借《ThinkinginPatternswithjava》中的教授教养代码一用。我略微做了下修正。
importjava.util.*;
importjunit.framework.*;
//会见者脚色
interfaceVisitor{
voidvisit(Gladiolusg);
voidvisit(Runuculusr);
voidvisit(Chrysanthemumc);
}
//TheFlowerhierarchycannotbechanged:
//元素脚色
interfaceFlower{
voidaccept(Visitorv);
}
//以下三个详细元素脚色
classGladiolusimplementsFlower{
publicvoidaccept(Visitorv){v.visit(this);}
}
classRunuculusimplementsFlower{
publicvoidaccept(Visitorv){v.visit(this);}
}
classChrysanthemumimplementsFlower{
publicvoidaccept(Visitorv){v.visit(this);}
}
//Addtheabilitytoproduceastring:
//完成的详细会见者脚色
classStringValimplementsVisitor{
Strings;
publicStringtoString(){returns;}
publicvoidvisit(Gladiolusg){
s="Gladiolus";
}
publicvoidvisit(Runuculusr){
s="Runuculus";
}
publicvoidvisit(Chrysanthemumc){
s="Chrysanthemum";
}
}
//Addtheabilitytodo"Bee"activities:
//另外一个详细会见者脚色
classBeeimplementsVisitor{
publicvoidvisit(Gladiolusg){
System.out.println("BeeandGladiolus");
}
publicvoidvisit(Runuculusr){
System.out.println("BeeandRunuculus");
}
publicvoidvisit(Chrysanthemumc){
System.out.println("BeeandChrysanthemum");
}
}
//这是一个对象天生器
//这不是一个完全的对象布局,这里仅仅是摹拟对象布局中的元素
classFlowerGenerator{
privatestaticRandomrand=newRandom();
publicstaticFlowernewFlower(){
switch(rand.nextInt(3)){
default:
case0:returnnewGladiolus();
case1:returnnewRunuculus();
case2:returnnewChrysanthemum();
}
}
}
//客户测试程序
publicclassBeeAndFlowersextendsTestCase{
/*
在这里你能看到会见者形式实行的流程:
起首在客户端先取得一个详细的会见者脚色
遍历对象布局
对每个元素挪用accept办法,将详细会见者脚色传进
如许就完成了全部历程
*/
//对象布局脚色在这里才组装上
Listflowers=newArrayList();
publicBeeAndFlowers(){
for(inti=0;i<10;i++)
flowers.add(FlowerGenerator.newFlower());
}
Visitorsval;
publicvoidtest(){
//It’salmostasifIhadafunctionto
//produceaFlowerstringrepresentation:
//这个中央你能够修正以便利用别的一个详细会见者脚色
sval=newStringVal();
Iteratorit=flowers.iterator();
while(it.hasNext()){
((Flower)it.next()).accept(sval);
System.out.println(sval);
}
}
publicstaticvoidmain(Stringargs[]){
junit.textui.TestRunner.run(BeeAndFlowers.class);
}
}
<p>
用winrar打包j2ee的程序和用IDE打包应用程序是一样的。按照你的想法,你是不是也希望服务器都整合由一家公司提供呢? |
|