129
DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐徐徐 [email protected] 徐徐徐徐徐徐徐徐

DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 [email protected] 复旦大学软件学院

Embed Size (px)

Citation preview

Page 1: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

DESIGNING USE-CASEREALIZATIONS WITH GoF

DESIGN PATTERNS

徐迎晓[email protected]

复旦大学软件学院

Page 2: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

OUTLINE

Adapter

Factory

Singleton

Strategy

Composition

Facade

Observer

Page 3: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Adapter

问题:如何解决接口不兼容问题,几个类似的构件接口不同,如何为其提供稳定的接口 ?

解决:通过中间的适配器对象,将构件原有接口转换成另一个接口

Page 4: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 5: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 6: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 7: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 8: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 9: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 10: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 11: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 12: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

support external third-party services, tax calculators

Page 13: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

support external third-party services, credit authorization services,

Page 14: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

support external third-party services,

inventory systems,

Page 15: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

support external third-party services,

accounting systems,

Page 16: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 17: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 18: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Adapter pattern 是 GRASP building blocks 的特例It offers Protected Variations from changing external interfaces or third-party packages through the use of an Indirection object that applies interfaces and Polymorphism.

Page 19: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

" Analysis" Discoveries During Design: Domain

Modela list of tax line items are associated with a sale, such as state tax, federal tax, and so forth

Page 20: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 21: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

OUTLINE

Adapter

Factory

Singleton

Strategy

Composition

Facade

Observer

Page 22: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Factory

who creates the adapters?a domain object (such as a Register)?

如何确定创建哪种 adapter? such as TaxMaster-Adapter or GoodAsGoldTaxProAdapter?

Page 23: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

another fundamental design principle

Design to maintain a separation of concerns.一般作为 architectural design principleone of the essential principles in software

engineering modularize or separate distinct concerns

into different areas, so that each has a cohesive purpose.

Page 24: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

domain layer 软件对象相对强调纯应用逻辑的职责另一组软件对象负责与外部系统的连接

Page 25: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Context I Problem

当有特殊考虑时如何创建对象 ? ( 如创建对象的逻辑很复杂,或想将创建对象的职责分离出来以获得更高的内聚度等 )

Solution

Create a Pure Fabrication object called a Factory that handles the creation.

Page 26: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

public class Factory{ public static Sample creator(){ .... if (which==1) return new MySample(); else if (which==2) return new HisSample(); }}

Sample s;s=Factory.creator();s.xxx();

Page 27: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 28: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Factory objects have several advantages: the responsibility of complex creation 分离

到高内聚的 helper objects 中将潜在的复杂的创建对象的逻辑隐藏可进而引入增强性能的内存管理策略,如

object caching or recycling.

Page 29: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Also is an example of a partial data-driven design通过改变属性值来选择创建不同的 adapter

对象Protected Variations : Adapter 的实现类在变化

Page 30: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

OUTLINE

Adapter

Factory

Singleton

Strategy

Composition

Facade

Observer

Page 31: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Singleton (GoF)

who creates the factory itself, and how is it accessed?整个过程只需要一个 factory 实例代码中各个地方都可能需要调用 factory 中

的方法来创建实例 -- 〉 Thus, there is a visibility problem: how to get visibility to this single ServicesFactory instance?

Page 32: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Con text I Problem

只允许创建一个实例— it is a “singleton.”需要为对象提供全局的、单点访问

Solution

Define a static method of the class that returns the singleton.

Page 33: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 34: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

lazy initializaition// Singleton.javapublic class Singleton{

private static Singleton _instance = null;private Singleton(){}

public static Singleton getInstance(){

if (null==_instance)_instance = new Singleton();

return _instance;}

}

保存全类唯一的实例

对客户隐藏构造器

客户只能从此处获得实例

Page 35: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

eager initializaition

public class Singleton {

private static Singleton _instance = new Singleton();

public static Singleton getInstance() {

return _instance;

}

}

Page 36: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 37: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

使用

Page 38: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

UML 表示

Page 39: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Fig. 26.7

:Register1

:ServicesFactory

aa = getAccountingAdapterinitialize

...

the ‘1’ indicates that visibility to this instance was achieved via the Singleton pattern

Page 40: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Conclusion

综合使用 Adapter, Factory, and Singleton patterns ,针对外部系统 (tax calculators, accounting systems 等 ) 的各种接口变化提供了 PV

Page 41: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 42: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Fig. 26.8

:Register accountingAdapter : SAPAccountingAdapter

postSale ( sale )

makePayment

SOAP over HTTP

xxx

:Register

1:ServicesFactory

accountingAdapter = getAccountingAdapter

:Store

createcreate

: SAPAccountingAdapter

: Paymentcreate (cashTendered )

«actor»: SAPSystem

create

Page 43: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

OUTLINE

Adapter

Factory

Singleton

Strategy

Composition

Facade

Observer

Page 44: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Strategy (GoF)

如何提供复杂的 pricing logic (圣诞促销、会员价 ,……)

The pricing strategy(a rule, policy, or algorithm) can vary during different period

Page 45: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Context / Problem

对于变化着的、但又相关的算法和策略如何设计 ? 如何设计才能改变这些算法和策略 ?

Solution

将每个 algorithm/policy/strategy 定义在具有共同接口的不同的类中 .

Page 46: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 47: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 48: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Fig. 26.10

:PercentDiscountPricingStrategy

s : Sale

st = getSubtotal

t = getTotal

lineItems[ i ] :SalesLineItem

t = getTotal( s )

pdt = getPreDiscountTotal

{ t = pdt * percentage }

note that the Sale s is passed to the Strategy so that it has parameter visibility to it for further collaboration

loop

Page 49: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Creating a Strategy with a Factory

Page 50: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 51: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Fig. 26.13

:Sale

1:PricingStrategyFactory

ps =getSalePricingStrategy

:Register

makeNewSalecreate

create(percent) ps : PercentDiscountPricingStrategy

Page 52: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 53: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

public class Sale{ ISalePricingStrategy pricingStrategy ; double predicounttotal;

double getTotal(){...

predicounttotal=… pricingStrategy=PricingStrategyFactory.getSalePricingStrategy();

return pricingStrategy.getTotal( this ) // pricingStrategy got from PricingStrategyFactory

}}

public interface ISalePricingStrategy { public double getTotal(Sale s);}

public class PricingStrategyFactory{ public ISalePricingStrategy getSalePricingStrategy(){

//… by "salepricingstrategy.class.name" return strategy;

}}

public class PercentDiscountPricingStrategy implements ISalePricingStrategy { public double getTotal( s:Sale ){

return s.getPreDiscountTotal() * percentage }

}

Page 54: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Reading and Initializing the Percentage Value初始值从外部数据源如关系数据库中读取,

以便容易修改

Page 55: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 56: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Summary

通过 Strategy and Factory patterns 获得针对定价策略变化的 PV.

对象设计中,基于 Polymorphism and interfaces 的策略模式允许可 pluggable algorithms

策略通常通过 Factory 模式创建

Page 57: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Strategy 和 Factory 有一定的类似 , Strategy 相对简单容易理解 , 并且可以在运行时刻自由切换。 Factory 重点是用来创建对象

Page 58: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Define a family of algorithms

Encapsulate each algorithm

Make the algorithms interchangeable

Let the algorithm vary independently from clients that use it

Page 59: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

OUTLINE

Adapter

Factory

Singleton

Strategy

Composition

Facade

Observer

Page 60: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Composition(GoF)

Page 61: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

对于多个冲突的定价策略如何处理 ?高级会员打 8 折超过 XXX 元打 8.5 折星期一购买超过 XXX 元立即返还 XX 元买 1 盒龙井,则买所有商品都打 8.5 折

Page 62: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

影响 Sale 的定价策略有三个要素

1. time period (Monday)

2. customer type (senior)

3. a particular line item product ( 买 1 盒龙井,则买所有商品都打 8.5 折 )

Page 63: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Context / Problem如何将组合结构和原子结构的对象进行同样

的处理Solution

Define classes for composite and atomic objects so that they implement the same interface.

Page 64: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 65: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 66: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 67: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 68: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 69: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Fig. 26.15

:CompositeBestForCustomerPricingStrategy

s : Sale

st = getSubtotal

t = getTotal

lineItems[ i ] :SalesLineItem

t = getTotal( s )

the Sale object treats a Composite Strategy that contains other strategies just like any other ISalePricingStrategy

x = getTotal( s )

strategies[ j ] :: ISalePricingStrategy

UML: ISalePricingStrategy is an interface, not a class; this is the way in UML 2 to indicate an object of an unknown class, but that implements this interface

{ t = min(set of all x) }

loop

loop

Page 70: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 71: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

将对象组合成树形结构以表示“部分 -整体”的层次结构。 C o m p o s i t e 使得用户对单个对象和组合对象的使用具有一致性

Page 72: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 73: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 74: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 75: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Creating Multiple SalePricingStrategies

什么时候创建这些策略 ?Current store-defined discount

added when the sale is created.Customer type discount,

added when the customer type is communicated to the POS.

Product type discountadded when the product is entered to the sale.

Page 76: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 77: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

:Sale

1:PricingStrategyFactory

ps =getSale

PricingStrategy

:Register

makeNewSale create

create ps :CompositeBestForCustomerPricingStrategy

create( percent ) s : PercentageDiscountPricingStrategy

add( s )

Page 78: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Customer Type DiscountUse Case : Process Sale

5b. Customer says they are eligible for a discount

1. Cashier signals discount request

2. Cashier enters Customer identification

3. System presents discount total

Introducing the new system operation,

enterCustomerForDiscount(custId)

Page 79: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 80: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

s :Sale:Register

enterCustomerForDiscount( custID )

by Controllerby Expert and IDs to Objects

:Store

c = getCustomer( custID )

enterCustomerForDiscount( c : Customer )

by Expert

ref Enter CustomerFor Discount

Page 81: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 82: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 83: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 84: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

s :Sale

<<singleton>>:PricingStrategy

Factory

addCustomerPricingStrategy( s )

ps :CompositeBestForCustomerPricingStrategy

ISalePricingStrategy

create( pct ) s : PercentageDiscountPricingStrategy

ISalePricingStrategy

add( s )

by Expert

enterCustomerForDiscount( c : Customer

)

originates inanother diagram

c :=getCustomer()

by Factory andHigh Cohesion

by Expert ps := getPricingStrategy()

pct :=getCustomer

Percentage( c )

by High Cohesion

by Factory and Composite

PassAggregateObject asParameter

Page 85: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

s :Sale

1:PricingStrategy

Factory

addCustomerPricingStrategy( s )

ps :CompositeBestForCustomerPricingStrategy

create( pct ) s : PercentageDiscountPricingStrategy

add( s )

by Expert

enterCustomerForDiscount( c : Customer )

c = getCustomer

by Factory and High Cohesion

by Expert ps = getPricingStrategy

pct = getCustomer

Percentage( c )

by High Cohesion

by Factory and Composite

Pass Aggregate Object as Parameter

sd Enter Customer For Discount

Page 86: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

OUTLINE

Adapter

Factory

Singleton

Strategy

Composition

Facade

Observer

Page 87: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Facade (GoF)

NextGen POS Requirementspluggable business rules.

用例场景可预测的点上(如 Process Sale 的makeNewSale, enterItem 等),不同顾客的行为略有不同

如 when a new sale is created,礼券payment type of change duescharitable donation rules

Page 88: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Analysis and Design the specific scenario points across all use

cases must be identified (enterItem, chooseCashChange, ...) 本次只考虑 enterltem

low impact on the existing software components

may want to experiment with different solutions

Page 89: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Context/Problem需要为不同的实现或子系统内部的接口提供公共的、统一的接口 .

外界对子系统内部有很多耦合,或子系统的实现可能会改变

Solution为子系统设计单点访问

– a facade object that wraps the subsystem. The facade object 代表单一的、统一的接口

Page 90: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 91: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 92: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Creating facade object and calling operations in facade objectFacades are often accessed via a

singleton factory. Calls to the facade should be placed near

the start of the methods that have been defined as the points for pluggable rules

Page 93: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

public class Sale

{

public void makeLineItem (ProductSpecification spec, int quantity)

{

SalesLineItem sli = new SalesLineItem(spec, quantity);

if (POSRuleEngineFacade.getInstance().isInvalid(sli, this))

return;

.....

}

...

}

Page 94: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Domain

+ Sale + Register ...

POSRuleEngine

<<interface>>- IRule

...

- Rule1

...

- Rule2

...

...

package name may beshown in the tab

visibility of the package element (tooutside the package) can be shownby preceding the element name with avisibility symbol

+ POSRuleEngineFacade

instance : RuleEngineFacade

getInstance() : RuleEngineFacade

isInvalid( SalesLineItem, Sale )isInvalid( Payment, Sale )...

*1

Page 95: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Observer/Publish-Subscribe/Delegation

Event Model

Goal: When the total of the salechanges, refresh the display withthe new value

Sale

total...

setTotal( newTotal )...

Page 96: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 97: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Context/Problem不同的 subscriber 对某个 publisher 的状态变化

和事件感兴趣,当 publisher 生成事件时,每个subscriber 用各自独有的方式响应

Publisher 和 subscribers之间希望低耦合Solution

定义一个 subscriber or listener 接口Subscribers 实现这个接口 .Publisher 可动态地将对自己感兴趣的

subscribers 进行登记事件发生时, notify 所有登记的 subscribers

Page 98: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 99: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

<<interface>>PropertyListener

onPropertyEvent( source, name, value )

SaleFrame1

onPropertyEvent( source, name, value )

initialize( Sale sale )...

javax.swing.JFrame

...setTitle()setVisible()...

{ if ( name.equals("sale.total") ) saleTextField.setText( value.toString() );}

Sale

addPropertyListener( PropertyListener lis )publishPropertyEvent( name, value )

setTotal( Money newTotal )...

*propertyListeners

{ total = newTotal; publishPropertyEvent( "sale.total", total); }

{ propertyListeners.add( lis );}

{ for each PropertyListener pl in propertyListeners pl.onPropertyEvent( this, name, value ); }

{ sale.addPropertyListener( this ) ...}

Subject

Observer

具体的Observer

update( )

update( )

Page 100: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Subscribing Listener Objects

s :Salesf :SaleFrame1

initialize( s : Sale)

addPropertyListener( sf)

PropertyListener

propertylisteners:Object

add( sf)

PropertyListener UML notation: Recall that

there is no such thing as aninstance of an interface.Therefore, we can generalize(or be vague) and simplyindicate the instances as typeObject, which is assumed tobe the superclass of allclasses. This approach can beused even if the language(such as C++) does notliterally define a root Objectsuperclass.

Page 101: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Fig. 26.23

s : Salesf : SaleFrame1

initialize( s : Sale )

addPropertyListener( sf )

propertyListeners : List<PropertyListener>

add( sf )

Page 102: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Publishing an event(Sale total change)

s :Sale

setTotal( total)

* : onPropertyEvent( s, "sale.total", total)

UML notation: Since themembers of this collection aretyped to the interfacePropertyListener, it is not legal toshow an implementationresponse, such as furthermessaging, since the responsecan vary, depending on the classimplementing this interface.

Therefore, "stop" the messagingat this point, and showimplementions on differentdiagrams.

publishPropertyEvent( "sale.total", total )

propertylisteners:Object

PropertyListener

Page 103: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Fig. 26.24

s :Sale

setTotal( total )

onPropertyEvent( s, "sale.total", total )

publishPropertyEvent( "sale.total", total )

propertylisteners[ i ] : PropertyListener

loop

Page 104: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Receiving event notification

:SaleFrame1

onPropertyEvent( source, name, value)

PropertyListener

saleTextField: JTextField

setText( value.toString())

Since this is a polymorphic operationimplemented by this class, show a newinteraction diagram that starts with thispolymorphic version

UML notation: Note this little expression within theparameter. This is legal and consise.

Page 105: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

<<interface>>AlarmListener

onAlarmEvent( source, time )

Beeper

onAlarmEvent( source, time )...

{ display notification dialogbox}

AlarmClock

addAlarmnListener( AlarmListener lis )publishAlarmEvent( time )

setTime( newTime )...

*alarmListeners

{ time = newTime; if ( time == alarmTime ) publishAlarmEvent( time ); }

{ alarmListeners.add( lis );}

{ for each AlarmListener al in alarmListeners al.onAlarmEvent( this, time ); }

AlarmWindow

onAlarmEvent( source, time )...

javax.swing.JFrame

...setTitle()setVisible()...

ReliabilityWatchDog

onAlarmEvent( source, time )...

{ beep}

{ check that all required processes are executing normally}

Page 106: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

补充内容

Page 107: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

OUTLINE

Adapter

Factory

Singleton

Strategy

Composition

Facade

Observer

Page 108: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

More on Factory and Singleton

[email protected]

Page 109: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Existing class

class Employee{ //... public void youAreFired() { // lots of code }}a lot of code scattered through the system that looks something like this Employee fred = new Employee(); //... fred.youAreFired();

Page 110: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

must-change-all-new-invocations problem

1 Create an interface that has the same name as the existing class, like so:interface Employee{ void youAreFired();}2 Rename the existing class, like so:class Peon implements Employee // used to be Employee{ public void youAreFired() { // lots of code }}3. ?

Page 111: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Factory 1 public interface Employee 2 { void youAreFired(); 3 } 4 5 public static class EmployeeFactory 6 { private Factory(){/*empty*/} 7 8 public static Employee create() 9 { return new Peon();10 }11 }

/*package*/ class Peon implements Employee14 { public void youAreFired()15 { // lots of code16 }17 }

Page 112: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 113: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

restrict access to the concrete class even further public static class EmployeeFactory{ private EmployeeFactory(){/*empty*/} public static Employee create() { return new Peon(); } private static class Peon implements Employee { public void youAreFired() { // lots of code } }}

Page 114: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

anonymous-inner-class version of the factory

public static class EmployeeFactory{ private Factory(){/*empty*/} public static Employee create() { return new Employee() { public void youAreFired() { // lots of code } } }}

Page 115: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Runtime runtimeEnvironment = Runtime.getRuntime();

ButtonPeer peer = Toolkit.getDefaultToolkit().createButton(b);

Page 116: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Thread Problem

1 class Singleton 2 { private static Singleton instance = null; 3 public static instance() 4 { if( instance == null ) 5 { instance = new Singleton(); 6 } 7 return instance; 8 } 9 //...10 }

Page 117: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

The easy solution is to use a static initializer

class Singleton2

{ private static Singleton instance = new Singleton();

public instance() { return instance; }

//...

}

Page 118: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

The only time the static -initializer approach isn't workable

public static void main( String[] args ){ //... Connection.pointAt( new URL(args[i]) ); //...}

Connection c = Connection.instance();

Page 119: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

class Connection{ private static URL server; public static pointAt( URL server ){ this.server = server; } private Connection() { //... establishConnectionTo( server ); //... } private static Connection instance; public synchronized static Connection instance() { if( instance == null ) instance = new Connection(); return connection(); }}

Page 120: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Double-Checked Locking 1 class DoubleChecked 2 { private static volatile DoubleChecked instance = null; 3 private static Object lock = new Object(); 4 5 public static DoubleChecked instance() 6 { if( instance == null ) 7 { synchronized( lock ) 8 { if( instance == null ) 9 instance = new DoubleChecked();10 }11 }12 return instance;13 }14 }

Page 121: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Game of Life

Page 122: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 123: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Game of Life

对于处在”生态的格 ,若八个邻居中有 2 个或 3 个”生” ,则继续存活 ,否则将因过于孤独或过于拥挤而死亡 .

对于处在”死”态的空格 ,若八个邻格中有 3 个”生” , 则该格转变为”生” ( 代表繁衍过程 ),否则继续空着 .

Page 124: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院
Page 125: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Observer Pattern

Page 126: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

ObserverObserver uses an anonymous inner class as the Concrete Subject/Subscriber

class Client{ volatile boolean menuItemSelected = false;

public Client( JMenu topMenu ) { // Add an item to the topMenu, and arrange to be notified when it // is selected:

JMenuItem myItem = new JMenuItem( "Hello" ); myItem.addActionListener ( new ActionListener() { public void actionPerformed( ActionEvent e ) { menuItemSelected = true; // process selection } } );

topMenu.add( myItem ); }}

Page 127: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Universe——Observerclass Universe{…Clock.instance().addClockListener( new Clock.Listener() { public void tick() { // code to handle a clock tick goes here } });

}

Page 128: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Clock——Timer 13 public class Clock{ 14 private Timer clock = new Timer(); 15 private TimerTask tick = null; 16

21 private Clock() 22 { createMenus(); 23 }

39 public void startTicking( int millisecondsBetweenTicks ) 40 { if(tick != null) 41 { tick.cancel(); 42 tick=null; 43 } 44 45 if( millisecondsBetweenTicks > 0 ) 46 { tick = new TimerTask() 47 { public void run(){ tick(); } 48 }; 49 clock.scheduleAtFixedRate( tick, 0, millisecondsBetweenTicks); 50 } 51 }

97 public void tick(){ …

Page 129: DESIGNING USE-CASE REALIZATIONS WITH GoF DESIGN PATTERNS 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

Implementing Observer: The Publisher Classclass Publisher1

{ ArrayList subscribers = new ArrayList();

public synchronized void subscribe( Runnable subscriber ) { subscribers.add( subscriber ); }

public synchronized void cancelSubscription( Runnable subscriber ) { subscribers.remove( subscriber); }

private synchronized void fireEvent() // notify all subscribers { for( int i = 0; i < subscribers.size(); ++i ) ((Runnable) subscribers.get(i) ).run(); }}