473,387 Members | 1,899 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Name-Based Object Creation

I'm working on the client side of a distributed application that uses what I
call an XML over quasi-HTTP protocol. The client and server are connected
with a single persistent socket and exchange messages that look something
like this:

Content-type: P51Mustang
Content-length: 147

<?xml version="1.0"?>
<P51Mustang>
<Pilot>SGT Yeager</Pilot>
<Fuel units="gallons">600</Fuel>
<Guns caliber="50">6</Guns>
</P51Mustang>

After parsing the HTTP-like headers, the problem boils down to how to
deserialize this object give its name in the Content-type string. In other
words, how to go about creating an object of type class P51Mustang given
that the message is a "P51Mustang" message.

I'm considering a number of ways to do this and wondered if anyone else has
any different ideas. So far I've come up with:

1. A BIG if-else if-else statement that considers all possible object types:
// maintenance nightmare, I know.
if(contenttype == "P51Mustang")
p = new P51Mustang;
2. A "map" object, using STL or another library, that maps a string to a
function pointer to create the appropriate type of object. The map object
must be populated (hard-coded) to map the names of the various types of
objects to the appropriate function pointers before being used. Another
maintenance nightmare, much like the BIG if-else if- else statement above.
Use would go something like this:
typedef IncomingMessage* (*fpCreateMsg)( );
void *fpv = 0;
if(map.Lookup(contenttype, fpv))
{
// fpv now points to a function will create the appropriate object
type.
fpCreateMsg fp = (fpCreateMsg)fpv; // now we have a function pointer
that can be invoked.
IncomingMessage *pMessage = (*fp)( );
// We now have an uninitialized P51Mustang object, although the
calling object only knows that it's an IncomingMessage.
// pMessage can be use to initialize the object with the XML here.
// Getting the right thing to happen next is a double-dispatch
problem, but I don't want to get into that here.
}
3. Use a DLL (running on Windows) to find the appropriate function based on
contenttype. Easier maintenance, but might be slower than above methods:
void *fpv = GetProcAddress(hModule, contenttype);
if(fpv)
{
// we can proceed as in 2. above if Lookup succeeds.
4. A combination of 2. and 3. above where the function pointer is retrieved
from the DLL if it is not found in the map and then stored in the map for
later (and faster) use. Easier maintenance than 1. and 2. above, and
probably pretty fast.

Any other ideas? I realize that there are many middleware solutions as well
as commercially available and shareware libraries that deal with such object
deserializations over a network, but unfortunately I am not able to use any
of these do to management decisions.

Thanks!

Mike
Jul 22 '05 #1
6 1442
Mike Monagle wrote:
I'm working on the client side of a distributed application that uses what I
call an XML over quasi-HTTP protocol. The client and server are connected
with a single persistent socket and exchange messages that look something
like this:


....

Check out "factory pattern".

An implementation is :
http://austria.sourceforge.net/dox/h...Factories.html

(shameless plug)

Download the Austria source, check out the factory test case.
Jul 22 '05 #2
Mike Monagle wrote:
typedef IncomingMessage* (*fpCreateMsg)( );
void *fpv = 0;
if(map.Lookup(contenttype, fpv))
{
// fpv now points to a function will create the appropriate object
type.
fpCreateMsg fp = (fpCreateMsg)fpv; // now we have a function

pointer

Why is there a typecast there? If you use STL map, and if all creators have
the same signature, you won't need a typecast.

Crack the book /Design Patterns/, and look at the Prototype and Factory
patterns for your system. The most important thing to resolve is how to add
new items. A big if-then-else chain won't make that easy. The Prototype
pattern can decouple all the types from their own list.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #3
OK. Thanks. I'll check that out.

Mike

"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:cf********@dispatch.concentric.net...
Mike Monagle wrote:
I'm working on the client side of a distributed application that uses what I call an XML over quasi-HTTP protocol. The client and server are connected with a single persistent socket and exchange messages that look something like this:


...

Check out "factory pattern".

An implementation is :
http://austria.sourceforge.net/dox/h...Factories.html

(shameless plug)

Download the Austria source, check out the factory test case.

Jul 22 '05 #4
Why is there a typecast there? It's because the sample I concocted for
myself used MFC and not STL. If I had used STL for my sample, and I may end
up using STL eventually, the typecast will not be required.

Yes, my problem could definitely fall into the Factory pattern, or even the
Prototype pattern.

So I cracked "the book" and found that it had to say this about the Factory
Method:

Product* Creator::Create::Create(ProductId id)
{
if(id == MINE)
return new MyProduct:
else if(id == YOURS)
return new YourProduct;
// and so on....
else
return NULL;
)

That's fine. It's just that my ProductId is a String and there are dozens
of different Product(s) that may be created. The Factory Method is fine.
It just makes me wonder about what the best way to implement this.

As far as the Prototype method goes, "the book" has this to say about it:

"A prototype manager is an associative store that returns the prototype
matching a given key." My question then becomes "What is the best way to
implement such an associative store given that the key is a string and there
are dozens or key-prototype pairs?"

Thanks,

Mike

"Phlip" <ph*******@yahoo.com> wrote in message
news:F2****************@newssvr19.news.prodigy.com ...
Mike Monagle wrote:
typedef IncomingMessage* (*fpCreateMsg)( );
void *fpv = 0;
if(map.Lookup(contenttype, fpv))
{
// fpv now points to a function will create the appropriate object type.
fpCreateMsg fp = (fpCreateMsg)fpv; // now we have a function pointer

Why is there a typecast there? If you use STL map, and if all creators

have the same signature, you won't need a typecast.

Crack the book /Design Patterns/, and look at the Prototype and Factory
patterns for your system. The most important thing to resolve is how to add new items. A big if-then-else chain won't make that easy. The Prototype
pattern can decouple all the types from their own list.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces

Jul 22 '05 #5
Mike Monagle wrote:
"A prototype manager is an associative store that returns the prototype
matching a given key." My question then becomes "What is the best way to
implement such an associative store given that the key is a string and there are dozens or key-prototype pairs?"


#include <map>

class
clonable
{
public:
virtual clonable *clone() = 0;
virtual string weBe() = 0;
};

class
red: public clonable
{
public:
virtual string weBe() { return "red"; }
clonable * clone() { return new red(*this); }
};

class
green: public clonable
{
public:
virtual string weBe() { return "green"; }
clonable * clone() { return new green(*this); }
};

class
blue: public clonable
{
public:
virtual string weBe() { return "blue"; }
clonable * clone() { return new blue(*this); }
};
TEST_(TestCase, clonable)
{

red aRed; green aGreen; blue aBlue;
typedef std::map<string, clonable*> clonables_t;
clonables_t clonables;
clonables[aRed .weBe()] = &aRed ;
clonables[aGreen.weBe()] = &aGreen;
clonables[aBlue .weBe()] = &aBlue ;

clonable * clone = clonables["blue"]->clone();
CPPUNIT_ASSERT_EQUAL("blue", clone->weBe());
delete clone;

clone = clonables["red"]->clone();
CPPUNIT_ASSERT_EQUAL("red", clone->weBe());
delete clone;

clone = clonables["green"]->clone();
CPPUNIT_ASSERT_EQUAL("green", clone->weBe());
delete clone;

}

Notice something very important. I could export 'clonables' to any module,
and that module would register its clonable things with it. This system does
not require the module owning 'clonables' to import every module in a
system. The leaf types - red, green, blue - are all decoupled from each
other. Each only needs to know about itself and 'clonables'. This represents
the Dependency Inversion Principle.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #6
On Sat, 14 Aug 2004 23:01:56 -0600, "Mike Monagle"
<mi*********@nospam.comcast.net> wrote:
Why is there a typecast there? It's because the sample I concocted for
myself used MFC and not STL. If I had used STL for my sample, and I may end
up using STL eventually, the typecast will not be required.

Yes, my problem could definitely fall into the Factory pattern, or even the
Prototype pattern.

So I cracked "the book" and found that it had to say this about the Factory
Method:

Product* Creator::Create::Create(ProductId id)
{
if(id == MINE)
return new MyProduct:
else if(id == YOURS)
return new YourProduct;
// and so on....
else
return NULL;
)

That's fine. It's just that my ProductId is a String and there are dozens
of different Product(s) that may be created. The Factory Method is fine.
It just makes me wonder about what the best way to implement this.

As far as the Prototype method goes, "the book" has this to say about it:

"A prototype manager is an associative store that returns the prototype
matching a given key." My question then becomes "What is the best way to
implement such an associative store given that the key is a string and there
are dozens or key-prototype pairs?"


The prototype method doesn't look like the ideal choice here, since
that is better when you need to clone some prototype products, rather
than just create new ones. Something like this:

template <class Base, class Derived>
Base* create()
{
return new Derived;
}

//id to creation function map:
std::map<ProductId, Product* (*)()> m_products;

template <class AProduct>
void Creator::RegisterProduct(ProductId id)
{
m_products[id] = &create<Product, AProduct>;
}

Product* Creator::Create::Create(ProductId id)
{
map_t::const_iterator i = m_products.find(id);
if (i == m_products.end())
return NULL;

return i->second();
}

Then you register a product with:

mycreator.RegisterProduct<Spanner>(Spanner::id); //or similar

and create it with:

Product* p = mycreator.Create(anid);

There are lots of variations; a description of a generic
implementation can be found in Alexandrescu's book, "Modern C++
Design".

Tom
Jul 22 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: ja | last post by:
Hello, I have a table that has a name field with the following data john doe john doe smith john d smith I need to separate the first, middle and last names into separate fields. ex....
2
by: Ravi | last post by:
My XML looks like: <abc> <def type="apple"> 1 </def> <def type="peach"> 2 </def> <def type="orange"> 3 </def> <def type="banana"> 4 </def> <def type="plum"> 5 </def> </abc>
2
by: Sebastian Kerekes | last post by:
Greetings, I'm new to XSD and I'm trying to create a schema for the following: The document 'persons' should contain 0+ elements of type 'person', which has a subelement called 'name' which is a...
1
by: discomiller | last post by:
Mario Mueller: Hello *, radiobuttons belong to other radiobuttons by the "name="any_value"" attribut. Thats a fakt. I got the following XML:...
12
by: CJ | last post by:
Why won't this work? I am passing the name of the form (I have two that use this validation script) but I keep getting an error. Error reads: "document.which_form.name is null or not an object" ...
2
by: nick_tucker | last post by:
Hi, I am very new to XML and XPATH. I have made a sample XML fileto ask my question. <?xml version="1.0" encoding="utf-8"?> <Test> <A> <B> <C> <D>
3
by: TomislaW | last post by:
I am sending word document with e-mail from asp.net 2.0 application. I read doc file like this:FileStream fs = System.IO.File.Open(docPath,FileMode.Open,FileAccess.Read,FileShare.Read); Then...
1
by: ivanet | last post by:
Hello everyone, I am trying to use the following Schema but I get the error "src- resolve: Cannot resolve the name 'ValuesList' to a(n) 'element declaration' component." at line 144. I have...
1
by: mark | last post by:
Forgive me if this seems like a stupid question but I need help... I'm trying to do a simple online form that emails me the results from a few fields. Here is the code: <form...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.