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

Composite Pattern (OOP)

The composite pattern works for structures (trees) where we have two kinds, the leaf and the composite. The composite perform an operation to all children's , If child is a leaf perform an operation for leaf, if it is a composite perform an operation for all children's on that composite.

Simple:

\\ Composite Pattern


Class iComponet {
      module operation {
            error "Abstract"
      }
}
Class Componet as iComponet {
Private:
      name$
Public:
      module operation {
            print "do something"
      }
      remove {
            Print "remove ";.name$
      }
}
Class Leaf as Componet {
      module operation {
            Print "do an operation to this leaf:";.name$
      }
Class:
      module Leaf (.name$) {
      }
}
Class Composite as Componet {
      m=stack
      module operation {
       k=each(.m)
       Print "["+.name$+"]"
       while k
             z=stackitem(k)
             z=>operation
       end while
      }
      module addChild (child as *Componet) {
            stack .m {data child}
      }
Class:
      module Composite (.name$) {
      }
}
M->Composite("GroupA")
M=>addChild pointer(Leaf("Shape1"))
M=>addChild pointer(Leaf("Shape2"))
M=>addChild pointer(Leaf("Shape3"))
M1->Composite("Graphic")
M1=>addChild M
M->Composite("GroupB")
M=>addChild pointer(Leaf("Shape4"))
M1=>addChild M
M->0&
M1=>operation



Advanced (has a deep copy function for components) :
If we add a Push MM as last statement in Module A then the groups form MM (one composite with one leaf) pushed to current stack. So the last 2 lines "remove.." not displayed. The current stack is the same as the stack in console level (or level 0). So if we write flush we get the 2 remove (from the 2 objects). 







\\ Composite Pattern


Class iComponet {
      module operation {
            error "Abstract"
      }
}
Class Componet as iComponet {
Private:
      name$
Public:
      module operation {
            print "do something"
      }
      function Copy {
            C=This
            ->(C)
      }
      remove {
            Print "remove ";.name$
      }
}
Class Leaf as Componet {
      totalOperations=0
      module final operation {
            .totalOperations++
            Print "do an operation to this leaf:";.name$, .totalOperations
      }
Class:
      module Leaf (.name$) {
      }
}
Class Composite as Componet {
Private:
      m=stack
Public:
      totalOperations=0
      module final operation {
            k=each(.m)
            .totalOperations++
            Print "["+.name$+"]", .totalOperations
            while k
                   z=stackitem(k)
                   z=>operation
                   .totalOperations+=z=>totalOperations
            end while
      }
      Function final Copy {
                  k=each(.m)
                  flush ' empty current stack
                  while k
                         z=stackitem(k)
                         // append to current stack
                         Data Pointer((z=>Copy()))
                  end while
                  CC=This
                  // m is private in CC but..
                  // created in a member of same type object
                  // [] return current stack as pointer, and change current stack to a an empty one.
                  CC.m=[]
                  //  ->CC return pointer wich is a reference, but after the end of this function
                  // CC deleted. So we need a pointer of a copy of CC ->(CC) or =Pointer((CC))
                  -> (CC)
      }
      module Final addChild (child as *Componet) {
            stack .m {data child}
      }
Class:
      module Composite (.name$) {
      }
}
M->Composite("GroupA")
For M {
      // for this block M changed to a named group (hidden)
      // a name group is like a static, but not exactly.
      // we can use &This to pass a reference, or This to pass a copy (a shallow copy)
      // all public members are connected to code without use of pointer.
      .addChild pointer(Leaf("Shape1"))
      .addChild pointer(Leaf("Shape2"))
      // we can also use the pointer (which change to a reference)
      M=>addChild pointer(Leaf("Shape3"))
}
// now M change to a true pointer to a group (a nameless)
M1->Composite("Graphic")
M1=>addChild M
M->Composite("GroupB")
M=>addChild pointer(Leaf("Shape4"))
MM=M=>copy()
M1=>addChild M
M->0&
Print type$(M)="Group"  ' true
Print M is type Null = true ' true
Print M1 is type Composite and M1 is type Componet ' true
M1=>operation
Print M1=>totalOperations
List  ' Variables: if this is module a then we see A.M *[Group], A.M1 *[Group], A.MM *[Group]
Modules ? ' Modules & Functions: A, COMPOSITE(), LEAF(), COMPONET(), ICOMPONET()
Stack ' empty line, nothing in current stack
MM=>operation
Print MM=>totalOperations


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

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

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