Τρίτη 14 Ιουλίου 2020

Visitor Pattern (OOP)

The visitor pattern used for a structure of objects. Here we have a group of customers. Each customer has a list of orders, and each order has a list of items. Order has an item list of type queue, which gets same keys. Orders and Customers are lists with unique keys.

First we make the structure. Then we want a Visitor type object to visit all parts of the structure. Each part has an accept method and get the a pointer from the Visitor. A pointer Pointer(This) is a reference to This. (a pointer Pointer((This)) is a pointer of a copy of This). Here we want to send reference, because all the job done from one call accept from CustomerGroup.

GeneralReport is a true pointer. When the first visitor=>visit perfroms the closed object became open, so pointer(this) point to the open group (a named group, but name is hidden by interpreter).

We use iterators for lists/queues. So we get the data and we place them to a Document object, a structure with strings as paragraphs. Assign a string value to a document append it. So to clear a document we use Clear statement.

This is the export (using Clipboard we send the text to clipboard)

Customer: Bob
Order : 1001
     1. AZX100
     2. ZZ12-23
Order : 1002
     1. AZX101
Customer: John
Order : 1003
     1. KKX112
     2. BZ212-6
     3. BZ212-7

Class Visitor {
Private:
      module VisitItem (p as Item) {
            Error "Abstract"
      }
      module VisitOrder (p as Order) {
            Error "Abstract"
      }
      module VisitCustomer (p as Customer) {
            Error "Abstract"
      }
Public:
      module Visit (p as *Visitable){
            if p is type Item then
                  .VisitItem p
            else.if p is type Order then
                  .VisitOrder p
            else.if p is type Customer then
                  .VisitCustomer p
            end if
      }
}
Class Visitable {
      module accept (visitor as *Visitor){
            Error "Abstract"
      }
}
\\ a structure of objects
Class Item as Visitable {
      property name$ {Value}
      module accept (visitor as *Visitor){
            \\ do nothing
      }
Class:
      module Item (.[name]$) {
      }
}
Class Order as Visitable {
Private:
      Items=Queue
Public:
      property name$ {Value}
      module final accept (visitor as *Visitor){
            m=each(.Items)
            while m
                  visitor=>visit eval(m)
            end while
      }
      module addItem (aName$){
            Append .items, aName$:=Pointer(item(aName$))
      }
Class:
      module Order (.[name]$, itemname$="") {
            if itemname$<>"" then .additem itemname$
      }
}
Class Customer as Visitable {
Private:
      orders=List
Public:
      property name$ {Value}
      module final accept (visitor as *Visitor){
            m=each(.orders)
            while m
                  visitor=>visit eval(m)
            end while
      }
      module addOrder (order as *Order) {
            Append .orders, order=>name$:=order
      }
      module Customer (.[name]$) {
      }
}
Class CustomerGroup as Visitable {
Private:
      customers=List
Public:
      module final accept (visitor as *Visitor){
            m=each(.customers)
            while m
                  visitor=>visit eval(m)
            end while
      }
      module addCustomer (customer as *Customer) {
            Append .customers, customer=>name$:=customer
      }
}
Class GeneralReport as Visitor {
Private:
      ItemNo, OrderNo, CustomerNo
      Document Result$
      module VisitItem (p as *Item) {
            .ItemNo++
            .Result$<=format$("{0::-6}. {1}",.ItemNo, p=>name$)+{
            }
      }
      module VisitOrder (p as *Order) {
            .OrderNo++
            .ItemNo<=0
            .Result$<=format$("Order : {0}",p=>name$)+{
            }
            p=>accept pointer(this)
      }
      module VisitCustomer (p as *Customer) {
            .CustomerNo++
            .OrderNo<=0
            .Result$<=format$("Customer: {0}", p=>name$)+{
            }            
            p=>accept pointer(this)
      }
Public:
      module displayResults {
            Report .Result$
            ClipBoard .Result$
            Clear .Result$
            .CustomerNo<=0
      }
}
CustomerGroup=CustomerGroup()
\\ put some items in an order
For This {
      order1=Order("1001", "AZX100")
      order1.addItem "ZZ12-23"
      M1=Customer("Bob")
      M1.addOrder Pointer((order1))
      order1=Order("1002", "AZX101")
      M1.addOrder Pointer((order1))
      CustomerGroup.addCustomer Pointer((M1))
      order1=Order("1003", "KKX112")
      order1.addItem "BZ212-6"
      order1.addItem "BZ212-7"
      M1=Customer("John")
      M1.addOrder Pointer((order1))
      CustomerGroup.addCustomer Pointer((M1))
}
\\ Now order1 and M1 erased
\\ we get a pointer to a GeneralReport
GeneralReport->GeneralReport()
CustomerGroup.accept GeneralReport
GeneralReport=>displayResults


You can add in class Item the Remove clause (this is the de-constructor). The de-constructor called when an object referred only by a pointer. So when last pointer to a group (the m2000 user object) deleted the M2000 Interpreter call the Remove function. When the module which have the program above ends execution then all items removes (we will see 6 rows Remove One). In M2000 objects  type Group maybe like variables using a hidden pointer. If A  and B are variable type groups then A=B means B merge to A (so internal hidden pointers never changed) . These variable like objects erased automatic along with local variables. The remove functionality not used for these "static" like objects. Although we can start the remove clause using Clear statement and as parameter the name of the variable which hold the group object.

Class Item as Visitable {

      property name$ {Value}
      module accept (visitor as *Visitor){
            \\ do nothing
      }
      Remove {
            Print "Remove One"
      }
Class:
      module Item (.[name]$) {
      }
}


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

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

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