------------------------------------------------------------------------------- getDescription ------------------------------------------------------------------------------- Illustrative method of the pattern METHOD getDescription: string ------------------------------------------------------------------------------- getValue ------------------------------------------------------------------------------- Ilustrative method of the pattern METHOD getValue: REAL ------------------------------------------------------------------------------- PLC_PRG ------------------------------------------------------------------------------- PROGRAM PLC_PRG VAR basicComponent: ConcreteComponent; iTempDisplay: INT; rDisplayValue: REAL; sDisplayDescription: string; ptrDecorA: pointer; ptrDecorB: pointer; ptrDecorC: pointer; bDecorA: BOOL; bDecorB: BOOL; bDecorC: BOOL; END_VAR //The visualization element will handle the request from the client in real time. //The client can chose any possible combination for the element and the display will show the specific results. //As there are 3 possible options, the programs checks a 3X3 matrix and checks the last handled request //If the user has not chosen any Decoration AND iTempDisplay is different to the initial state of 1, IF NOT bDecorA AND NOT bDecorB AND NOT bDecorC AND iTempDisplay <> 1 //000 THEN //Then the request from the client is just a basic component, // so from the basic component declared on the PLC_PRG declaration part the program delivers the results //The temporal Value field gets the actual value of the request from the basicComponent object rDisplayValue := basicComponent.getValue(); //The temporal Description field gets the actual value of the request from the basicComponent object sDisplayDescription := basicComponent.getDescription(); //The temporal state of the display is set to 1, this will avoid processing duplicate requests iTempDisplay := 1; END_IF //If the user has chosen only Decoration A AND iTempDisplay is different to this concrete state of 2, IF bDecorA AND NOT bDecorB AND NOT bDecorC AND iTempDisplay <> 2 //100 THEN //Then the request from the client is a basic component with Decoration A, // so from the basic component declared on the PLC_PRG declaration part the program delivers the results //First a ConcreteDecoratorA object must be created passing as an argument the basicComponent object ptrDecorA := __NEW(ConcreteDecoratorA(tempInputComponent := basicComponent)); //The temporal Value field gets the actual value of the request from the ConcreteDecoratorA object rDisplayValue := ptrDecorA^.getValue(); //The temporal Description field gets the actual value of the request from the ConcreteDecoratorA object sDisplayDescription := ptrDecorA^.getDescription(); //The temporal state of the display is set to 2, this will avoid processing duplicate requests iTempDisplay := 2; //Now the ConcreteDecoratorA object is destroyed to free memory __DELETE(ptrDecorA); END_IF //If the user has chosen Decorations A and B AND iTempDisplay is different to this concrete state of 3, IF bDecorA AND bDecorB AND NOT bDecorC AND iTempDisplay <> 3 //110 THEN //Then the request from the client is just a basic component, // so from the basic component declared on the PLC_PRG declaration part the program delivers the results //First a ConcreteDecoratorA object must be created passing as an argument the basicComponent object ptrDecorA := __NEW(ConcreteDecoratorA(tempInputComponent := basicComponent)); //Then a ConcreteDecoratorB object must be created passing as an argument the ConcreteDecoratorA object ptrDecorB := __NEW(ConcreteDecoratorB(tempInputComponent := ptrDecorA^)); //The temporal Value field gets the actual value of the request from the ConcreteDecoratorB object rDisplayValue := ptrDecorB^.getValue(); //The temporal Description field gets the actual value of the request from the ConcreteDecoratorB object sDisplayDescription := ptrDecorB^.getDescription(); //The temporal state of the display is set to 3, this will avoid processing duplicate requests iTempDisplay := 3; //Now the ConcreteDecoratorA object is destroyed to free memory __DELETE(ptrDecorA); //Now the ConcreteDecoratorB object is destroyed to free memory __DELETE(ptrDecorB); END_IF //If the user has chosen Decorations A, B and C AND iTempDisplay is different to this concrete state of 4, IF bDecorA AND bDecorB AND bDecorC AND iTempDisplay <> 4 //111 THEN //Then the request from the client is just a basic component, // so from the basic component declared on the PLC_PRG declaration part the program delivers the results //First a ConcreteDecoratorA object must be created passing as an argument the basicComponent object ptrDecorA := __NEW(ConcreteDecoratorA(tempInputComponent := basicComponent)); //Then a ConcreteDecoratorB object must be created passing as an argument the ConcreteDecoratorA object ptrDecorB := __NEW(ConcreteDecoratorB(tempInputComponent := ptrDecorA^)); //Then a ConcreteDecoratorC object must be created passing as an argument the ConcreteDecoratorB object ptrDecorC := __NEW(ConcreteDecoratorC(tempInputComponent := ptrDecorB^)); //The temporal Value field gets the actual value of the request from the ConcreteDecoratorC object rDisplayValue := ptrDecorC^.getValue(); //The temporal Description field gets the actual value of the request from the ConcreteDecoratorC object sDisplayDescription := ptrDecorC^.getDescription(); //The temporal state of the display is set to 4, this will avoid processing duplicate requests iTempDisplay := 4; //Now the ConcreteDecoratorA object is destroyed to free memory __DELETE(ptrDecorA); //Now the ConcreteDecoratorB object is destroyed to free memory __DELETE(ptrDecorB); //Now the ConcreteDecoratorC object is destroyed to free memory __DELETE(ptrDecorC); END_IF //If the user has chosen Decorations A and C AND iTempDisplay is different to this concrete state of 2, IF bDecorA AND NOT bDecorB AND bDecorC AND iTempDisplay <> 5 //101 THEN //Then the request from the client is just a basic component, // so from the basic component declared on the PLC_PRG declaration part the program delivers the results //First a ConcreteDecoratorA object must be created passing as an argument the basicComponent object ptrDecorA := __NEW(ConcreteDecoratorA(tempInputComponent := basicComponent)); //Then a ConcreteDecoratorC object must be created passing as an argument the ConcreteDecoratorA object ptrDecorC := __NEW(ConcreteDecoratorC(tempInputComponent := ptrDecorA^)); //The temporal Value field gets the actual value of the request from the ConcreteDecoratorC object rDisplayValue := ptrDecorC^.getValue(); //The temporal Description field gets the actual value of the request from the ConcreteDecoratorC object sDisplayDescription := ptrDecorC^.getDescription(); //The temporal state of the display is set to 5, this will avoid processing duplicate requests iTempDisplay := 5; //Now the ConcreteDecoratorA object is destroyed to free memory __DELETE(ptrDecorA); //Now the ConcreteDecoratorC object is destroyed to free memory __DELETE(ptrDecorC); END_IF //If the user has chosen only Decoration B AND iTempDisplay is different to this concrete state of 6, IF NOT bDecorA AND bDecorB AND NOT bDecorC AND iTempDisplay <> 6 //010 THEN //Then the request from the client is just a basic component, // so from the basic component declared on the PLC_PRG declaration part the program delivers the results //First a ConcreteDecoratorB object must be created passing as an argument the basicComponent object ptrDecorB := __NEW(ConcreteDecoratorB(tempInputComponent := basicComponent)); //The temporal Value field gets the actual value of the request from the ConcreteDecoratorB object rDisplayValue := ptrDecorB^.getValue(); //The temporal Description field gets the actual value of the request from the ConcreteDecoratorB object sDisplayDescription := ptrDecorB^.getDescription(); //The temporal state of the display is set to 6, this will avoid processing duplicate requests iTempDisplay := 6; //Now the ConcreteDecoratorB object is destroyed to free memory __DELETE(ptrDecorB); END_IF //If the user has chosen Decorations B and C AND iTempDisplay is different to this concrete state of 7, IF NOT bDecorA AND bDecorB AND bDecorC AND iTempDisplay <> 7 //011 THEN //Then the request from the client is just a basic component, // so from the basic component declared on the PLC_PRG declaration part the program delivers the results //First a ConcreteDecoratorB object must be created passing as an argument the basicComponent object ptrDecorB := __NEW(ConcreteDecoratorB(tempInputComponent := basicComponent)); //Then a ConcreteDecoratorC object must be created passing as an argument the ConcreteDecoratorB object ptrDecorC := __NEW(ConcreteDecoratorC(tempInputComponent := ptrDecorB^)); //The temporal Value field gets the actual value of the request from the ConcreteDecoratorC object rDisplayValue := ptrDecorC^.getValue(); //The temporal Description field gets the actual value of the request from the ConcreteDecoratorC object sDisplayDescription := ptrDecorC^.getDescription(); //The temporal state of the display is set to 7, this will avoid processing duplicate requests iTempDisplay := 7; //Now the ConcreteDecoratorB object is destroyed to free memory __DELETE(ptrDecorB); //Now the ConcreteDecoratorC object is destroyed to free memory __DELETE(ptrDecorC); END_IF //If the user has chosen only Decoration C AND iTempDisplay is different to this concrete state of 8, IF NOT bDecorA AND NOT bDecorB AND bDecorC AND iTempDisplay <> 8 //001 THEN //Then the request from the client is just a basic component, // so from the basic component declared on the PLC_PRG declaration part the program delivers the results //First a ConcreteDecoratorC object must be created passing as an argument the basicComponent object ptrDecorC := __NEW(ConcreteDecoratorC(tempInputComponent := basicComponent)); //The temporal Value field gets the actual value of the request from the ConcreteDecoratorC object rDisplayValue := ptrDecorC^.getValue(); //The temporal Description field gets the actual value of the request from the ConcreteDecoratorC object sDisplayDescription := ptrDecorC^.getDescription(); //The temporal state of the display is set to 8, this will avoid processing duplicate requests iTempDisplay := 8; //Now the ConcreteDecoratorC object is destroyed to free memory __DELETE(ptrDecorC); END_IF ------------------------------------------------------------------------------- ConcreteComponent ------------------------------------------------------------------------------- This class creates the most basic object well called. This object is to be decorated FUNCTION_BLOCK ConcreteComponent VAR sDescription: string; rValue: REAL; END_VAR ------------------------------------------------------------------------------- getDescription ------------------------------------------------------------------------------- Illustrative method of the pattern METHOD getDescription: string //Description of the plain object is given getDescription := This^.sDescription; ------------------------------------------------------------------------------- getValue ------------------------------------------------------------------------------- Illustrative method of the pattern METHOD getValue: REAL //Assume we are going to calculate the cost os the object. //The plain value (without extra decoration) is given getValue := THIS^.rValue; ------------------------------------------------------------------------------- fb_init ------------------------------------------------------------------------------- METHOD fb_init: VAR_INPUT bInitRetains: BOOL; bInCopyCode: BOOL; END_VAR //Sets the default description for the objects of this class THIS^.sDescription := 'Plain Component'; //Sets the default value for the objects of this class THIS^.rValue := 4.0; ------------------------------------------------------------------------------- Decorator ------------------------------------------------------------------------------- This class mainteins the reference to a ConcreteComponent object and works as an interface for its subclasses to decorate the ConcreteComponent FUNCTION_BLOCK Decorator VAR tempComponent: Component_Interface; sDescription: string; rValue: REAL; END_VAR ------------------------------------------------------------------------------- getDescription ------------------------------------------------------------------------------- Illustrative method of the pattern METHOD getDescription: string //Outputs the description of the component to be decorated tempComponent. If tempComponent is not an undecorated component (plain object) // it means the program has to do at least 2 decorations. Then is going to output the previous decoration complete description // to be used by the next decorator. getDescription := THIS^.tempComponent.getDescription(); ------------------------------------------------------------------------------- getValue ------------------------------------------------------------------------------- Illustrative method of the pattern METHOD getValue: REAL //Outputs the cost of the component to be decorated tempComponent. If tempComponent is not an undecorated component (plain object) // it means the program has to do at least 2 decorations. Then is going to output the previous decoration complete value // to be used by the next decorator. getValue := tempComponent.getValue(); ------------------------------------------------------------------------------- fb_init ------------------------------------------------------------------------------- Constructor of the decorator class called at instanciation METHOD fb_init: VAR_INPUT bInitRetains: BOOL; bInCopyCode: BOOL; tempInputComponent: Component_Interface; END_VAR //This constructor stores the component to be decorated in its field tempComponent in orer to be used by all its subclasses THIS^.tempComponent := tempInputComponent; ------------------------------------------------------------------------------- ConcreteDecoratorA ------------------------------------------------------------------------------- This class acts as a decorating class. It adds responsibilities and functionality to the component FUNCTION_BLOCK ConcreteDecoratorA EXTENDS Decorator VAR_INPUT tempInputComponent: Component_Interface; END_VAR ------------------------------------------------------------------------------- getDescription ------------------------------------------------------------------------------- Illustrative method of the pattern METHOD getDescription: string //Outputs the decorated description of the component by obtaining the description of the component // to be decorated stored in tempComponet.getDescription() and then concatenates the decoration // description( ' Decorator A' as example) getDescription :=CONCAT(THIS^.tempComponent.getDescription() , THIS^.sDescription); ------------------------------------------------------------------------------- getValue ------------------------------------------------------------------------------- Illustrative method of the pattern METHOD getValue: REAL //Outputs the decorated cost of the component by obtaining the cost of the component to be decorated // stored in tempComponent.getValue() and then adds the decoration value (0.5 as example) getValue := tempComponent.getValue() + THIS^.rValue; ------------------------------------------------------------------------------- fb_init ------------------------------------------------------------------------------- Constructor of the decorating class called at instanciation METHOD fb_init: VAR_INPUT bInitRetains: BOOL; bInCopyCode: BOOL; tempInputComponent: Component_Interface; END_VAR //Calls the constructor (fb_init) in its SUPER class (Decorator) // in order to pass the component to be decorated to the Decorator constructor. SUPER^.fb_init(TRUE, TRUE, tempInputComponent); //Sets the default description for the objects of this class THIS^.sDescription := ' Decorator A'; //Sets the default value for the objects of this class THIS^.rValue := 0.5; ------------------------------------------------------------------------------- ConcreteDecoratorB ------------------------------------------------------------------------------- This class acts as a decorating class. It adds responsibilities and functionality to the component FUNCTION_BLOCK ConcreteDecoratorB EXTENDS Decorator VAR_INPUT tempInputComponent: Component_Interface; END_VAR ------------------------------------------------------------------------------- getDescription ------------------------------------------------------------------------------- Illustrative method of the pattern METHOD getDescription: string //Outputs the decorated description of the component by obtaining the description of the component // to be decorated stored in tempComponet.getDescription() and then concatenates the decoration // description( ' Decorator B' as example) getDescription :=CONCAT(THIS^.tempComponent.getDescription() , THIS^.sDescription); ------------------------------------------------------------------------------- getValue ------------------------------------------------------------------------------- Illustrative method of the pattern METHOD getValue: REAL //Outputs the decorated cost of the component by obtaining the cost of the component to be decorated // stored in tempComponent.getValue() and then adds the decoration value (0.35 as example) getValue := tempComponent.getValue() + THIS^.rValue; ------------------------------------------------------------------------------- fb_init ------------------------------------------------------------------------------- Constructor of the decorating class called at instanciation METHOD fb_init: VAR_INPUT bInitRetains: BOOL; bInCopyCode: BOOL; tempInputComponent: Component_Interface; END_VAR //Calls the constructor (fb_init) in its SUPER class (Decorator) // in order to pass the component to be decorated to the Decorator constructor. SUPER^.fb_init(TRUE, TRUE, tempInputComponent); //Sets the default description for the objects of this class THIS^.sDescription := ' Decorator B'; //Sets the default value for the objects of this class THIS^.rValue := 0.35; ------------------------------------------------------------------------------- ConcreteDecoratorC ------------------------------------------------------------------------------- This class acts as a decorating class. It adds responsibilities and functionality to the component FUNCTION_BLOCK ConcreteDecoratorC EXTENDS Decorator VAR_INPUT tempInputComponent: Component_Interface; END_VAR ------------------------------------------------------------------------------- getValue ------------------------------------------------------------------------------- Ilustrative method of the pattern METHOD getValue: REAL //Outputs the decorated cost of the component by obtaining the cost of the component to be decorated // stored in tempComponent.getValue() and then adds the decoration value (0.15 as example) getValue := tempComponent.getValue() + THIS^.rValue; ------------------------------------------------------------------------------- getDescription ------------------------------------------------------------------------------- Illustrative method of the pattern METHOD getDescription: string //Outputs the decorated description of the component by obtaining the description of the component // to be decorated stored in tempComponet.getDescription() and then concatenates the decoration // description( ' Decorator C' as example) getDescription :=CONCAT(THIS^.tempComponent.getDescription() , THIS^.sDescription); ------------------------------------------------------------------------------- fb_init ------------------------------------------------------------------------------- Constructor of the decorator class called at instanciation METHOD fb_init: VAR_INPUT bInitRetains: BOOL; bInCopyCode: BOOL; tempInputComponent: Component_Interface; END_VAR //Calls the constructor (fb_init) in its SUPER class (Decorator) // in order to pass the component to be decorated to the Decorator constructor. SUPER^.fb_init(TRUE, TRUE, tempInputComponent); //Sets the default description for the objects of this class THIS^.sDescription := ' Decorator C'; //Sets the default value for the objects of this class THIS^.rValue := 0.15;