[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Solving encryption using Design Patterns. Approach?

Posted on 2006-05-01
3
Medium Priority
?
839 Views
Last Modified: 2008-03-04
Hi,
Need help on a project.
I want to encrypt/decrypt simple text files, using key phrase Caesar cipher and Vigenere.

But, I want to approach the whole project using design patters, don’t know how one can solve it using patterns like Factory method, Abstract factory and proxy, Template method, Bridge.
Come from a TurboPascal background, have troubles planning my whole projects in terms of objects with design patterns.

Comand line goal: ./encrypt input output CaesarORVigenere EncryptORDecrypt Key phrase

Thanks for the time
TRG
0
Comment
Question by:TRG00
  • 2
3 Comments
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 1000 total points
ID: 16586079
Factory:

Creates class objects out of a group of classes. The point is that the decision what class to chose is made at runtime.  

To implement encryption by using a Factory pattern, you would need two classes, say class Cypher and and class Vigenere, and creation functions which return either a Cypher or Vingenere object. Both classes would be able to take either a plain or encrypted text. Dependent on the input arguments the Factory would create an object of Cypher or Vigenere and call the appropriate conversion method.

int main()
{
     string key;
     bool   encode;
     string input, output;
     if (parseCommandLine(key, encode, input))
     {
            Codec* pCodec = Codec::factory(key);  // call the *factory function* of baseclass Codec
            if (encode)
                 output = pCodec->encode(input);
            else
                 output = pCodec->decode(input);
      }
      cout << output << endl;
      return 0;
}

Note, factory(...) returns either a 'Caesar' or a 'Vigenere' object, where Caesar and Viginere are derived from Codec.

class Codec
{
public:
     virtual string encode(const string& input) = 0;  // pure virtual function
     virtual string decode(const string& input) = 0;  // must be overwritten by derived classes
     Codec* factory(const string& key);
};

The factory(...) function might be implemented like that:

Codec* Codec::factory(const string& key)
{
     if (key == "Caesar")
         return new Caesar;
     else if (key == "Viginere")
         return new Viginere;
     else
         return NULL;    
}


Abstract Factory:

An Abstract Factory is a Factory that doesn't know about the classes it can create objects of. You could add new classes without having to change the baseclass or factory class. That is done by registering objects of create functions of the derived classes in the factory class:

class Codec
{
    map<string, Codec*> factoryMap;
public:
    static void registerDerived(const string& key, Codec* pCodec); // each derived class would need to register
    Codec* factory(const string& key);
};

class Caesar : public Codec
{
     static bool registered;  // used to make the registering at runtime
     static bool register()
     {
          Codec::registerDerived("Caesar", new Caesar());
     }
public:
     ...
};

// caesar.cpp

  bool Caesar::registered = Caesar::register();


// codedec.cpp

Codec* Codec::factory(const string& key)
{
     map<string, Codec*>::iterator it = factoryMap.find(key);

     if (it != factoryMap.end())
         return it->second();
     else
         return NULL;    
}

Proxy:

A proxy is an abstract interface that transfers a given task to a configurable service. Don't think that a proxy is a suitable pattern for the coding problem.

Template:

Template is a pattern where you have functions or classes that can take an arbitrary type. Instead of using a baseclass Codec as I did in the code above, you could define a template class that could take either class Caesar or class Viginere as template argument. However, templates need to be instantiated at compile time.

string encodeString(const string& key, const string& input)
{
     if (key == "Caesar")
         return encode<Caesar>(input);
     else if (key == "Viginere")
         return encode<Viginere>(input);
     else
         return NULL;    
}

where there is a template function like

template <class T>
string encode<T> (const string& input)
{
     T t;
     return t.encode(input);
}

Note, the types must provide a member function T::encode(const string&). However, they don't need to be derived from a common baseclass.

Nevertheless, I don't think that the Template pattern has any advantage over factories for the encoding problem.

Bridge:

That is another name for using virtual functions and baseclass objects as in the (factory) sample code above. Bridge and Template are the alternatives.

Regards, Alex
0
 

Author Comment

by:TRG00
ID: 16595653
Thank you for the replay.

I am getting a really good idea now how one uses design patterns.

Think I will solve my projects, by using SINGLETON creating a operational class, then using a ITERATOR parse the command line, from there creating the object using FACTORY dp which is called by using TEMPLATE method.

Getting a hang of DP.
But are they actually widely used under Programmers?

CIA
TRG
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 16597210
>>>> But are they actually widely used under Programmers?

Yes and no. "Design Pattern" is a label that came up in the last ten years - as far as I know - which isn't protected. Therefore different people may have a different view of what DP is, especially if regarding different (programming) languages. Moreover, design patterns were used long before they were called like that. E. g. Bjarne Stroustrup, the father of C++, described Templates as an element of C++ while it is a design pattern as well. Same applies to 'Bridge'. Iterators were described in the reference manuals of any OO language, and so on.

>>>> by using SINGLETON creating a operational class

Good. Either use a Singleton for parsing only, e, g.

class ParseCommand
{
     enum Action { ENCODE, DECODE };
     string  codec;
     Action action;
     string  text;
     bool    valid;
public:
     ParseCommand(int nargs, char* pszArgs[]);
     bool isValid() { return valid; }
     ...
};

int main(int nargs, char* pszArgs[])
{
     ParseCommand parser(nargs, pszArgs) ;   // singleton
     if (parser.isValid())
     {
          ...
     }
     return 0;
}

 or for managing the the whole thing:

class Cryption
{
      ...
public:
      Cryption();
      bool run(int nargs, char* pszArgs[]);
      ...
};

int main(int nargs, char* pszArgs[])
{
     Cryption crypt;   // singleton
     return crypt.run(nargs, pszArgs);
}

>>>> then using a ITERATOR parse the command line

You would need to put the 'pszArgs' array to a vector<string>. Then you could use vector<string>::iterator.

>>>> from there creating the object using FACTORY

ABSTRACT FACTORY is much more interesting...

>>>> which is called by using TEMPLATE method

???

Actually a factory should be run in C++ by calling virtual functions.

Regards, Alex


0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
Suggested Courses

872 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question