Τετάρτη 15 Ιουλίου 2020

Flyweight Pattern (OOP)

The Flyweight Pattern used when a client object has two parts, one which have intrinsic state, and another which is extrinsic. Here soldier has intrinsic the graphical representation, but the position handled as extrinsic, from the SoldierClient, which hold the current X and Y values.

This statement Dim warSoldier(1 to 5)<<SoldierClient() make an array and execute the SoldierClient for each item on the array. A SoldierClient make an internal Soldier from Soldierfactory. Soldierfactory isn't a class, is an object and we make it as global (so we can use it from Class). The SoldierFactory keep a pointer to a SoldierImp, and return that pointer We can change that to return object as a copy of the pointed group using Group(.Solider) and then we use .Soldier.moveSoldier .currX, .currY, toX, toY and notice that we use a dot and not fat arrow => as for .Soldier as pointer to Group. Because we want extrinsic state to handled by SoldierClient we keep the first option, the use of pointer in SoldierFactory in method getSoldier().

We apply two set of coordinates for 5 warSoldiers. Notice the use of -1000 as an out of area position. So when we have to draw we check if the soldier is hidden by checking the -1000 value.  The same hold when we have to remove the soldier, the value -1000 tell that it was hidden, so skip the removing.


\\ Flyweight Pattern
class Soldier {
      module moveSoldier {
            error "abstract"
      }
}
Global Group GraphicalSoldierRepresentation {
      \\ render the representation of a soldier
      \\ it is the same for each soldier
      module drawSoldier (X, Y){
            Print "Soldier draw to ", X, Y
      }
      module removeSoldier (X, Y) {
            Print "Soldier removed from ", X, Y
      }
}
class SoldierImp as Soldier {
      \\ we put only a reference to the global group
private:
      GraphicalRepresentation=Pointer(GraphicalSoldierRepresentation)
Public:
      module moveSoldier(fromX, fromY, toX, toY) {
            \\ delete soldier representation from previous location
            \\ then render soldier representation in new location
            if fromY>-1000 then .GraphicalRepresentation=>removeSoldier fromX, fromY
            if toY>-1000 then .GraphicalRepresentation=>drawSoldier toX, toY
            
      }
}
Global Group SoldierFactory {
Private:
      soldier=Pointer()
Public:
      Function GetSoldier {
            if .soldier is type null then .soldier<=Pointer(SoldierImp())
            \\ return object as copy the one which soldier points
            =.soldier
      }
}
class SoldierClient {
Private:
      Soldier=SoldierFactory.GetSoldier()
      currX=-1000, currY=-1000
Public:
      module moveSoldier(toX, toY) {
            .Soldier=>moveSoldier .currX, .currY, toX, toY
            \\ multiassign. Notice that we didn't use <=
            \\ this happen because actually interpreter
            \\ push values to stack and read to the variables on the left
            (.currX, .currY)=(toX, toY)
      }
}
Flush ' empty the stack
Dim warSoldier(1 to 5)<<SoldierClient()
Data 100,200, 400,500,700,300,150,200, 30,160
For i=1 to 5
For warSoldier(i) {
      \\ we can remove Read statement, and posX, posY in .moveSoldier
      \\ because the stack of values is the same for modules
      Read posX, posY
      .moveSoldier posX, posY
}
Next
\\ new positions
Data 110,200, 440,500,700,350,150,-1000, 30,-1000
For i=1 to 5
For warSoldier(i) {
      .moveSoldier
}
Next
Print "Done"

Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.