Difference between revisions of "Support pattern"

From wiki.visual-prolog.com

(initial)
 
(xxxSite -> xxxSupportSite)
 
Line 12: Line 12:
*The <vp>target</vp> interface, which defines the <vp>target</vp>'s public interface.
*The <vp>target</vp> interface, which defines the <vp>target</vp>'s public interface.
*The <vp>targetSupport</vp> interface, which defines the <vp>target</vp>'s view of the <vp>targetSupport</vp>.
*The <vp>targetSupport</vp> interface, which defines the <vp>target</vp>'s view of the <vp>targetSupport</vp>.
*The <vp>targetSite</vp> interface, which defines the <vp>targetSupport</vp>'s view of the <vp>target</vp>.
*The <vp>targetSupportSite</vp> interface, which defines the <vp>targetSupport</vp>'s view of the <vp>target</vp>.


[[PFC]] has many of uses the support pattern.
[[PFC]] has many of uses the support pattern.
Line 46: Line 46:
The <vp>targetSupport</vp> and <vp>target</vp> classes are in symbiosis with one and other:
The <vp>targetSupport</vp> and <vp>target</vp> classes are in symbiosis with one and other:


* The <vp>targetSite</vp> interface contains entities that the <vp>targetSupport</vp> class will need from the <vp>target</vp>.
* The <vp>targetSupportSite</vp> interface contains entities that the <vp>targetSupport</vp> class will need from the <vp>target</vp>.
* And the <vp>targetSupport</vp> interface contains entities that the <vp>targetSupport</vp> class provides to the <vp>target</vp>.
* And the <vp>targetSupport</vp> interface contains entities that the <vp>targetSupport</vp> class provides to the <vp>target</vp>.


The exact contents of these interfaces will depend on how the <vp>targetSupport</vp> class is supposed to support the construction of the <vp>target</vp> classes.  For the the description we have added a predicate predicate to the targetSite:
The exact contents of these interfaces will depend on how the <vp>targetSupport</vp> class is supposed to support the construction of the <vp>target</vp> classes.  For the the description we have added a predicate predicate to the targetSupportSite:


<vip>interface targetSite
<vip>interface targetSupportSite
predicates
predicates
     sitePredicate : ().
     sitePredicate : ().
end interface targetSite</vip>
end interface targetSupportSite</vip>


For the description we will assume that the targetSupport class will directly implement the <vp>targetProperty</vp> and provide a support predicate, <vp>supportPredicate</vp>, which the target class can use to implement the <vp>targetPredicate</vp>.
For the description we will assume that the targetSupport class will directly implement the <vp>targetProperty</vp> and provide a support predicate, <vp>supportPredicate</vp>, which the target class can use to implement the <vp>targetPredicate</vp>.
Line 68: Line 68:
end interface targetSupport</vip>
end interface targetSupport</vip>


<vp>targetSupport</vp>'c constructor will (at least) take a <vp>targetSite</vp> as parameter, here we have also chosen that it should have an initial value for the <vp>targetProperty</vp>:
<vp>targetSupport</vp>'c constructor will (at least) take a <vp>targetSupportSite</vp> as parameter, here we have also chosen that it should have an initial value for the <vp>targetProperty</vp>:


<vip>class targetSupport : targetSupport
<vip>class targetSupport : targetSupport
constructors
constructors
     new : (targetSite Site, string TargetPropertyInit).
     new : (targetSupportSite Site, string TargetPropertyInit).
end class targetSupport</vip>
end class targetSupport</vip>


Line 80: Line 80:


facts
facts
     site : targetSite.
     site : targetSupportSite.
     targetProperty : string.
     targetProperty : string.


Line 95: Line 95:
end implement targetSupport</vip>
end implement targetSupport</vip>


The implementation of the target classes (here <vp>target_1</vp>) we will inherit from <vp>targetSupport</vp> to get access to the shared functionality, it will also have to support and implement the <vp>targetSite</vp> interface and privide itself (i.e. <vp>This</vp>) as site:
The implementation of the target classes (here <vp>target_1</vp>) we will inherit from <vp>targetSupport</vp> to get access to the shared functionality, it will also have to support and implement the <vp>targetSupportSite</vp> interface and privide itself (i.e. <vp>This</vp>) as site:


<vip>implement target_1 inherits targetSupport % access to shared functionality by inheritance
<vip>implement target_1 inherits targetSupport % access to shared functionality by inheritance
     supports targetSite % support the site so that the targetSupport can access functionality here
     supports targetSupportSite % support the site so that the targetSupport can access functionality here


clauses
clauses
Line 156: Line 156:
So the site will have to supply <vp>getAll_nd</vp> predicate:
So the site will have to supply <vp>getAll_nd</vp> predicate:


<vip>interface collectionSite{@Type}
<vip>interface collectionSupportSite{@Type}


predicates from collection{@Type}
predicates from collection{@Type}
     getAll_nd/0->
     getAll_nd/0->


end interface collectionSite</vip>
end interface collectionSupportSite</vip>


And then the support class will implement all the rest:
And then the support class will implement all the rest:
Line 180: Line 180:


facts
facts
     site : collectionSite{@Type}.
     site : collectionSupportSite{@Type}.


clauses
clauses

Latest revision as of 13:32, 20 February 2016

The purpose of the support pattern is to implement a number of target classes all supporting a common interface target, using a targetSupport class to implement common functionality. The pattern is a more explicit version of some common less structured inheritance patterns.

Even though the purpose of the pattern it so create many target classes, the pattern is described for one of these target classes. In that context there are two actors:

Target
The targets are the class we want to implement.
Support
The targetSupport is a class that implement those parts of the target that is to be reused/shared for other target's.

There are three contracts in the pattern:

  • The target interface, which defines the target's public interface.
  • The targetSupport interface, which defines the target's view of the targetSupport.
  • The targetSupportSite interface, which defines the targetSupport's view of the target.

PFC has many of uses the support pattern.

The contents of the target interface solely depend on overall problem, and does not contain anything that have to do with the design patters. For the the description we have added a property and a predicate:

interface target
 
properties
    targetProperty : string.
 
predicates
    targetPredicate : ().
 
end interface target

Likewise the class declaration of the target (here target_1) solely depends on the overall problem:

class target_1 : target
...
end interface target_1

It will either construct objects of the target type (as above), or of a type that supports target as here:

interface target_2 supports target
% additional special target_2 functionality
end interface target_2
 
class target_2 : target_2
...
end interface target_2

The targetSupport and target classes are in symbiosis with one and other:

  • The targetSupportSite interface contains entities that the targetSupport class will need from the target.
  • And the targetSupport interface contains entities that the targetSupport class provides to the target.

The exact contents of these interfaces will depend on how the targetSupport class is supposed to support the construction of the target classes. For the the description we have added a predicate predicate to the targetSupportSite:

interface targetSupportSite
predicates
    sitePredicate : ().
end interface targetSupportSite

For the description we will assume that the targetSupport class will directly implement the targetProperty and provide a support predicate, supportPredicate, which the target class can use to implement the targetPredicate.

Since targetProperty is to be exposed directly as target::targetProperty it must be declared as coming from the target interface:

interface targetSupport
properties from target
    targetProperty
 
predicates
    supportPredicate : ().
end interface targetSupport

targetSupport'c constructor will (at least) take a targetSupportSite as parameter, here we have also chosen that it should have an initial value for the targetProperty:

class targetSupport : targetSupport
constructors
    new : (targetSupportSite Site, string TargetPropertyInit).
end class targetSupport

The implementation of the targetSupport class will store the site in a fact so that the site can be accessed where required. This code also contains example implementation of the targetSupport interface

implement targetSupport
 
facts
    site : targetSupportSite.
    targetProperty : string.
 
clauses
    new(Site, TargetPropertyInit) :-
        site := Site,
        targetProperty := TargetPropertyInit.
 
clauses
    supportPredicate(...) :-
         ...
        site:sitePredicate(),  % site functionality can be used where required
        ...
end implement targetSupport

The implementation of the target classes (here target_1) we will inherit from targetSupport to get access to the shared functionality, it will also have to support and implement the targetSupportSite interface and privide itself (i.e. This) as site:

implement target_1 inherits targetSupport % access to shared functionality by inheritance
    supports targetSupportSite % support the site so that the targetSupport can access functionality here
 
clauses
    new(...) :-
        targetSupport::new(This, "target_1_property"). % initialization of the base class
 
% The targetProperty is directly inherited from the targetSupport
% but this class will have to implement targetPredicate
clauses
    targetPredicate() :-
        ...
        supportPredicate(),  % we can use the inherited supportPredicate in the target class
        ...
 
clauses
    sitePredicate() :- % The target class must implement the sitePredicate
        ...
end implement target_1

The support pattern very explicitly express what functionality the support class provides to the target classes and vice versa.

Example The collectionSupport class in PFC is an example of the the support pattern. (Here it is shown in the Visual Prolog 7.5 version.)

A collection must implement this interface:

interface collection{@Type}
 
predicates
    isEmpty : () determ.
    % @short Succeeds if the collection is empty.
    % @end
 
predicates
    contains : (@Type Value) determ.
    % @short Succeeds if the collection contains the value @Type
    % @end
 
predicates
    tryGetFirst : () -> @Type Value determ.
    % @short @Type is the first element in the collection; fails if the collection is empty.
    % @end
 
predicates
    getAll_nd : () -> @Type Value nondeterm.
    % @short @Type is nondeterministic iteration of the elements in the collection.
    % @end
 
properties
    asList : @Type* (o).
    % @short All the elements in the collection as a list.
    % @end
 
end interface collection

If the support class have access to the getAll_nd predicate, it can implement all the other predicates in terms of it.

So the site will have to supply getAll_nd predicate:

interface collectionSupportSite{@Type}
 
predicates from collection{@Type}
    getAll_nd/0->
 
end interface collectionSupportSite

And then the support class will implement all the rest:

interface collectionSupport{@Type}
 
predicates from collection{@Type}
    isEmpty, tryGetFirst
 
properties from collection{@Type}
    asList
 
end interface collectionSupport

The implementation of the collectionSupport looks like this (here commented additionally):

implement collectionSupport{@Type}
 
facts
    site : collectionSupportSite{@Type}.
 
clauses
    new(Site) :-
        site := Site.
 
clauses
    isEmpty() :-
        not(_ = site:getAll_nd()).
 
clauses
    tryGetFirst() = First :-
        First = site:getAll_nd(),
        !.
 
clauses
    asList() = [ V || V = site:getAll_nd() ].
 
end implement collectionSupport