grasp: 设计带职责的对象

147
GRASP: 设设设设设设设设 设设设 [email protected] 设设设设设设设设

Upload: aulani

Post on 27-Jan-2016

161 views

Category:

Documents


1 download

DESCRIPTION

GRASP: 设计带职责的对象. 徐迎晓 [email protected] 复旦大学软件学院. 设计带职责的对象. 交互设计和职责分配的质量决定系统的质量 可维护性 可理解性 可重用性 可扩展性 好的面向对象设计原则可用于交互图设计和职责分配 — GRASP 模 式. GRASP :通用职责分配软件模式 General Responsibility Assignment Software Patterns 将职责分配给对象的基本原则. GRASP: 设计带职责的对象. 五个 GRASP 模式 应用 G RASP 实现 Process Sale 用例 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: GRASP: 设计带职责的对象

GRASP: 设计带职责的对象

徐迎晓[email protected]

复旦大学软件学院

Page 2: GRASP: 设计带职责的对象

设计带职责的对象交互设计和职责分配的质量决定系统的质量可维护性可理解性可重用性可扩展性

好的面向对象设计原则可用于交互图设计和职责分配— GRASP 模式

Page 3: GRASP: 设计带职责的对象

GRASP :通用职责分配软件模式 General Responsibility Assignment

Software Patterns

将职责分配给对象的基本原则

Page 4: GRASP: 设计带职责的对象

GRASP: 设计带职责的对象

五个 GRASP 模式应用 GRASP 实现 Process Sale 用例可见性设计类图设计

Page 5: GRASP: 设计带职责的对象

五个 GRASP 模式

. Low Coupling

. High Cohesion

. Controller

. Creator

. Information Expert

Page 6: GRASP: 设计带职责的对象

模式: Low Coupling

Problem :如何降低依赖、减少改变的影响,增加重用性 ?

Solution: 分配职责时使耦合低

Page 7: GRASP: 设计带职责的对象

原理:耦合表明两个类之间连接的强度,一个类是

否依靠其他类A 具有低耦合,则 A 不依赖很多其他的类

高耦合带来的问题其他类改变则可能自己也必须改变单独(无其他类时)难以理解由于需要很多其他类,难以重用

Page 8: GRASP: 设计带职责的对象
Page 9: GRASP: 设计带职责的对象

举例 we have a need to create a Payment instance and associate it with the Sale.

谁来创建 Payment 实例 ?

Page 10: GRASP: 设计带职责的对象
Page 11: GRASP: 设计带职责的对象
Page 12: GRASP: 设计带职责的对象
Page 13: GRASP: 设计带职责的对象

两种都假定 Sale 和 Payment 之间有关联, register 创建则增加关联,不好

Page 14: GRASP: 设计带职责的对象

讨论

低藕合模式常与专家、高内聚一起使用是基本目标,所有设计决策中都要考虑中等层度的藕合是正常和必需的(对象之间需要连接以便协作)优点:不受其他组件变化的影响,易于理解,易于重用

Page 15: GRASP: 设计带职责的对象

类 X 和类 Y 之间常见的藕合X 有属性引用 Y 的实例X 对象调用 Y 对象的服务X 的方法引用 Y 的实例(参数,局部变量,

返回值 )X 是 Y 直接或间接子类Y 是接口, X 实现 Y

Page 16: GRASP: 设计带职责的对象

But 对稳定元素的藕合和普遍的元素藕合很少会有问题如类库

Page 17: GRASP: 设计带职责的对象

五个 GRASP 模式

. Low Coupling

. High Cohesion

. Controller

. Creator

. Information Expert

Page 18: GRASP: 设计带职责的对象

模式: Hign Cohesion

Problem: 如何使复杂性可管理 ?

Solution: 分配职责时使内聚度高

Page 19: GRASP: 设计带职责的对象

内聚:类的职责如何紧密关联类或子系统等若职责紧密关联,且没有大量

的工作,则具有高内聚度高内聚则方法的数量相对较少若 task is large, 则与其他对象协作低内聚说明类做了很多无关的事情,或做了

太多的事情低内聚的问题:难以理解,重用,维护,易

受变化的影响

Page 20: GRASP: 设计带职责的对象

不独立使用,而是与专家、低藕合模式一起使用评估所有设计决策的一个准则

Register 做很多系统操作,下图哪个好?

Page 21: GRASP: 设计带职责的对象
Page 22: GRASP: 设计带职责的对象

RDB-RPC-Interface class responsible for interacting with relational

databases and for handling remote procedure calls

(two vastly different functional areas)

Page 23: GRASP: 设计带职责的对象

RDBInterface classcompletely responsible for interacting with

relational databases.hundreds or thousands of methods(all

related)A lot of supporting code

Page 24: GRASP: 设计带职责的对象

RDBInterface classOnly partially responsible for interacting

with relational databases interacts with a dozen other classes

related to RDB access

Page 25: GRASP: 设计带职责的对象

Company classcompletely responsible for (a) knowing its

employees and (b) knowing its financial information.

total number of public methods is small the amount of supporting code is small

Page 26: GRASP: 设计带职责的对象

可低内聚的场合

grouping of responsibilities or code into one class or component to simplify maintenance by one person只有 1 , 2 个 SQL 专家,对 OO 不熟

software architect may decide to group all the SQL statements into one class, RDBOperations

Page 27: GRASP: 设计带职责的对象

可低内聚的场合 2distributed server objects less remote calls, and better performance.

远程服务器对象要 fewer and larger, less cohesive ,为很多操作提供接口

远程操作粗粒度,以便一次 remote operation call 可以做或请求更多的工作

Example 1: remote object with three fine-grained operations setName, setSalary, and setHireDate

Example 2: one remote operation setData which receives a set of data

Which is better?

Page 28: GRASP: 设计带职责的对象

五个 GRASP 模式

. Low Coupling

. High Cohesion

. Controller

. Creator

. Information Expert

Page 29: GRASP: 设计带职责的对象

模式 :Controller

Problem: 谁负责处理系统输入事件 ?

Solution: 将处理系统输入事件的职责分配给代表以下的类: 代表整个系统、设备或子系统 - 外观

Controller ( facade controller ) 代表整个业务过程或组织( facade controller ) 代表现实世界中可能执行该任务的角色 (role

controller) 代表系统事件发生的用例场景, (use-case or

session controller)

Page 30: GRASP: 设计带职责的对象

Problem:The UI & domain layers should be loosely

coupledWhich object should coordinate msgs

between the UI and other domain objects?Solution (advice):

Assign responsibility to an object representing..

The ‘system’ or a ‘root’ object (Store, Bank) A device/subsystem (AccountingSystem,

BankATM) A use case scenario (GameHandler) ‘Single channel of communication between layers’

Page 31: GRASP: 设计带职责的对象

“window,” “applet,” “widget,” “view,” and “document” 不是控制器,而是将事件发往控制器系统操作在设计时通常交给控制器

Page 32: GRASP: 设计带职责的对象
Page 33: GRASP: 设计带职责的对象

可供选择的代表整个系统、设备或子系统

Register, POSSystem代表整个业务过程或组织

Store代表现实世界中可能执行该任务的角色

Cashier代表系统事件发生的用例场景

ProcessSaleHandler

Page 34: GRASP: 设计带职责的对象
Page 35: GRASP: 设计带职责的对象

整个系统、设备或子系统

Page 36: GRASP: 设计带职责的对象

系统事件发生的用例场景

Page 37: GRASP: 设计带职责的对象

讨论

大多数系统接受外部输入事件 (GUI,传感器信号 ,…)

一个用例中所有系统事件用一个控制器处理,不同用例用不同控制器控制器通常将将需要做的工作委托给其他对象,自己并不做很多工作

Page 38: GRASP: 设计带职责的对象

优点业务处理由业务对象完成,而不是把图形界

面作为控制器,这样可重用性高将控制器的职责委托给各个领域类,支持逻辑重用但要防止控制器过于臃肿可用多个控制器可用角色控制器或用例控制器,而不是

facade controller

Page 39: GRASP: 设计带职责的对象
Page 40: GRASP: 设计带职责的对象

图形界面

Page 41: GRASP: 设计带职责的对象

不好的做法

Page 42: GRASP: 设计带职责的对象

五个 GRASP 模式

. Low Coupling

. High Cohesion

. Controller

. Creator

. Information Expert

Page 43: GRASP: 设计带职责的对象

模式: CreatorProblem: 谁负责创建新的对象 ?

Solution: 如果满足以下条件之一,则将创建类 A 的实例的职责分配给

类 B B 聚合 A 对象 B包含 A 对象 B contains A objects. B记录 A 对象 (前三个最常用 ) B 紧密使用 A 对象 B 具有创建 A 对象时需要传入的初始化数据

B 是 A 的 Creator 如果有多个类满足条件,优先选择聚合或包含关系

Page 44: GRASP: 设计带职责的对象

Name: Creator Problem: Who creates an A? Solution: (this can be viewed as advice) Assign class B the responsibility to create an instance of class A if one of these is true (the more the better):

B "contains" or compositely aggregates A.

B records A.

B closely uses A.

B has the initializing data for A.

Page 45: GRASP: 设计带职责的对象

举例

谁负责创建 SalesLineltem 对象 ?

Page 46: GRASP: 设计带职责的对象
Page 47: GRASP: 设计带职责的对象
Page 48: GRASP: 设计带职责的对象

讨论低耦合 对依赖的维护少 可重用性高简明,封装But 若出于性能考虑使用回收的实例,或根据外部的值从一组类似的类中挑选一个创建实例 建议将创建工作交给 helper class----Factory ,而

不使用本模式

Page 49: GRASP: 设计带职责的对象

五个 GRASP 模式

. Low Coupling

. High Cohesion

. Controller

. Creator

. Information Expert

Page 50: GRASP: 设计带职责的对象

模式: Information Expert

Problem OOD 中分配职责最基本的原则是什么 ?

Solution 将职责分配给 Information Expert (拥有完成该职责所需要信息的类)

Page 51: GRASP: 设计带职责的对象

1. 如果设计模型存在相关的类,则到领域模型中查找2. 否则,查看领域模型,应用或扩展领域模型得到相应的设计类

Page 52: GRASP: 设计带职责的对象

画交互图时碰到的问题:计算总价 ( 总计, grand total )的职责分配给谁 ? 检查领域模型或设计模型

Page 53: GRASP: 设计带职责的对象

计算总价需 要知道所 有销售条目( SalesLineltem )及其各个条目的总价( subtotals )之和Sale包含 SalesLineltem这些信息——所以计算总价( grand total )的职责分配给Sale。

Page 54: GRASP: 设计带职责的对象

此时对交互图和类图可以增加哪些内容 ?

Page 55: GRASP: 设计带职责的对象
Page 56: GRASP: 设计带职责的对象

各个条目 的总价( subtotals. ) 分 配 给谁 ?需要知道数量 SalesLineltem.quantity 和单价

ProductSpecification.price

分配给 SalesLineltem

Page 57: GRASP: 设计带职责的对象

交互图和类图增加什么内容 ?

Page 58: GRASP: 设计带职责的对象
Page 59: GRASP: 设计带职责的对象

获取单价的职责分配给谁 ?

ProductSpecification包含该信息

Page 60: GRASP: 设计带职责的对象

最终通过 Information Expert 模式得到的职责分配为了能得到总价的信息:

Page 61: GRASP: 设计带职责的对象

最终通过 Information Expert 模式得到的协作图

Page 62: GRASP: 设计带职责的对象

讨论模式 Information Expert

来自直觉 -- 对象做的事情总是与其拥有的信息有关常需要多个对象协作

But 影响耦合和内聚时,可能不使用Expert将销售保存的数据库的职责分配给谁 ?

Page 63: GRASP: 设计带职责的对象

优点

低耦合 -- 对象用自己的信息,封装性好高内聚 - 行为分布在具有所需信息的类上,易于理解和维护

Page 64: GRASP: 设计带职责的对象

GRASP: 设计带职责的对象

五个 GRASP 模式应用 GRASP 实现 Process Sale 用例可见性设计类图设计

Page 65: GRASP: 设计带职责的对象

应用 GRASP 实现 Process Sale 用例

Page 66: GRASP: 设计带职责的对象

enterItem(itemID, quantity)

:System: Cashier

endSale

makePayment(amount)

a UML loop interaction frame, with a boolean guard expression

external actor to system

Process Sale Scenario

system as black box

the name could be "NextGenPOS" but "System" keeps it simple

the ":" and underline imply an instance, and are explained in a later chapter on sequence diagram notation in the UML

a message with parameters

it is an abstraction representing the system event of entering the payment data by some mechanism

description, total

return value(s) associated with the previous message

an abstraction that ignores presentation and medium

the return line is optional if nothing is returned

total with taxes

change due, receipt

makeNewSale

[ more items ]loop

Page 67: GRASP: 设计带职责的对象

先为每个系统操作创建独立的图,将每个系统事件作为起始消息若图太复杂,分解成小的图使用系统操作合约和用例描述作为起点,使用 GRASP 等模式

Page 68: GRASP: 设计带职责的对象
Page 69: GRASP: 设计带职责的对象

Controller

协作图:每个系统事件要画一个

Page 70: GRASP: 设计带职责的对象

顺序图:可在一张图上

Page 71: GRASP: 设计带职责的对象

太长的也可每个系统事件 分开

Page 72: GRASP: 设计带职责的对象

enterItem(itemID, quantity)

:System: Cashier

endSale

makePayment(amount)

a UML loop interaction frame, with a boolean guard expression

external actor to system

Process Sale Scenario

system as black box

the name could be "NextGenPOS" but "System" keeps it simple

the ":" and underline imply an instance, and are explained in a later chapter on sequence diagram notation in the UML

a message with parameters

it is an abstraction representing the system event of entering the payment data by some mechanism

description, total

return value(s) associated with the previous message

an abstraction that ignores presentation and medium

the return line is optional if nothing is returned

total with taxes

change due, receipt

makeNewSale

[ more items ]loop

Page 73: GRASP: 设计带职责的对象

makeNewSale

Page 74: GRASP: 设计带职责的对象
Page 75: GRASP: 设计带职责的对象
Page 76: GRASP: 设计带职责的对象

:Register

makeNewSale

:Salecreate

Register creates a Sale by Creator

create lineItems :List<SalesLineItem>

by Creator, Sale creates an empty collection (such as a List) which will eventually hold SalesLineItem instances

by Creator and Controller

this execution specification is implied to be within the constructor of the Sale instance

Page 77: GRASP: 设计带职责的对象

enterItem(itemID, quantity)

:System: Cashier

endSale

makePayment(amount)

a UML loop interaction frame, with a boolean guard expression

external actor to system

Process Sale Scenario

system as black box

the name could be "NextGenPOS" but "System" keeps it simple

the ":" and underline imply an instance, and are explained in a later chapter on sequence diagram notation in the UML

a message with parameters

it is an abstraction representing the system event of entering the payment data by some mechanism

description, total

return value(s) associated with the previous message

an abstraction that ignores presentation and medium

the return line is optional if nothing is returned

total with taxes

change due, receipt

makeNewSale

[ more items ]loop

Page 78: GRASP: 设计带职责的对象

enterItem

UC3. Cashier enters item identifier.4. System records sale line item and presents item description, price, and running total.

Page 79: GRASP: 设计带职责的对象
Page 80: GRASP: 设计带职责的对象
Page 81: GRASP: 设计带职责的对象
Page 82: GRASP: 设计带职责的对象
Page 83: GRASP: 设计带职责的对象

2: makeLineItem(desc, qty)enterItem(id, qty)

1: desc = getProductDesc(id) 2.1: create(desc, qty)

1.1: desc = get(id)

:Register :Sale

:ProductCatalog

sl: SalesLineItem

lineItems : List<SalesLineItem>

: Map<ProductDescription>

2.2: add(sl)

by Expert

by Controllerby Creator

add the newly created SalesLineItem instance to the List

Page 84: GRASP: 设计带职责的对象

enterItem(itemID, quantity)

:System: Cashier

endSale

makePayment(amount)

a UML loop interaction frame, with a boolean guard expression

external actor to system

Process Sale Scenario

system as black box

the name could be "NextGenPOS" but "System" keeps it simple

the ":" and underline imply an instance, and are explained in a later chapter on sequence diagram notation in the UML

a message with parameters

it is an abstraction representing the system event of entering the payment data by some mechanism

description, total

return value(s) associated with the previous message

an abstraction that ignores presentation and medium

the return line is optional if nothing is returned

total with taxes

change due, receipt

makeNewSale

[ more items ]loop

Page 85: GRASP: 设计带职责的对象

endSale

Cashier repeats steps 3-4 until indicates done. 指示重复5. System presents total with taxes calculated.

Page 86: GRASP: 设计带职责的对象

endSale

Page 87: GRASP: 设计带职责的对象
Page 88: GRASP: 设计带职责的对象

:RegisterendSale( s :Sale1: becomeComplete

by Expertby Controller

Page 89: GRASP: 设计带职责的对象
Page 90: GRASP: 设计带职责的对象
Page 91: GRASP: 设计带职责的对象

:Saletot = getTotal 1 *[ i = 1..n]: st = getSubtotal

:ProductDescription

1.1: pr = getPrice

lineItems[ i ] :SalesLineItem

«method»public void getTotal(){ int tot = 0; for each SalesLineItem, sli tot = tot + sli.getSubtotal(); return tot}

Page 92: GRASP: 设计带职责的对象

enterItem(itemID, quantity)

:System: Cashier

endSale

makePayment(amount)

a UML loop interaction frame, with a boolean guard expression

external actor to system

Process Sale Scenario

system as black box

the name could be "NextGenPOS" but "System" keeps it simple

the ":" and underline imply an instance, and are explained in a later chapter on sequence diagram notation in the UML

a message with parameters

it is an abstraction representing the system event of entering the payment data by some mechanism

description, total

return value(s) associated with the previous message

an abstraction that ignores presentation and medium

the return line is optional if nothing is returned

total with taxes

change due, receipt

makeNewSale

[ more items ]loop

Page 93: GRASP: 设计带职责的对象

makePayment

8. System logs completed sale and sends sale and payment information to the external Accounting system and Inventory system

Page 94: GRASP: 设计带职责的对象
Page 95: GRASP: 设计带职责的对象

Make Payment :Creating the Payment

Page 96: GRASP: 设计带职责的对象

1: makePayment(cashTendered)

1.1: create(cashTendered)

:Register :Sale

:Payment

makePayment(cashTendered)

by Controller by Creator and Low Coupling

Page 97: GRASP: 设计带职责的对象

Make Payment :Logging a Completed Sale

Who is responsible for knowing all the logged sales, and doing the logging?

Page 98: GRASP: 设计带职责的对象
Page 99: GRASP: 设计带职责的对象
Page 100: GRASP: 设计带职责的对象

1: makePayment(cashTendered)

1.1: create(cashTendered)

:Register s :Sale

:Payment

makePayment(cashTendered)

:Store

2: addSale(s)

completedSales: List<Sale>

2.1: add(s)

by Expert

note that the Sale instance is named's' so that it can be referenced as a parameter in messages 2 and 2.1

Page 101: GRASP: 设计带职责的对象

makePayment:Calculating the Balance

The Process Sale use case implies that the balance due from a payment be printed on a receipt and displayed somehow.

Page 102: GRASP: 设计带职责的对象

7a. Paying by cash:1 收银员输入收取的现金数额2 系统给出应找的余额,并弹出现金抽屉3 收银员放入收取的现金,并拿出应找的余额给顾客

4 系统记录现金支付

Page 103: GRASP: 设计带职责的对象

Model-View Separation principle, we should not concern ourselves with how the balance will be displayed or printed

Page 104: GRASP: 设计带职责的对象
Page 105: GRASP: 设计带职责的对象

s :Sale pmt: Payment1: amt = getAmountbal = getBalance

2: t = getTotal

{ bal = pmt.amount - s.total }

Page 106: GRASP: 设计带职责的对象

startUp

Page 107: GRASP: 设计带职责的对象

StartUp 的开始

Page 108: GRASP: 设计带职责的对象

The startUp system operation occurs when a manager powers on the POS system and the software loads.

control will remain in the UI layer (such

as a Java JFrame) after the initial domain object is created.

Page 109: GRASP: 设计带职责的对象

Choosing the Initial Domain Object

Page 110: GRASP: 设计带职责的对象

StartUp启动时对数据库的操作

ProductSpecification 实例存储在存储介质如关系数据库或对象数据库中StartUp 时,若 ProductSpecification 对象数量不多,可全部加载到内存

若很多,消耗内存和时间太多,可在需要时才装载

Page 111: GRASP: 设计带职责的对象

StartUp 创建其他哪些对象

Page 112: GRASP: 设计带职责的对象
Page 113: GRASP: 设计带职责的对象
Page 114: GRASP: 设计带职责的对象

:Store :Register

pc:ProductCatalog

create 2: create(pc)

1: create

1.2: loadProdSpecs()

descriptions:Map<ProductDescription>

1.1: create

1.2.2*: put(id, pd)

1.2.1*: create(id, price, description)

pd:ProductDescriptionthe * in sequence number indicates the

message occurs in a repeating section

pass a reference to the ProductCatalog to the Register, so that it has permanent visibility to it

by Creatorcreate an empty collection object

Page 115: GRASP: 设计带职责的对象
Page 116: GRASP: 设计带职责的对象

:Register

Cashier

:ProcessSaleJFrame

actionPerformed( actionEvent )

1: enterItem(id, qty)? system event

UILayer

DomainLayer

presses button

Page 117: GRASP: 设计带职责的对象

:Register

Cashier

:ProcessSaleJFrame

actionPerformed( actionEvent )

1: enterItem(id, qty)

2 [no sale] : s = getSale : Sale

UILayer

DomainLayer

s : Sale

3: t = getTotal

presses button

Page 118: GRASP: 设计带职责的对象

用例实现和 UP

用例实现是 UP 设计模型的一部分建议并行画类图和交互图

初始阶段:设计模型和用例实现通常不做,因为涉及详细的设计决策,而初始阶段尚不成熟细化阶段:创建体系结构上重要的或风险较大的用例实现构造阶段:为剩下的设计问题创建用例实现

Page 119: GRASP: 设计带职责的对象

GRASP: 设计带职责的对象

五个 GRASP 模式应用 GRASP 实现 Process Sale 用例可见性设计类图设计

Page 120: GRASP: 设计带职责的对象

可见性设计

基本判断 :若对象 A 向对象 B 发消息,则 B 必须对 A

是可见的

Page 121: GRASP: 设计带职责的对象
Page 122: GRASP: 设计带职责的对象

四种可见方式

Attribute visibility– B 是 A的属性 Parameter visibility—B 是 A 的方法的参数 Local visibility—B 是 A 的局部对象(非方法的参数) .

• Global visibility—B 是以某种方式全局可见的

Page 123: GRASP: 设计带职责的对象

属性可见

相对永久,最常见

public class Register

{

private ProductCatalog catalog;

}

Page 124: GRASP: 设计带职责的对象

属性可见

Page 125: GRASP: 设计带职责的对象

参数可见

Page 126: GRASP: 设计带职责的对象

相对临时的可见性,只在方法范围内可见可见性的第二种常见形式

Page 127: GRASP: 设计带职责的对象

局部可见

相对临时的可见性,只在方法范围内可见

两种常见情况创建局部实例,并赋给局部变量将方法执行的返回对象赋给局部变量

Page 128: GRASP: 设计带职责的对象
Page 129: GRASP: 设计带职责的对象

全局可见

相对永久的可见性C++全局变量Singleton pattern

Page 130: GRASP: 设计带职责的对象

GRASP: 设计带职责的对象

五个 GRASP 模式应用 GRASP 实现 Process Sale 用例可见性设计类图设计

Page 131: GRASP: 设计带职责的对象

类图设计

Page 132: GRASP: 设计带职责的对象

依据

交互图软件类和方法概念模型 类定义的细节

Page 133: GRASP: 设计带职责的对象

领域模型和设计类图

Page 134: GRASP: 设计带职责的对象

方法

Page 135: GRASP: 设计带职责的对象
Page 136: GRASP: 设计带职责的对象

Method Name Issues

Method Names—createcreate message 不同语言中实现不同

C++ ,自动或 new 调用构造器Java , new 构造器

初始化是常见的 activity, 通常 DCD 中可省略 creation-related methods and constructors from a DCD.

Page 137: GRASP: 设计带职责的对象

Method Names—Accessing MethodsgetXXX(), setXXX()high noise-to-value ratio , for n attributes,

there are 2n uninteresting methods.通常省略

Page 138: GRASP: 设计带职责的对象

Method Names—Multiobjects

Page 139: GRASP: 设计带职责的对象

Method Names—Language-Dependent Syntax生成代码时自动转换成相应的语言格式

Page 140: GRASP: 设计带职责的对象
Page 141: GRASP: 设计带职责的对象

加上关联

Page 142: GRASP: 设计带职责的对象
Page 143: GRASP: 设计带职责的对象
Page 144: GRASP: 设计带职责的对象

Adding Dependency Relationships

depict non-attribute visibility between classes; in other words, parameter, global, or locally declared visibility.

Page 145: GRASP: 设计带职责的对象
Page 146: GRASP: 设计带职责的对象

visibility marker for attribute or method

current iteration does not have many interesting member details; all attributes are private and all methods public.

Page 147: GRASP: 设计带职责的对象

Rose演示