7.4 消息与操作
在序列图中,对象会遵照箭头方向传送消息(message)给另一个对象,因此而引发了接收消息对象的某一项操作。换言之,在序列图中的每一个消息,都可以对应到对象所属类中已经定义好的操作。
 |
| 图7-18 公有操作及私有操作 |
不过,特别需要注意操作的可见度等级,对象仅能调用其他对象公有等级的操作,至于私有等级的操作只有对象本身可以调用,如图7-37所示。定期定额申购(RegularBid)对象中的计算资产(calcAsset)属于公有操作,所以外界可以调用。但是,取得申购单位数量(getUnit)属于私有操作,所以只有定期定额申购对象本身可以调用。
其实,对象本身可以调用任何可见度等级的操作。再看图7-19,取得申购单位数量(getUnit)原属于申购交易(Bid)超类所定义之保护等级的操作,通过泛化关系带来的继承好处,使得定期定额申购(RegularBid)子类的对象也可以调用使用此保护等级的操作。
 |
| 图7-19 保护等级的操作 |
子类可以继承公有等级与保护等级的操作,其所属的对象当然可以调用之。倘若是私有等级的操作,则不可以被子类继承,所以其所属对象也就不能调用了。请看图7-20,申购交易超类定义了一个私有操作,所以定期定额申购子类无法使用此操作,且子类之对象也无法调用之。因此,定期定额申购对象所调用的“取得申购单位数量”(getUnit)操作,其实所属类自行定义的公开操作,而非继承来的私有操作。
 |
| 图7-20 私有操作的继承 |
接着,我们来看“创建消息”(creation message)与“销毁消息”(destruction message)。接收对象收到创建消息时,将执行建构式,进行对象诞生之后的初始化设定。请看图7-21的左图,创建消息的图标是一条带开放箭头的虚线,指向诞生对象,意味着对象是在接收到创建消息之际,才刚诞生。或者,也可以使用如图7-21右图的表示法,采用调用消息的带实心箭头实线,并于其旁标记《create》字眼。
 |
| 图7-21 创建消息 |
销毁消息的图标则是在消息箭头端打上大叉(×),而且存活终止于大叉处。因为对象在收到销毁消息之后,将执行析构式,进行对象消灭之际的设定工作,然后就被消灭、不再存活了,生命线也就终止了,如图7-22所示。
 |
| 图7-22 销毁消息 |
现在,我们来看类图7-23的案例,其对象如图7-24所示。执行一开始将产生五个单期交易(BidItem)对象,计算资产(calcAsset)之后,消灭前两个单期交易对象,然后再一次计算资产,会发现资产降低了,因为已经删除了两个单期交易对象,执行结果如图7-25所示。
 |
| 图7-23 类图 |
 |
| 图7-24 对象图 |
再看此案例的序列图7-26,有几项特别之处,如下所述。
• 创建消息—第1~4号消息,都是创建消息。由于单期交易(BidItem)为定期定额申购(RegularBid)的部分对象(part object),所以仅能由定期定额申购交易负责创建。
• 销毁消息—第16号消息是销毁消息,示意执行完delete之后,单期交易(BitItem)对象就会被删除。不过,此处无法表达仅删掉某几个对象,而非删掉全部对象;从此也可以发现UML图示只能呈现重点,所以我们不用它来表达实况,同时它也无法被用来表达实况。
• 泛化关系—在6号消息中,实际传入的是定期定额申购对象的指针,而非申购交易超类的对象指针。
• 循环片段—循环片段中可以包含另一个循环片段,这是很常见的状况。
• 序列片段与引用片段—标记sd字眼的大方框称为序列片段,可用来框住某一片段的设计,方便引用这段设计。引用时可使用ref字眼的方框,标示出引用之序列片段名称即可。
 |
| 图7-25 执行画面 |
请看图7-27的序列图的局部放大图,我们将消息10~14框住,并命名为calcAsset flow,在16号消息之后引用calcAsset flow片段,意味着消息16之后,会再度执行消息10~14的交互。最后看下述的程序清单7-20~7-30为C++(www.cppentry.com)的源代码,对应图7-26的序列图消息序号处,如下所示。
1. main.cpp中行号13—Account myAccount;
2. main.cpp中行号14—myFund=new Fund(49.61);
3. main.cpp中行号15—myRegularBid=new RegularBid();
4. RegularBid.cpp中行号7~13—myItem=new BidItem(36.72);
5. main.cpp中行号16—myRegularBid>setFund(myFund);
6. main.cpp中行号17—myAccount.setBid(myRegularBid);
7. main.cpp中行号19—myRegularBid->getUnit();
8. RegularBid.cpp中行号23~24—for控制流程及其中的itemObj[i]->getUnit();
. main.cpp中行号20—myFund->getPrice();
10. main.cpp中行号21—myAccount.calcAsset();
11. Account.cpp中行号12~13—for控制流程及其中的bidObj[i]->calcAsset();
12. RegularBid.cpp中行号29—getUnit()
13. RegularBid.cpp中行号23~24—for控制流程及其中的itemObj[i]->getUnit();
14. RegularBid.cpp中行号29—fundObj[i]->getPrice();
15. main.cpp中行号24~25—myRegularBid->delBidItem(0);
16. RegularBid.cpp中行号33—delete itemObj[index];
ref calcAsset flow—重复第10~14号消息的交互片段。
|
| 图7-26 序列图 |
|
| 图7-27 序列片段与引用片段 |
程序清单7-20 Account.h
//// EX07_04
1. // Account.h
2. //
3. #pragma once
4. #include
5. #include
6. #include "Bid.h"
7. using namespace std;
8. class Account
9. {
10. public:
11. void setBid(Bid*);
12. int calcAsset();
13. private:
14. vector bidObj;
15. };
/// EX07_04
第7 章 从序列图到C++(www.cppentry.com) 159
程序清单7-21 Account.cpp
//// EX07_04
1. // Account.cpp
2. //
3. #include "Account.h"
4. void Account::setBid(Bid *theBid)
5. {
6. bidObj.push_back(theBid);
7. }
8. int Account::calcAsset()
9. {
10. int size,theAsset=0;
11. size=bidObj.size();
12. for(int i=0;i13. theAsset=theAsset+bidObj[i]->calcAsset();
14. return theAsset;
15. }
/// EX07_04
程序清单7-22 Fund.h
//// EX07_04
1. // Fund.h
2. //
3. #pragma once
4.
5. class Fund
6. {
7. public:
8. Fund(float);
9. float getPrice();
10. private:
11. float price;
12. };
/// EX07_04
程序清单7-23 Fund.cpp
//// EX07_04
1. // Fund.cpp
2. //
3. #include "Fund.h"
4. Fund::Fund(float thePrice)
5. {
6. price=thePrice;
7. }
8. float Fund::getPrice()
9. {
10. return price;
11. }
/// EX07_04
程序清单7-24 Bid.h
//// EX07_04
14. // Bid.h
15. //
16. #pragma once
17. #include "Fund.h"
18. class Bid
19. {
20. public:
21. void setFund(Fund*);
22. virtual int calcAsset()=0;
23. virtual float getUnit()=0;
24. protected:
25. Fund *fundObj;
26. };
/// EX07_04
程序清单7-25 Bid.cpp
//// EX07_04
9. // Bid.cpp
10. //
11. #include "Bid.h"
12.
13. void Bid::setFund(Fund *theFund)
14. {
15. fundObj=theFund;
16. }
/// EX07_04
程序清单7-26 RegularBid.h
//// EX07_04
1. // RegularBid.h
2. //
3. #pragma once
4. #include
5. #include
6. #include "BidItem.h"
7. #include "Bid.h"
8. using namespace std;
9. class RegularBid : public Bid
10. {
11. public:
12. RegularBid();
13. int calcAsset();
14. float getUnit();
15. void delBidItem(int);
16. private:
17. vector itemObj;
18. };
//// EX07_04
程序清单7-27 RegularBid.cpp
//// EX07_04
1. // RegularBid.cpp
2. //
3. #include "RegularBid.h"
4. RegularBid::RegularBid()
5. {
6. BidItem *myItem;
7. myItem=new BidItem(36.72);
8. itemObj.push_back(myItem);
9. myItem=new BidItem(72.94);
10. itemObj.push_back(myItem);
11. myItem=new BidItem(59.53);
12. itemObj.push_back(myItem);
13. myItem=new BidItem(89.85);
14. itemObj.push_back(myItem);
15. myItem=new BidItem(91.45);
16. itemObj.push_back(myItem);
17. }
18. float RegularBid::getUnit()
19. {
20. int size;
21. float theUnit=0;
22. size=itemObj.size();
23. for(int i=0;i24. theUnit=theUnit+itemObj[i]->getUnit();
25. return theUnit;
26. }
27. int RegularBid::calcAsset()
28. {
29. return getUnit()*fundObj->getPrice();
30. }
31. void RegularBid::delBidItem(int index)
32. {
33. delete itemObj[index];
34. }
//// EX07_04
程序清单7-28 BidItem.h
//// EX07_04
1. // BidItem.h
2. //
3. #pragma once
4. class BidItem
5. {
6. public:
7. BidItem(float);
8. float getUnit();
9. private:
10. float unit;
11. };
/// EX07_04
程序清单7-29 BidItem.cpp
//// EX07_04
1. // BidItem.cpp
2. //
3. #include "BidItem.h"
4. BidItem::BidItem(float theUnit)
5. {
6. unit=theUnit;
7. }
8. float BidItem::getUnit()
9. {
10. return unit;
11. }
/// EX07_04
程序清单7-30 main.cpp
//// EX07_04
1. // main.cpp
2. //
3. #include
4. #include
5. #include "RegularBid.h"
6. #include "Account.h"
7. #include "Fund.h"
8. using namespace std;
9. int main(int argc, char *argv[])
10. {
11. Fund *myFund;
12. RegularBid *myRegularBid;
13. Account myAccount;
14. myFund=new Fund(49.61);
15. myRegularBid=new RegularBid();
16. myRegularBid->setFund(myFund);
17. myAccount.setBid(myRegularBid);
18. cout << "富邦长虹基金单位、净值及总资产为: "
19. << "(" << myRegularBid->getUnit() << ")"
20. << "(" << myFund->getPrice() << ")"
21. << "(" << myAccount.calcAsset() << ")"
22. << endl << endl;
23. cout << "删掉两个单期交易对象,再算一次..." << endl;
24. myRegularBid->delBidItem(0);
25. myRegularBid->delBidItem(1);
26. cout << "富邦长虹基金单位、净值及总资产为: "
27. << "(" << myRegularBid->getUnit() << ")"
28. << "(" << myFund->getPrice() << ")"
29. << "(" << myAccount.calcAsset() << ")"
30. << endl << endl;
31. system("PAUSE");
32. return EXIT_SUCCESS;
33. }
//// EX07_04