Πέμπτη, 9 Ιουλίου 2020

Factory Method Pattern (OOP)

We mimic the abstract class by using members which produce error at execution. So we have to replace them.

Look the line where we make the MyApplication as a combine from class Application and the ConcreteCreate group. The ConcreteCreate is typeless, so we didn't add type, and replace two functions with two other as final change. So now MyApplication can handle specific types. The Application knows nothing about the types. but knows the Document type of class. (Document is a specific object in M2000, but here we use the name for a class, and all classes have their name as type, plus other names from classes which inherit .


\\ Factory Method Pattern

\\ Document used as abstract group
\\ identifier Document used to define Documents, but here we redefine the name

Class Document {
    module open {
        Error "Not implemented yet "+module.name$
    }
    module save (filename$) {
        Error "Not implemented yet "+module.name$
    }
    module close {
        Error "Not implemented yet "+module.name$
    }
}
\\ also Application is a pointer to M2000 interpreter to access inner funcitons
\\ but here we redefine the identifier
Class Application {
Private:
    docnum=0, docs=list
    Function GetType$(filename$) {
        Error "Not implemented yet "+module.name$
    }
Public:
    Value (num=0){
        \\ by default return 0
        if num=0 then
            =.docnum
        Else.if exist(.docs, num) Then
            =num
        End If
    }
    Function ExportPointer(Num) {
        if exist(.docs, Num) then
            =eval(.docs)
        else
            =pointer() ' Null Group
        end if
    }
    Module DropDocument (Num) {
        if exist(.docs, Num) then delete .docs, Num
    }
    Function CreateDocument(type$){
        Error "Not implemented yet "+module.name$
    }
    Module NewDocument(type$){
        doc->(.CreateDocument(type$))
        .docnum++
        Append .docs, .docnum:=doc
        doc=>Open
    }
    Module OpenDocument(filename$) {
        Doc=Pointer(.CreateDocument(.GetType$(filename$)))
        If Doc is type Document then
            .docnum++
            Append .docs, .docnum:=doc
            doc=>Open
        Else
            Error "Wrong File Type"
        End If
    }
    
}
Group ConcreteCreator {
Private:
    Function Final GetType$(filename$) {
        \\ supposed we read the magic number from file
        \\ but here we check the filename only
        filename$=lcase$(filename$)
        if filename$ ~ "*.html" Then
            ="html"
        Else.if filename$ ~ "*.odt" Then
            ="proprietary"
        Else.if filename$ ~ "*.pdt" Then
            ="pdf"
        End if    
    }
Public:
    Function Final CreateDocument(type$){
        if type$="html" Then
            =HtmlDocument()
        Else.if type$="proprietary" Then
            =MyDocument()
        Else.if type$="pdf" Then
            =PdfDocument()
        Else
            Error "Not such type "+type$
        End if
    }    
}
Class SimpleText {
    Property dirty {value}=false
    Property text$ {Value}=""
    module placetext (aText$) {
        .[dirty] <= .[text]$<>aText$ or .[dirty]
        Swap .[text]$, aText$
    }
}
Class HtmlDocument as SimpleText as Document{
    module open {
    }
    module save (filename$) {
    }
    module close {
    }    
}
Class MyDocument as SimpleText as Document {
    module open {
    }
    module save (filename$) {
    }
    module close {
    }    
}
Class PdfDocument as SimpleText as Document {
    module open {
    }
    module save (filename$) {
    }
    module close {
    }    
}
MyApplication = Application() with ConcreteCreator
MyApplication.NewDocument "html"
DocId1=MyApplication()
MyApplication.NewDocument "pdf"
DocId2=MyApplication()
MyDocument1=if( DocId1<>0-> MyApplication.ExportPointer(DocId1), SimpleText())
MyDocument1=>placetext "html text"
Disp(MyDocument1)
MyDocument2=if( DocId2<>0-> MyApplication.ExportPointer(DocId2), SimpleText())
MyDocument2=>placetext "pdf text"
Disp(MyDocument2)

End
Sub Disp(Doc as *Simpletext)
    Print "Dirty: ";Doc=>dirty=True
    Print "Text : ";Doc=>Text$
End Sub

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

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