问答格
第一章 系统设计 | Flexunit还需要实验 3小时 | |
1.系统构建的步骤 | 分析 设计 实现 测试 | |
2.分析阶段的方法 | 1.编写用例 2.UML的使用 | |
3.设计阶段的方法 | CRC卡 UML | |
4.一个类的功能有几个 | 有一到三个功能 | |
5.类与类之间的关系 | 1.关联 依赖 2.注释 map里有一个street map消失,street也会消失 3.继承 是一个 | |
6.编程规范 | 1.英语 2.骆驼 3.最短最多 4.不要数字 5.私有属性命名用下划线 6.常量全部大写,用下划线分隔 7.类大写 8.接口大写 | |
7.封装的内容 | 1.公共属性用存取器 2.外部引用的限制,类不能直接引用任何外部对象 3.封装的方法: 拷贝 迭代器 | |
8.重用其他类功能的方法有两个 | 继承和组合 | |
9.什么时候选择继承 | 如果新类定义的是已存在类的子类型,如果新类自己无子类,如果新类通过继承已存在类的实现收益颇多或者如果新类没有什么特别的要求,比如,运行时可以更改。 | |
10.解决耦合的方法 | 使用命令模式 | |
11.FlexUnit应用范围 | 也可以应用于纯AS的项目 | |
12.基本的单元测试两步走 | 1.测试用例 1.要继承自TestCase 2.构造函数是这样 SimpleTest(method:String){ super(method)} 3.具体方法的最后一步是类似这样: assertEquals(degrees.0); 4.assertEquals 这些都是TestCase的父类Assert的方法 2.测试运行器 1.实例化TestSuite 2.像这样把具体方法加入到TestSuite中 suite.addTest(new SimpleTest("方法名")); 3.实例化TestRunnerBase 4.TestRunnerBase的实例.test = suite 5.TestRunnerBase的实例.startTest(); | |
13.异步单元测试 | 1.测试用例 1.目标类实例.addEventListener(Event.COMPLETE,addAsync(onData,2000)) 2.在onData 里写 assertNotNull(event.target.data) 3.在用例里写上 TestCase的实例名.addTest(new 这个TestCase的当前子类(测试方法名)) 2.在测试运行器里 1.TestSuite的实例.addTest(new 这个TestCase的当前子类.suite()); 2.TestRunnerBase的实例.test = suite; 3. testRunner.startTest(); | |
第二章 接口编程 | 通讯的那个还要实验 2小时 | |
1.原则 | 对接口进行编程要比对实现编程要好得多 | |
2.定义接口的两种方式 | 1.通过抽象类继承接口 和 普通接口 | |
3.有一个很好的例子 | 1.通讯服务那个,要做实验! | |
第三章 MVC模式 | 要再找两个例子能默写 3小时 | |
4.Time | 1.三个private属性 及其存取器 2.在构造函数中给三属性赋值 3.clone() | |
5.ClockData | 1.它必须是一个EventDispatcher 2.有private Time实例 3.get time时如果无则返回当前时间,有则返回clone 4.set time时把value.clone的值赋值给time. 并发出Event.CHANGE事件 | |
6.AbstractClockView. | 1.有一个protected的ClockData 2.在构造函数里把data传给clockData 3.侦听clockData 如果有变化则执行protected draw() | |
7.AnologClock. | 1.继承自AbstractClockView 并且super(data); 2.若干private的显示对象. 并且在initView里详细描述它们 3.重写AbstractClockView里的关键方法draw(). | |
8.关于控制器 | 1.它的功能块有 1.通过private属性和initView把三个TextField和toggle按钮画上去. 2.addView toggleView 3.当clockData改变时,自动执行onModuleUpdate来更新三个textField clockData --> textField 实时传送 4.当鼠标移出testfield的时候。textField -- >clockData 即时传送 | |
10.时钟能走的关键原理是 | 设计一: 在具体view 在主main里面。改动ClockData的time值, 然后view里的显示就会随之改变. 设计二: 但是上面都不是好的方法,可以给ClockData自身加一个realTime属性. 自已不断的更新date到time! | |
第四章 单例模式 | 1.Settings类还需要实验 2小时 2.要把五种用途的例子都总结出来。 5 | |
1.单例模式三要素 | 私有静态属性 公共静态方法 限制被实例化 | |
2.用途 | 焦点 鼠标 历史 窗体深度 资源 | |
3.标准代码 | private static var _instance:MyClass; public static function getInstance():MyClass{ if(_instance == null){ _instance = new MyClass(new SingletonEnforcer())} return _instance } public function MyClass(inforcer:SingletonEnforcer){} 。。。 class SingletonEnforcer{} | |
4.创建Settings类 | 1.类的定义 dynamic public class Settings extends Proxy implements IEventDispatcher{} 2. getInstance() 3. loadSettings() 4. loadSettings的回调方法 5. 获取属性的方法. | |
5 上面例子中我不太懂的地方有 | 1.proxy 2.命名空间 3.getProperty(); | |
第五章 模板方法和工厂模式 | 1.有必要去网上再看向个工厂方法的例子 3小时 2.书里的例子要都能默写 4小时 | |
1.工厂模式的用途 | 1.用于在不指定具体类型的前提下创建类的对象 | |
2.如果定义模版方法 | 1.要在抽象类中使用final关键字来定义方法 | |
3.模版方法举例 | 1.public final function iniitiallize():{} | |
4.工厂模式的目的 | 1.连接两个或者多个不同但却相关联的类级别 | |
5.写一个工厂方法 | 1.public function createField():IField{} | |
6.如何选择 | 1.使用模版方法,我们可以创建一个公共的算法,用于定义哪些步骤在哪些具体的子类中定义 2.使用工厂方法,我们可以引发一个抽象类的对象创建,并且将其具体类型实现放置于其子类中。 | |
第六章 代理模式 | 1.要能默写出那向个红色的实验 2 2.再去网上找个几个例子,总结出什么时候能用代理模式 3 3.在牧场和三国两个游戏中找到也使用代理的地方. 3 | |
1.代理模式支持到另一个什么对象的访问 | 图像文件 ,XML ,Flash Remoting Service 。Web服务 | |
2.代理模式和适配器模式facade模式最主要的区别是 | 1.代理模式和对象具有相同的API或接口. 2.而适配器模式用于转换对象的API 3.facade模式用于简化对象的API | |
3.有两种代理 | 虚拟代理 远程代理 | |
4.虚拟代理的定义 | 用于代理那些创建代价昂贵的对象以及那些急于立即使用的对象。直到它被需要的时候,虚拟代理才进行实质的创建或者初始化过程。 在主体创建之前或者正在创建的过程当中,虚拟代理一直代替该对象。直到创建过程结束,它会删除对该主体的直接请求。 | |
5.使用Loader的心得 | 1.虚拟代理给您的操作带来了诸多简便。如果不是虚拟代理,我们还必须等待加载完成才可以把它添加到显示列表中去,也只有当加载完成后,我们才可以给它添加效果 2.注意,Loader类并不代表被加载的图像,它并不是一个纯正的虚假代理器。 Loader类并没有将任何修改应用到图像上去,它只是把这些更改应用在自身。而由于图像是Loader的子类,才进行了这些更改。 | |
6.序列化的两种方式 | 1.将数据传到构造函数里面,传给对应的属性,这是预先序列化 2.还有一种叫做惰性序列化。 | |
7.创建代理 | 当存在getPrice()请求的时候,代理首先会检查Product类实例是否具有price值。如果有,则返回该值;如果没有,代理则在XML对象外部搜索该数据信息,并将该值赋给真正的"product".这就是方法调用的时候,序列化的方式。 | |
8.创建Product代理类 | 要实验能默写P102 正好证实上面的理论 | |
9.代理的用法 | 要实验能默写P104页 | |
10.对于上面代理用法的理解 | 当我们引入多重级对象的复杂数据结构时,使用惰性序列化可以让我们省掉很多麻烦。它可以减少先前发生的序列化数量,让系统运行得更为流畅,它还会排除那那些根本不会请求到的序列化条目 | |
11.远程代理定义 | 远程代理也用于代替一个对象,只不过它代替的一般是远程对象。它可以是和代理分离的swf文件,Flash Remoting服务,SOAP或者REST服务以及其他任意类型的服务。 相对于远程对象,远程代理就扮演着一个本地的角色。 它拥有和远程对象一样的公共方法作为远程资源,代表对该对象的请求。它还负责与远程资源的通信。 | |
12.搜索代理的创建 | 要实验能默写P105 | |
13 搜索代理的用法 | 要实验能默写P106 | |
14.创建远程图片代理的一句话 | 将覆盖callProperty()方法以代理对远程Flicker API的调用。这样,我们可以创建更为灵活的代理 | |
15.创建远程图片代理的方式 | 1.设置类为dynamic 2.该类继承于flash.utils.Proxy类 ,并覆盖callProperty方法。只要有对未定义方法的调用。我们就可以通过callProperty来调用。 3.我们需要实现IEventDispatcher接口.并通过组合添加EventDispatcher功能. 我们只有对未定义方法的调用,我们就可以保存所有的参数并得知方法的名称,然后可以根据方法名称进行反射调用。 | |
16.具体细节详述 | 1.通过callProperty(method:*...para):返回值是method的名字 第一个参数是调用的方法名,para是向这个方法里面传入的参数。 2.把para都存在pendingArr里 3.在callProperty()里面,执行向urlLoader 。向指定url + method +api名发送请求 4.在上面方法的回调函数里面获得了一个包含method名以及众多methodArguemenst[]. 5.再次使用urlLoader 向指定url + method + methodArguments和pendingArr的键值对组成的queryString发送请求 6.在上面的回调函数里得到新的数据,把这个数据作为DataEvent的第四个参数派发出去! | |
第七章 迭代器模式 | 什么时候使用,要从网上找些例子。 3小时 要能默写书中的例子 2小时 | |
要求 15点前高效完成 不许有误操作 要把标记打好 要写实验心得 | ||
1.目的 | 存取或者访问集合中的每一个组成元素,同时避免存取数据时容易存在的一些问题 | |
2.原来的处理方法的缺点 | 1.把数据直接展现,打破了类的封装性. 2.打破了类型控制 3.而且把数据结构也直接展现了 4.每一个集合对象都拥有自己的游标,因此不能多次同时对集合对象数据进行迭代 5.集合类需要定义数据的每一种迭代方式 | |
3.迭代器模式的优点 | 可以在保持良好封装的前提下,不必展示数据结构就可以对集合元素进行迭代。 迭代器模式将迭代的功能转嫁给另外一个新对象,这样,集合类就非常简单,我们可以多次同时对集合进行迭代。 | |
4.组成元素 | 1.迭代器接口 2.迭代器 3.集合接口 4.集合 | |
5.在集合接口的写法 | public interface ICollection{ function iterator(type:String = null):IIterator; } | |
6.null迭代器 | 在迭代器中,hasNext()返回false next()返回null 在组合模式中,叶子元素就是null迭代器 | |
第八章 组合模式 | 1. 那个文件系统有必要自己默写一遍 2小时 2. 上网再找个例子看 2小时 | |
1.用途 | 处理递归以及构建分组数据结构 | |
2.组合元素具有下列几种元素 | 1.元素接口 2.实现元素接口的抽象接口 3.组合元素 叶子元素 | |
3.元素接口 | public interface ISystemItem{ function iterator():IIterator; function addItem(item:ISystemItem); function removeItem(item:ISystemItem); function getName():String function setName(name:String); function setParent(parent:ISystemItem); function getParetn():ISystemItem; } | |
4.实现元素接口的抽象类 | 1. 要实现了getName setName setParent getParent这几个方法。 这样在File 和 Directory 类中就不必实现这四个方法了. | |
第九章 装饰器模式 | 1.俄罗斯娃娃~ 2.要再从网上找两个例子加深理解 2小时 3.IReader 和 可视化 这两个要能默写 . 3小时 | |
1.作用 | 1.使用装饰器模式,我们可以在运行时将新行为应用到对象上,它使用的是组合而不是继承来给对象添加新的行为。 | |
2.使用继承的弊端 | 1.不能在运行时更改对象的行为。 2.随着交换次数的增加,需要对类的数量进一步管理。 | |
3.基本思想 | 新对象类型(装饰器)可以添加新的行为或者更改被装饰对象已存在的行为。 装饰器和装饰对象实现的是同一个接口,这样保证了它们之间的可互换性. | |
4.装饰器模式有四部分 | 1.装饰接口 2.装饰类 3.抽象装饰器类 4.装饰器类 | |
5.装饰器和装饰对象的关系 | 它们的区分并不十分清晰。装饰器是使用组合在运行时添加或修改另一个对象行为的对象。而被添加或者修改行为的对象称之为装饰对象。而装饰器对象又可以被其他装饰器来装饰。 因而两者实现同一接口至关重要。 | |
6.抽象装饰器类 | 1.一个装饰器需要做的也就是实现和装饰类型一样的接口。可是,多数装饰器继承的抽象装饰器类中都有一些基本功能,如组合装饰对象以及通过方法调用来传递。 2.构造函数使用了IWidget类型的参数,也就是装饰器将装饰的对象。尽管并没有要求通过构造函数来传递被装饰对象。但这是一种习惯性的做法。 3.装饰器的decorated属性设置为protected 这可以保证其子类的可访问性. | |
7.装饰器 | 1.通常, 装饰器和装饰对象通过继承于抽象装饰器类来实现其拥有同一个接口的目的。装饰器类需要实现的功能有: a.对已有行为的修改。装饰器经常代理对装饰方法的请求。当然,装饰器可以将请求简单地发送给装饰对象,并且装饰器还可以进行预处理和后处理。装饰器还可以在装饰器层级上同时处理所有的请求,而不必将这些请求发送给装饰对象。 b.添加新行为,装饰器不仅需要实现接口,还可以添加新行为。这是一个可选项。添加新行为的优势在于我们可以在运行进给对象添加新的功能。可是,添加新方法也就意味着我们不能有效形成装饰器链。 | |
8.做一个大实验Reader | 要默写下来 1.装饰类接口 IReader extends EventDispatcher 2.抽象装饰类 AbstractReader extends EventDispacher 比IReader加了一个index和reset() 3.具体装饰类 StringReader extends AbstractReader a.加一个_content b.重写几个读写方法 c.重写hasNext() d.还可以用FileReader 4.抽象装饰器类 AbstractReaderDecorator extends AbstractReader a.加一个_content:IReader b.重写几个读写方法时,用this._content的方法,即可以说委托了所有的请求 5.具体装饰器类 WordReaderDecorator exntends AbstractReaderDecorator a.加一个_words:Array b.在构造函数中,首先使用super(read)把传入的read入到父类属性_content中,接着调用父类方法再用RegExp把数据传换成想要的数据传入_word c.利用_word重写几个主要的读写方法. d.装饰器类可以很多种。 还可以有LinesReaderDecorator ,还可以有可以用来装饰装饰器类的SorteReaderDecorator | |
9.做第二个大实验 可视化装饰器. 可交换装饰器. | 1.要定义一个公共的抽象父类 2.具体装饰类 extends 抽象父类 3.装饰器DraggableDecorator extends 抽象父类 4.装饰器BevelDecorator extends 抽象父类 5.装饰器ColorableDecorator extends 抽象父类 6.装饰器ResizerDecorator extends 抽象父类 | |
第十章 命令模式 | 1.用途我只找到了一个,其它的我不懂,需要上网再找一个例子。 2小时 2.这个棋盘功能,找空我得完整写一遍,最好能默写下来 。4小时 | |
1.命令模式的用途 | 1.构建高重用性组件。命令模式将初始化器的功能进行解耩。使用命令模式的组件可以直接使用实现了正确接口的对象,因而具有极高的可扩展性。 2.请求队列。当操作依照某一种时序发生时,它们必然要形成请求队列。命令模式可以将请求封装在对象内部。而数组或者其它集合却不支持请求队列。 3.撤消和重做。命令模式可以存储于内存当中,因而操作的历史均被保存下来。实现undo()和redo()方法,就可以给任何一个应用添加撤销和重做功能。 4.处理“事务”或者“向导”操作。每个操作都由多个步骤组成。如果其中一个步骤失败,就需要对所有已经发生的更改进行回滚操作。命令模式可以延迟执行或通过使用对象的undo()方法回滚所有已经发生的操作. | |
2.命令模式的元素 | 1.命令接口 2.具体接口 3.接收者 4.用户 5.调用者 | |
3.接口 | 1.ICommand 里面只有一个excute() 2.IUndoableCommand extends ICommand 里面有一个undo() 3.IRedoableCommand extends ICommand 里面有一个redo() | |
4.具体的命令和接收者 | 就像这样: public class ...Command implements ICommand{ private var _receiver:DisplayObject; public function .....Command(receiver:DisplayObject):void{ this._receiver = receiver; } public function excute():void{ this._receiver.rotation += 20; } } | |
5.用户和调用者 | 1.它们可以是一个对象 2.通过main就是客户,一个按钮都就是调用者 | |
6.4+1+1 按钮实验心得 | 1.要被执行的对象要传入具体的命令,作为一个私有属性。还有一个excute undo 或 redo方法 2.当_command.excut()的时候。执行CommandStack.getInstance().putCommand(_command); 3.在执行undo的时候,这样写代码 var stack:CommandStack = CommandStack.getInstance() for(stack.hasPreviousCommands){ var command:ICommand = stack.previous(); if(command is IUndoableCommand){ IUndoableCommand(Command).undo(); } } | |
7.CommandStack | 1.它是一个单例类。 2.它有两个private属性 _commands:Array _index:uint 3.五个公共方法 putCommand() hasPrevious() hasNext() previous() next(); | |
第十一章 备忘录模式 要到17点半 | 1.要能完全默写 1小时 2.这个备忘录想要在命令模式的棋盘例子中实现,因为上面的没有看懂,所以这个也没有办法看。 2小时 | |
1.目的 | 在不破坏封装性的前提下,把对象的当前状态都保存下来 | |
2.三组成 | 备忘录memento 原发器originator 负责人caretaker | |
3.实验主心得 | 1.负责人保存备忘录。即准备一个_previousMementos:Array _nextMementos:Array 当原发器状态发生变化是,把备忘录在上两个Array中交替存起来,还要在恢复的时候调用原发器执行.setMement() 2.原发器originator 里必须有用于获取备忘录和设置备忘录的方法。getMemento():备忘录接口{} 3.备忘录 里面有记录要备忘对象的状态的私有属性,有相应的get方法,没有set方法 | |
4.实验副心得 | 1.原发器,即在要改变状态的对象里面。 2.备忘录。即保存会改变的状态的一个类 ,里面只有get,没有set 3.负责人。其实就是主应用。里面有两个专门用来保存memento的类数组。在原发器状态改变的时候,存储它的备忘录状态到备忘录数组中。要用的时候,又重新从备忘录数组中取出来,用原发器中的setMemento()方法来执行 | |
第十二章 状态模式 | 1.状态模式的功能不可小觑 2.这两种方式,最好还能做从网上找两个例子来理解和默写 3 3.变迁两种方式的选择理论,我没有看懂! 2 | |
20:00 前看完状态模式 | ||
1. 目的 | 1.当对象内部状态发生更改的时候,状态模式支持该对象更改自己的行为。 2.对象类的更改 | |
2.实现方式 | 1.有很多种 接口方式 抽象类的方式 | |
3.第一种方式状态封装实验心得 | 1.建立状态接口,接口中有主要方法 2.实现上面的状态接口。可以写几个状态类 3.所有状态对象的代理类 ShooterStateMathine 。它实现了所有状态的相同方法,并代理对当前状态对象的调用。这同样适用于转换状态。 4.代理类中要有的东西 1.私有接口实例 2.表示状态的公共静态属性 3.用聚合的方式写状态接口中的方法 4.setState 不同的状态返回不同的状态对象 | |
4.上一条中最后一步关于创建和销毁状态对象的方法 | 1.在setState中有switch的方式。因为我们只是在需要的时候才创建这些状态,这样就避免去创建那些永远不被使用的状态. 2.在构造函数中创建所有的状态对象,并更改当前状态的引用.当我们需要在状态切换中保存一些数据信息的时候,这种方式就非常有用。上面那种方法,有利于内存管理,但是创建了太多的对象。如果系统需要频繁地更改状态,那么更适于使用第二种方式,这样,只用创建对象一次。 | |
5.第二种方式抽象类用法 | 1.把上例中接口中的方法再加上calculate shoot都抽象到抽象类中。其中 calculate和shot都详写 2.继承上面的抽象类,来写三个状态对象。只需要实现抽象类里的抽象方法。 3.状态自动机的内容 1.私有抽象类实例 2.表示状态的公共静态属性. 3.用聚合的方式写状态对象中的方法。 4.用聚合的方式写抽象类中的某些方法. 5.setState() 不同的状态返回不同的状态对象。 | |
6.变迁的方式 | 1._stateList:Array _index:int 2.第一种方式是在状态自动机里写。当执行一次动作就改变一次index 3.第二种方式是在状态对象里写.首先要在状态对象里重写抽象父类的用来执行动作的方法,在这个方法里改变状态字符串。 4.上两种方式的选择: a.如果希望同等看待所有的变迁.并拥有触发变迁的一系列方法,那么就可以直接使用状态机对其进行操作管理。不过,如果触发一个变迁的状态都有不同标准的时候,在状态对象中定义变迁的方法将给我们带来极大的便利以及灵活性 没看懂 | |
第十三章 事件 | ||
1.事件有两种基本类型 | 用户事件 和 系统事件 | |
2.观察者模式 | 很重要,但是ActionScript内置的事件模型已经解决了观察者模式。 | |
3.target 和 currentTarget | 1.target是引发事件的对象,而currentTarget是监听器注册的对象。 2.在目标阶段,它们俩引用的是同一个对象。可是如果您在捕获或者冒泡阶段获取一个对象,那么这两个属性一定是不同的。 | |
4.preventDefault() isDefaultPreventedI() | 1.调用事件对象的preventDefault()方法就可以停止默认行为 2.通过isDefaultPrevented()方法可以查看当前默认行为的状态.。只有事件的cancelable属性设置为true时,事件才可以被取消。 | |
5.停止事件传播 | 1. stopPropagation ,事件将不再继续出现在显示列表中。但currentTarget允许完成监听器的事件激发. 2. stopImmedietePropagation方法则彻底阻止了事件流。 | |
第十四章 发送和加载数据 | 1.有必要把所有的通信总结一下 4小时 | |
1.发送变量 | 1.用?index = 0; 2.用URLRequest.data = URLVariables(); 这时候URLRequest.method = URLRequestMethod.POST; | |
2.加载变量 | 1.URLLoader.dataFormat 有三种 text variables binary | |
3.发送和加载XML | URLRequest.contentType = "text/xml"; | |
4.Web服务的用法 | 1.flex 里的 mx.rpc.soap.WebService 2.在ActionScript 中编写Web服务框架。。。。。。没看懂p282 3.对服务器端脚本的标准请求可以调用Web服务。。。。。。没看懂 4.手动创建并解析SOAP请求和响应. | |
5.远程Flash和Web服务的区别 | p283 1.远程flash使用AMF,作为对数据打包的协议。AMF是SOAP的二进制形式,其性能优于SOAP。SOAP代价较高,增加了带宽的需求。而AMF以更紧凑的方式(二进制)发送数据 2.Flash Player 内在支持AMF 格式。除了应用于远程Flash之外。AMF还应用于共享对象和本地连接。Flash Player内在支持AMF格式,因而初始ActionScript类型的序列和解序列化都是自动的,快速进行的。 3.多数服务器技术并不支持AMF格式,但在在服务器端添加AMF网关并非难事。该网关同时支持多数平台,比如.ColdFusion Java Perl .NET 和 PHP 另外还有可信的,预企业版开源版本。 | |
6.远程flash的基本原理 | p283 1.远程flash有两个元素相互通信 客户端和服务端 2.服务器端通常是一个已经存在的,可应用于Flash 远程访问的类。 flash 远程访问是请求-响应模型。也就是说,客户端必须初始化所有的请求。 3.flash 远程访问的网关产品很多。 OpenAMF WebORB AMFPHP 每一种情况下,都需要知道服务器的网关地址。而特定网关的文档则会告诉您何处可以找到正确的资源. | |
7.flash远程调用 | NetConnection.connect(); NetConnection.call("method",new Responder(result,fault),para......) | |
8.通信优化的方法 | 1.数据缓存。 2.请求队列和队列池. | |
9.数据缓存的方式 | 1.一次请求所有的数据 2.一次只请求一个用户需要的数据(使用之后,缓存这些数据); | |
9.2的实验 | p288 在书上写了实验过程标注。但还是不能完全理解 需要做实验。 | |
10.论述请求队列和队列池 | 1.有大量服务调用的时候,方法有二 一是一个接一个 ,即把请求排队,然后依次调用。上面那个实验就是这个。因为两个调用有依赖关系。 二是全部一起调用 .队列池。很少用到,但是它确实可以明显降低网络的负荷。如果几种服务调用之间不存在任何依赖关系,那么最好一次调用所有方法. |