OO设计问题

时间:2013-12-16 16:08:12

标签: oop smalltalk pharo

我有一个系统,我必须为household建模TVSubscription。这可以是digital个,也可以是analog

user登录SetTopBox。然后他可以租用Movies

所以目前的方案如下:

//Existing instantiated variables in scope
aMovie
aUser
aSetTopBox
//End

--> execute this command: 
aUser rent: aVideo on: aSTB

Code:
User>>rent: aVideo on: aSTB
aVideo rentBy: self on: aSTB

Video>>rentBy: aUser on: aSTB
aUser rentActionMovie: self on: aSTB

User>> rentActionMovie: aMovie on: aSTB
aSTB rentActionMovie: aMovie by: self

STB>>rentActionMovie: aMovie by: aUser
(loggedInUser isNil)
    ifTrue: [ loggedInUser := aUser.
              --Do stuff to charge the movie]
    ifFalse: [ -- Show error that user is not logged in]

从技术上讲,这是正确的。但我有(抱歉是肛门)问题:

我必须通过aSTB 2个方法调用才能最终使用它。这里需要双重发送,因为我有ChildAdult,他们可以租用AdultMovieChildrensMovie。因此,我使用双重调度而不是类型检查(要求)。因此我想到了以下解决方案:

我可以在currentlyLoggedIn上存储aSTB,并在loggedInOn上存储aSTB。然而,这使得对象指向彼此。

我的直觉告诉我这是一种难闻的气味。我不确定如何修复它。

理想情况下,我想做这样的事情:

aUser rent: aMovie.

3 个答案:

答案 0 :(得分:2)

第二种选择......

STB>>initialize
    aUser := UserNotLoggedIn new.

STB>>login
    aUser := self getUserFromAuthorisationCheck

STB>>rentMovie: aMovie by: aUser
    (aUser canRent: aMovie)
        ifTrue:  [ --Do stuff to charge the movie]

UserNotLoggedIn>>canRent: aMovie
    self displayErrorUserNotLoggedOn
    ^false

User>>canRent: aMovie
    aMovie ratingAge <= self ratingAge.

AdultMovie>>ratingAge
    ^18

Adult>>ratingAge
    ^18

ChildrensMovie>>ratingAge
    ^10

Child>>ratingAge
    ^10

User>>rent: aMovie
    aSetTopBox rentMovie: aMovie by: self

答案 1 :(得分:1)

<强>思想

这么多关于两个对象之间的关系, 那么你可能想要将关系建模为对象

  

对象为anything that is visible or tangible and is relatively stable in form.

实施理念

您创建的临时对象只与两个对象之间的关系一样长。如果需要,该对象可以用作中介或方法对象。

我的感觉是,这可能是一个过度工程的情况,并且不会被读取代码的人立即理解。

答案 2 :(得分:1)

我不是专家,但只是我头脑中的另一种选择......

STB>>initialize
    aUser := UserNotLoggedIn new.

STB>>rentMovie: aMovie by: aUser
    (aMovie okayFor: aUser)
        ifTrue:  [ --Do stuff to charge the movie]

AdultMovie>>okayFor: aUser
    ^aUser canRentAdultMovie

ChildrensMovie>>okayFor: aUser
    ^aUser canRentChildMovie

User>>canRentChildMovie
    ^true

User>>canRentAdultMovie
    self displayErrorCannotRentAdultMovie
    ^false

Adult>>canRentAdultMovie
    ^true

UserNotLoggedIn>>canRentChildMovie
    self displayErrorUserNotLoggedOn
    ^false

UserNotLoggedIn>>canRentAdultMovie
    self displayErrorUserNotLoggedOn
    ^false

Child "just the same as User"

User>rent: aMovie.
    aSetTopBox rentMovie: aMovie by: self.

aUser rent:aMovie。