I
ishijak
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
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