jueves, 18 de enero de 2018

Southwind : Gof Patterns example of Template method and Strategy patterns

Southwind C++ (codeblocks ide) project for GoF patterns practicing. It takes as example a possible template method from the trader company "Southwind" and the use of 2 different Strategies (Kanban and JustInTime).

Files in project:

main.cpp

:
#include 
#include "templatemethod.h"
#include 

using namespace std;

int main()
{
 const static vector * catalog = {"Tablets offer", "SmartPhones offer", "Javas offer", "Androids offer", "Creatives offer"};
 const static vector  * locations = {"KanbanCity","JustInTimeCity"};

  int status = -1;
  map> * tradingdata;
  Strategy * strategy = NULL;
  Context* context = NULL;
  TraderCompany* southwind = NULL;


  vector * preorder = createPreOrder(catalog);
  string* location = getLocation(locations);

  if(location->compare(locations->at(0))== 0))
   /* we work with Kanban city */
    strategy = new KanbanStrategy();
   else
    strategy = new JustinStrategy();

   context = new Context(strategy);


   southwind = new Southwind(context);
   /* call to the template method */
   status = southwind->trade(preorder);


   tradingdata = southwind->getTraderdata();


   return status;






}



vector* createPreOrder(vector* catalog) {

 vector * selecteds(-1,5);
 vector * preOrder ;

 vector::iterator it = catalog->begin();
 int i = 1;
 int j = 0;
 bool exit = false;

 cout << "Welcome to Southwind company please choose our offers : ";
 cout << endl << endl;
 cout << "Catalog :" << endl;
 while(it!= catalog->end()) {
    cout << "Number: " << i << " " << "Product: " << *it << "  " << endl;
    it++;
    i++;
 }

i = 100;
cout << "Choose your offers : (input correct offer's number (1-" << catalog->size() << ") or 0 number for exit) " << endl;

while(i!= 0 && !exit){
cout << "Offer's number: " << endl;
 cin >> i;

 if(i>0 && i< catalog->size())
    selecteds->push_back( i--);
 else{
    j++;
    cout << " Input number is incorrect (1-6)" << endl;
    i = 100;
   if(j==10){
    cout << "Too many incorrect input, exiting..." << endl;
    exit = true;
   }

 }

 it = selecteds->begin();
 while(it!= selecteds->end()){
    preOrder->push_back( catalog[ *(it++)]);

 }

    return preOrder;
}

string * getLocation( vector* locations) {


 string * loc;

 vector::iterator it = locations->begin();
 int i = 1;
 int j = 0;
 int k = 0;

 cout << "Welcome to Southwind, this are the possible locations:";
 cout << endl << endl;
 cout << "Location :" << endl;
 while(it!= locations->end()) {
    cout << "Number: " << i << " " << "Location : " << *it << "  " << endl;
    it++;
    i++;
 }

i = 100;

cout << "Choose your location : (input correct location's number (1-" << locations->size() << ") or 0 number for exit) " << endl;


while(i!= 0 && k>1){
cout<< "Location's number: " << endl;
 cin >> i;

 if(i>0 && i< locations->size()){
    selecteds->push_back( i--);
    k++;
 }
 else{
    j++;
    cout << " Input number is incorrect (1-" << localtions->size() << ")" << endl;
    i = 100;
   if(j==10){
    cout << "Too many incorrect input, exiting..." << endl;
    exit = true;
   }

 }

}

 it = selecteds->begin();
 while(it!= selecteds->end())
    *loc  =   locations[ *(it++)]);


    return loc;

}








templatemethod.h

: It contains template method implementation and strategy pattern dependency.
#ifndef TEMPLATEMETHOD_H_INCLUDED
#define TEMPLATEMETHOD_H_INCLUDED

#include 
#include 
#include "strategy.h"
#include 
#include 


/**
Southwind trading company

*/

typedef map> TradeData;

class TraderCompany {
public:
    TraderCompany(Context* c);
    ~TraderCompany();
    int trade(vector* preorder);
    virtual int takeOrder();
    virtual int prepareOrder();
    virtual int computePrice();
    virtual int doShipping();
    virtual int doConfirm();
    map>* getTraderdata();
    int doReport();
private:
    Context* _context;
    map>  * _tradedata;
    vector _preorder;
};

TraderCompany::TraderCompany(Context* c){
    this->_context = c;
}
int TraderCompany::trade(vector * preorder) {
    this->_preorder = preorder;
    this->takeOrder();
    this->prepareOrder();
    this->computePrice();
    this->doShipping();

    return this->doConfirm();

}
int TraderCompany::doConfirm() {
    cout << " Operation confirm!!";
    return this->doReport();
}
map>* TraderCompany::getTraderdata() {
    return this->_tradedata;
}

class Southwind: public TraderCompany {
public:
    Southwind(Context * c);
    ~Southwind();
    int trade(vector * preorder);
    virtual int takeOrder();
    virtual int prepareOrder();
    virtual int computePrice();
    virtual int doShipping();
    virtual int doConfirm();
    int doReport();
private:
    Context* _context;
    map>  * _tradedata;
    vector * _preorder;
};


#endif // TEMPLATEMETHOD_H_INCLUDED

strategy.h

: specific strategies to be implemented
#ifndef STRATEGY_H_INCLUDED
#define STRATEGY_H_INCLUDED
#include 
#include 
#include 
#include 

using namespace std;

typedef map> * TradeData;

class Strategy {
public:
 Strategy();
 ~Strategy();
 virtual int create(vector * input);
 virtual int prepare();
 virtual int ship();
 virtual int confirm();
 map> * getData();
private:
    map> * _data;
};


class JustinStrategy: public Strategy {

};

class KanbanStrategy: public Strategy {


};


class Context {
public:
    Context(Strategy * s);
    ~Context();
    virtual int createOrder(vector * input);
    virtual int prepareOrder();
    virtual int ship();
    virtual int confirm();
    map> * getOrder();
private:
    Strategy * _strategy;
    map>* _order;

};



#endif // STRATEGY_H_INCLUDED

Download project from Github

jueves, 4 de enero de 2018

GoF patterns launcher and Chain of Resposibility pattern example (C++)

A C++ (codeblocks ide) project for GoF patterns practicing.It can be extended with the rest of patterns (command, state, factory, mediator, etc...).

Files in project:

main.cpp

:
#include 
#include 
#include "chainofresp.h"
#include "patternexec.h"

using namespace std;

const int CHAIN = 2;

int main()
{
    int sdirective = 2;
    PatternExec* _patterne = 0;
    string name ="CHAIN";
    string conf = "1000";

    switch(sdirective){
    case CHAIN:
        _patterne =  new PatternExec(new ChainOfResp(name,conf));
    break;
    default:
        return -100;

    }

   int r =   _patterne->execute();

   if(!r)
    cout << "Program ended correctly" << endl;

    return r;
}

patternexec.h

: It contains pattern's launcher (command) and specific pattern (in this case ChainOfResp) runner.
#ifndef PATTERNEXEC_H_INCLUDED
#define PATTERNEXEC_H_INCLUDED

#include 
#include 
#include 

using namespace std;

class Pattern {
public:
Pattern();
Pattern(string name, string conf);
virtual int run();
private:
    string _name;
    string _conf;
};
Pattern::Pattern() {}
Pattern::Pattern(string name, string conf) {
     _name = name; _conf= conf;
}
int Pattern::run() {
cout<< "Running an empty pattern " << endl;
return 10;
}
class PatternExec {

public:
PatternExec();
PatternExec(Pattern* pattern);
virtual int execute();
private:
    Pattern* _pattern;
};
PatternExec::PatternExec(Pattern* p){ _pattern = p;}
int PatternExec::execute() {
    return this->_pattern->run();
}


class ChainOfResp: public Pattern {
public:
ChainOfResp();
ChainOfResp(string name, string conf);
virtual int run();
void setConf(string conf);
private:
    string _staticName = "CHAIN";
    int _deep;
};
ChainOfResp::ChainOfResp(){}
ChainOfResp::ChainOfResp(string name, string conf){
   if( _staticName != name) cout<<"Incorrect pattern Name" <setConf(conf);
}
void ChainOfResp::setConf(string conf) {
 if(conf == "1000")
    _deep = 1000;
}
/**
Here is where pattern is applied
The value _deep indicates the TOPIC value which determines which component will process the call
*/
int ChainOfResp::run(){

Widget* aButton;
Widget* aField;
Dialog* aConfirm;
Application* anApp;

anApp = new Application(0, (TOPIC) _deep);
aConfirm = new Dialog(anApp, (TOPIC) _deep);
aField = new Widget(aConfirm, (TOPIC) _deep);
aButton = new Widget(aConfirm, (TOPIC) _deep);
cout << "Launch ChainOfResp from Button" << endl;
aButton->handle();
cout << "Launch CofResp from Field" << endl;
aField->handle();

cout << _staticName << " Pattern ended correctly " << endl;
return 0;
}

#endif // PATTERNEXEC_H_INCLUDED

chainofresp.h

: specific pattern implementation
#ifndef CHAINOFRESP_H_INCLUDED
#define CHAINOFRESP_H_INCLUDED

#include 
#include 

using namespace std;

typedef  int TOPIC;
const TOPIC NO_VALUE = -1;

class Handler {
public:
Handler();
Handler(Handler* sucessor,TOPIC topic);
 virtual int handle();

 virtual int doProcess();

private:
    Handler* _sucessor;
    TOPIC _topic;
    const static TOPIC _myTopic = 0;
};
Handler::Handler(){}
Handler::Handler(Handler* sucessor, TOPIC topic){
_sucessor=sucessor;
_topic = topic;
}

int Handler::handle() {
    cout<< "Handling from Handler class" << endl;

   if(_topic == _myTopic){
        _sucessor->handle();
   }else doProcess();

}
int Handler::doProcess() {
    cout<< "Processing!!! from Handler class " << endl;
}

class Widget: public Handler {
public:
Widget();
Widget(Handler* widget, TOPIC topic);
virtual int handle();
virtual int doProcess();
private:
    Handler* _parent;
    TOPIC _topic;
   const static TOPIC _myTopic = 1;
};
Widget::Widget(){}
Widget::Widget(Handler* w, TOPIC topic) {
    _parent = w;
    _topic = topic;
}
int Widget::handle(){
cout << "Hadling from Widget class " << endl;
 if(_topic == _myTopic){
    _parent->handle();
 }else doProcess();

}

int Widget::doProcess() {
cout << "Processing from Widget class " << endl;
Handler::doProcess();
}

class Dialog:public Handler{
public:
    Dialog();
    Dialog(Handler* h, TOPIC t);
    virtual int handle();
    virtual int doProcess();
private:
    Handler* _handler;
    TOPIC _topic;
    const static TOPIC _myTopic = 2;
};
Dialog::Dialog(){}
Dialog::Dialog(Handler* h, TOPIC t):Handler(h,t) {

}

class Application:public Handler {
public:
    Application();
    Application(Handler* h, TOPIC t);
    int handle();
    int doProcess();
private:
    const Application* _app = this;
    const static TOPIC _myTopic = 1000;

};
Application::Application(){}
Application::Application(Handler* h, TOPIC t):Handler(h,t){}


#endif // CHAINOFRESP_H_INCLUDED

Download project from Github