Exforsys

Online Training

How to organize-class/object relationship

This is a discussion on How to organize-class/object relationship within the Software Patterns forums, part of the Testing category; I have to construct a service that client programmers will use, eventually, client programmer can see the service through one ...


Go Back   Exforsys > Testing > Software Patterns

Register FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-07-2005, 10:00 AM
ishijak
Guest
 
Posts: n/a
How to organize-class/object relationship

I have to construct a service that client programmers will use,
eventually, client programmer can see the service through one interface
and one class that will create and return references to particular
implementation of that interface.

public interface Customer
{
// decreases the customer account by value of volume
void getMoney(double volume)

// increases the customer account by value of volume
void putMoney(double volume)

// returns unique customer id
String id();
}

public class CustomerCreator
{
// creates particular impl. of the Customer based on id
public Customer createCustomer(String id);

public void destroy(Customer cust);
}


// handles Customer whose id's are "3[0-9].*"
// This is a facade to subsystem that handles the group of these
customers
class CustomerImplOfType3 implements Customer
{
public void getMoney(double volume){}
public void putMoney(double volume){}
public String id(){}
}


// handles Customer whose id's are "7[0-9].*"
// This is a facade to subsystem that handles the group of these
customers
class CustomerImplOfType7 implements Customer
{
public void getMoney(double volume){}
public void putMoney(double volume){}
public String id(){}
}

Based on "id" value, there are completely different
ways(implementations) for handling customers and different subsystems
are involved. CustomerCreator has to decide from which implementation
to make instance. Customer implementations (Facades to subsystems) will
increase over time and existing ones will change. Also I want to have
possability to implement new CustomerImpls and to do not have to
recompile neither the framework classes, neither the existing
implementations (if they're still valid).
CustomerCreator.createCustomer will throw "Notsupported" if there is no
impelmentation that can handle given id.


One approach is to create an array of prototypes of CustomerImpl, all
of them will implement boolean canYouHandle(String id) and the
CustomerCreator object shall iterate and ask every prototype, and to
clone that one that will answer "yes(true)"

So the implemenatation will look something like this:


---charging framework package---

package chargingfw;

// Client programmers will use this interface to manipulate the
customers
public interface Customer
{
// decreases the customer account by value of volume
void getMoney(double volume);

// increases the customer account by value of volume
void putMoney(double volume);

// returns unique customer id
String id();
}


// subsystem programmers will use this interface to integrate
subsystems in the application
public interface CustomerFacadeBase extends Customer
{
public boolean canYouHandle(String id);
public CustomerFacadeBase instance(String id);
}

public class CustomerCreator
{
ArrayList<CustomerFacadeBase> custPrototypes;

public CustomerCreator(String[] listOfImpls)
{
for (each i in listOfImpls)
{
//load corresponding classes
// create prototype instance
custPrototypes.add(currenProto);
}
}


// creates particular impl. of the Customer based on id
Customer createCustomer(String id) throws Unsupported
{
for (each i in custPrototypes)
{
if (i.canYouHandle(id))
return i.instance(id);
}
throw new Unsupported(id);
}

void destroy(Customer cust);
}


---Subsystem3 Facade Implemenation package---

// handles Customer whose id's are "3[0-9].*"
// This is a facade to subsystem that handles these customers
final class CustomerImplOfType3 implements CustomerFacadeBase
{

public CustomerImplOfType3(String id)
{
_id = id;
init_subsystem();
}

public void getMoney(double volume){}
public void putMoney(double volume){}
public String id(){}

public CustomerFacadeBase instance(String id)
{
return new CustomerImplOfType7(id);
}


public boolean canYouHandle(String id)
{
if (id like "3[0-9].*")
return true;
return false;
}

private Subsystem3 ss;

}

---Subsystem7 Facade Implemenation package---

// handles Customer whose id's are "7[0-9].*"
// This is a facade to subsystem that handles these customers
final class CustomerImplOfType7 implements CustomerFacadeBase
{
public CustomerImplOfType7(String id)
{
_id = id;
init_subsystem();
}

public void getMoney(double volume) {}
public void putMoney(double volume){}
public String id(){}


public CustomerFacadeBase instance(String id)
{
return new CustomerImplOfType7(id);
}

public canYouHandle(String id)
{
if (id like "7[0-9].*")
return true;
return false;
}

private Subsystem7 ss;
String _id;
}


It would be better if only one object instance per customer exists in
the application, and all manipulation to go through that inctance for
particular customer.


---client code---

// client code shall be multithreaded,

import chargingfw;

main()
{
String[] ssFacades = //subsystem facade class names
CustomerCreator cr = new CustomerCreator(ssFacades);

Customer cust = cr.createCustomer("3124455");
cust.getMoney(10);
...
...
cr.destroy(cust);

}

My questions are:
Is this approach good?
Any suggestions for better design?
Issues?

Thanks,
Ivan Sijakovski

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 02-07-2005, 10:29 AM
Robert Klemme
Guest
 
Posts: n/a
Re: How to organize-class/object relationship


"ishijak" <ishijak@gmail.com> schrieb im Newsbeitrag
news:1107784849.988717.113990@c13g2000cwb.googlegroups.com...
> I have to construct a service that client programmers will use,
> eventually, client programmer can see the service through one interface
> and one class that will create and return references to particular
> implementation of that interface.
>
> public interface Customer
> {
> // decreases the customer account by value of volume
> void getMoney(double volume)
>
> // increases the customer account by value of volume
> void putMoney(double volume)
>
> // returns unique customer id
> String id();
> }
>
> public class CustomerCreator
> {
> // creates particular impl. of the Customer based on id
> public Customer createCustomer(String id);
>
> public void destroy(Customer cust);
> }
>
>
> // handles Customer whose id's are "3[0-9].*"
> // This is a facade to subsystem that handles the group of these
> customers
> class CustomerImplOfType3 implements Customer
> {
> public void getMoney(double volume){}
> public void putMoney(double volume){}
> public String id(){}
> }
>
>
> // handles Customer whose id's are "7[0-9].*"
> // This is a facade to subsystem that handles the group of these
> customers
> class CustomerImplOfType7 implements Customer
> {
> public void getMoney(double volume){}
> public void putMoney(double volume){}
> public String id(){}
> }
>
> Based on "id" value, there are completely different
> ways(implementations) for handling customers and different subsystems
> are involved. CustomerCreator has to decide from which implementation
> to make instance. Customer implementations (Facades to subsystems) will
> increase over time and existing ones will change. Also I want to have
> possability to implement new CustomerImpls and to do not have to
> recompile neither the framework classes, neither the existing
> implementations (if they're still valid).
> CustomerCreator.createCustomer will throw "Notsupported" if there is no


> impelmentation that can handle given id.
>
>
> One approach is to create an array of prototypes of CustomerImpl, all
> of them will implement boolean canYouHandle(String id) and the
> CustomerCreator object shall iterate and ask every prototype, and to
> clone that one that will answer "yes(true)"
>
> So the implemenatation will look something like this:


<snip/>

> My questions are:
> Is this approach good?
> Any suggestions for better design?
> Issues?


If you have only a small set of sub systems, then I'd probably just have
that many createCustomerTypeX(String id) methods and determine the
appropriate method programmatically "if (id.startsWith("3") ... else
if...".

If it's more complex I'd have a factory for each subsystem and class
CustomerCreator (better CustomerFactory) just delegates to the appropriate
subsystem factory; the simplest approach would be to just iterate through
all factories and ask each in turn whether it feels like handling this
particular id (for creation) or instance (for deletion).

You might also consider to put the delete method into the Customer
interface because the customer can easily know its factory. Drawback is a
certain degree of asymmetry between creation and deletion.

Kind regards

robert

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 02-08-2005, 04:59 AM
kurbylogic@hotmail.com
Guest
 
Posts: n/a
Re: How to organize-class/object relationship

I think that is a reasonable approach.

Another option you might concider is meta data.
Instead of i.canYouHandle(String Id)
you could use configuration files to associate an id or pattern with a
typename.
<customerTypes>
<add pattern="3[0-9].*"
typeName="CustomerImplOfType3"/>
...
</customerTypes>

This could also become a source of (mis)configuration errors so
sometimes its not worth adding flexibility where it isn't needed.
However in this case perhaps it is appropriate, expecially with "magic
numbers." Today it is 3[0-9], but tomorrow when decide to convert all
there existing data to use an alpha prefix instead it becomes C[0-9],
not only do you have to modify the code its also distributed across
many class files. If you decide it is so unlikely to change you would
rather modify the source code than maintain config files then using a
if/else/switch statements in the factory would at least centralize the
type mapping functionality.
canYouHandle does not seem complex enough in this scenario to
distribute the function to the various individual objects. If logic
begins to get more complex and/or seperate properties are used to
determine membership than asking the object canYouHandle might be more
appropriate, and you should make canYouHandle virtual so if it for
example you find that 3[0-9]* is actually 3([0-9]|[A-Z])* you can
simply replace this method instead of creating a new implementation.

- Kurt

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT -4. The time now is 10:15 AM.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.1.0
Copyright 2004 - 2007 Exforsys Inc. All rights reserved.