I have got an interface that defines some service methods for data retrieval:
public interface DataReceiver {
public Data getData();
}
Then i have a class that implements this interface and loads the data through a connection. I supply this connection using constructor injection:
public class ConnectionDataReceiver implements DataReceiver {
private Connection connection;
public ConnectionDataReceiver(Connection connection) {
this.connection = connection;
}
public Data getData() {
return connection.query("blabla");
}
}
This works pretty nicely. I can instantiate my ConnectionDataReceiver objects using the constructor, or i could add a factory method/class that extends the usability by providing an option to select a config file for connection setup. I then use my new class through my interface, so i can easily swap out the implementation (like loading the data from a file instead of a connection).
But what if i want to change my connection during runtime, without instantiating a new ConnectionDataReceiver? I would have to add getters and setters for my class. But since they are not part of my public service definition, i can't put them in my interface. I could use the implementation object in my code to set a new connection, but it feels pretty awkward hanging onto a reference to the original object only for maybe changing the connection object:
ConnectionDataReceiver conDataRec = new ConnectionDataReceiver(myConnection);
DataReceiver dataRec = conDataRec;
// use dataRec
conDataRec.setConnection(myNewConnection);
// use dataRec again
In this example it would be the easiest way to just instantiate a new ConnectionDataReceiver and just reassign dataRec, but what if the instantiation of my object is really expensive? How do i give my implementation classes additional functionality while still being able to use my old service interface? Or is it generally frowned upon changing data at runtime, when the interface doesn't define that functionality?
What you can do is that adding following two simple methods in your interface:
public void setProperty(String name, Object value);
public Object getProperty(String name);
Now with the help of these two simple methods, you may configure as many additional functionalities as you want in your implementation classes without adding a new method for a new feature (of your implementation class) in your super type.
This pattern is used in following interface:
com.ibm.msg.client.jms.JmsQueueConnectionFactory
The interface has setCharProperty, setDoubleProperty, setFloatProperty etc so that when they release a new implementation they do not have to modify the interface.
My version:
Interface
public interface DataReceiver
{
public Data getData();
}
Implementation
public class ConnectionDataReceiver implements DataReceiver
{
private Connection connection;
public ConnectionDataReceiver(Connection connection)
{
this.connection = connection;
}
public Data getData()
{
return connection.query("blabla");
}
}
Interface using in business layer, here method setReceiver will assign new implementation of interface in run-time.
public class SomeBusinessLogic
{
private DataReceiver receiver;
public SomeBusinessLogic(DataReceiver receiver)
{
this.receiver = receiver;
}
public void setReceiver(DataReceiver receiver)
{
this.receiver = receiver;
}
}
With this approach you can change implementation of DataReceiver in run-time
Related
I have a BasePersister that builds a complex persistence client in it's constructor, using Dagger:
public abstract class BasePersister {
#Getter
private PersistenceClient client;
public BasePersister() {
this.client = DaggerPersistenceClientComponent.create().getClient();
}
public abstract void persist(String data);
protected void helper() {
System.out.println("I am a helper");
}
}
The idea is that child persister classes can just extend the base class and perform its persistence logic with the client. An example child class:
public class SpecialPersister extends BasePersister {
public void persist(String data) {
// do stuff with the client
getClient().persist(data);
// use the shared helper
helper();
}
}
Moving the client instantiation within the base class constructor was ideal because in my PersisterFactory, I can simply invoke statements like new SpecialPersister(); the constructor doesn't take any arguments, doesn't need Dagger to instantiate and the factory is completely unaware of any clients.
I'm having trouble testing these child classes and I'm suspecting it has to do with my design choice of secretly instantiating clients within the base constructors.
More specifically, in my SpecialPersisterTest class, I can't do Spy(SpecialPersister) as this invokes the base constructor, which then instantiates my complex clients (giving me an error). I somehow need to mock this super-constructor call so that it doesn't actually invoke client instantiation, which has complex network calls etc.
Ideally, I can do a simple test such as checking:
def "my ideal test"() {
given:
specialPersister.persist(validData)
then:
1 * specialPersister.getClient()
and:
1 * specialPersister.helper()
}
Moving the client instantiation within the base class constructor was ideal because in my PersisterFactory, I can simply invoke statements like new SpecialPersister(); the constructor doesn't take any arguments, doesn't need Dagger to instantiate and the factory is completely unaware of any clients.
I'm having trouble testing these child classes and I'm suspecting it has to do with my design choice of secretly instantiating clients within the base constructors.
This design choice is the issue. If you want the code to be testable without making calls on the real client, you will need to be able to stub your client. One option for this is to pass the PersistenceClient in at instantiation.
Since you are using a factory pattern, your factory can provide it without worrying about the details elsewhere in your code. It should know how to create Persister objects, regardless of if it needs to know the details about the client - coupling at this level should be encouraged. You may also want your factory to take the argument, as well, so that a Persister from the factory can be tested.
public abstract class BasePersister {
private PersistenceClient client;
public BasePersister(PersistenceClient client) {
this.client = client;
}
}
public class SpecialPersister extends BasePersister {
public SpecialPersister(PersistenceClient client) {
super(client);
}
}
public class PersisterFactory {
// pass in the client once to a PersisterFactory instance
private PersistenceClient client;
public PersisterFactory(PersistenceClient client) {
this.client = client;
}
public SpecialPersister createSpecialPersister() {
return new SpecialPersister(client);
}
}
// elsewhere
PersisterFactory persisterFactory = new PersisterFactory(DaggerPersistenceClientComponent.create().getClient());
// ...
BasePersister persister = persisterFactory.createSpecialPersister();
I have an application class "Application", one abstract class "AbstractClass" extended by "Impl1" and "Impl2".
The application class gets the impl1 or impl2 to perform some task based on the input it receives.
Currently I am injecting both the classes into the application class as shown below.
Then based on input, I either ask impl1 OR impl2 to perform the task.
public class Application {
private static final Data data1 = DATA_CONFIG.data_1;
private final AbstractClass impl1;
private final AbstractClass impl2;
#Inject
Application(final AbstractClass impl1, final AbstractClass impl2){
this.impl1 = impl1;
this.impl2 = impl2;
}
public void mainTask(final Data data){
if(data == data1){
impl1.performTask();
}else{
impl2.performTask();
}
}
}
But, is there any way I could use assisted inject or a similar concept to inject only the dependency required, so for example input is data1, I only inject impl1 and not impl2.??
So, what you want is to select injected object depending to some context of injection point - value of Data object in particular. I didn't do such things and can't guarantee success, but you can try custom injections.
Also you can do something like factory. But IMHO, this approach is not much better than original, cause it will just move selection between impl1 and impl2 to a factory class you have to create first.
Sketch:
#Inject
Application(IAbstractClassFactory factory){
this.factory = factory
}
void mainTask(final Data data){
impl = factory.create(data)
}
I'm learning about the design patterns and I encountered a problem which I cant resolve. I'm writing a client/server script. The administrator client send a task with its task data in json format, and the server should instantiate an object accordingly to the recieved task type, and fill its constructor with correct classes. As you can see bellow there are two example class.
public class StartProcessing implements ITask{
private final IProcessor dataProcessor;
public StartProcessing(IProcessor dataProcessor){
this.dataProcessor = dataProcessor;
}
#Override
public void ProcessTask() {
this.dataProcessor.StartProcess();
}
}
public class StartQueueFiller implements ITask{
private IQueueFiller queueFiller;
public StartQueueFiller(IQueueFiller queueFiller){
this.queueFiller = queueFiller;
}
#Override
public void ProcessTask() {
this.queueFiller.Start();
}
}
interface ITask {
public void ProcessTask();
}
I've tried something like this, but I'll have like 50 different process and hundreds of tasks, so the constructor will be unmanageable, and I think the factory pattern is not so good in this case, and probably I just miss the point of the pattern. So how you would solve this problem? What should I use instead of the factory pattern?
public class TaskFactory(){
private final IProcessor processor;
private final IQueueFiller queuefiller;
public TaskFactory(IProcessor processor, IQueueFiller queuefiller){
this.processor = processor;
this.queuefiller = queuefiller;
}
public ITask Create(String task){
switch(task){
case "startprocessor":
return new StartProcessing(this.processor);
case "startqueuefiller":
return new StartQueueFiller(this.queuefiller);
}
}
}
I would just use the Abstract Factory pattern:
public interface TaskFactory {
Task create();
}
Then we can store a bunch of factories in a data structure of some kind, e.g.:
private final Map<String, TaskFactory> factoriesMap = new HashMap<>();
void registerFactory(String identifier, TaskFactory factory) {
factoriesMap.put(identifier, factory);
}
public Task create(String identifier) {
return factoriesMap.get(identifier).create();
}
Then we can register different kinds of factories using a lambda or something:
Processor processor = ...;
registerFactory("startprocessor", () -> new StartProcessingTask(processor));
etc.
At some point you're going to realize that your "factory map" is basically a kind of Service Locator, in which case you either need to double-down on that, or find an alternative solution. I tend to prefer Dependency Injection as an approach here. Depending on your DI environment, you might make all your TaskFactory instances injectable using qualifiers. You can either bind lazy providers of actual task objects, or bind a factory-like object (e.g. "assisted inject").
I have the following scenario:
public interface ServiceClientAdapter {
SomeData getSomeData()
}
#LegacyServiceClientAdapter
public class MyLegacyServiceClientAdapterImpl implements ServiceClientAdapter {
public SomeData getSomeData() {
// implementation
}
}
#NewServiceClientAdapter
public class MyNewServiceClientAdapterImpl implements ServiceClientAdapter {
public SomeData getSomeData() {
// implementation
}
}
public class BusinessLogic {
#Inject
private ServiceClientAdapter serviceClientAdapter;
}
LegacyServiceClientAdapter and NewServiceClientAdapter are custom annotations.
The implementation for the serviceClientAdapter field will be determined at runtime by whether the user has been migrated from the legacy to the new service or not.
What is the best way to accomplish this dependency injection using Google Guice?
Take into account that different BusinessLogic classes will exist, each with their own (different) ServiceClientAdapter-like interface and corresponding legacy and new implementation classes.
Ideally this should be done with a piece of framework code that can be used across all use cases.
I'm going to assume that the result of your LDAP call can be represented as a string, let's say "legacy" or "new". If not, hopefully you should still be able to adapt this example.
In your module, use a MapBinder:
public class BusinessLogicModule {
#Override
protected void configure() {
// create empty map binder
MapBinder<String, ServiceClientAdapter> mapBinder =
MapBinder.newMapBinder(
binder(), String.class, ServiceClientAdapter.class);
// bind different impls, keyed by descriptive strings
mapBinder.addBinding("legacy")
.to(MyLegacyServiceClientAdapterImpl.class);
mapBinder.addBinding("new")
.to(MyNewServiceClientAdapterImpl.class);
}
}
Now you can inject a map of instances (or a map of providers of instances if you need to keep creating new instances) into your main class and use the string discovered at runtime to control which kind of instance you get.
public class BusinessLogic {
#Inject
private ServiceClientAdapter serviceClientAdapter;
#Inject
private Map<String, ServiceClientAdapter> mapBinder;
public void setupAndUseClientAdapter() {
String userType = getUserTypeFromLdapServer();
serviceClientAdapter = mapBinder.get(userType);
if (serviceClientAdapter == null) {
throw new IllegalArgumentException(
"No service client adapter available for " +
userType + " user type.";
}
doStuffWithServiceClientAdapter();
}
}
While working on an web-application , I need to get a set of classes at few steps and I am thinking to separate this logic to a simple Factory so as based on the Class type We can create class instance as well init it with default values.
Current structure of Class hierarchy is
public interface DataPopulator<Source,Target>{
// some method decaration
}
Abstract class
public abstract class AbstractDataPopulator<Source,Target> implements DataPopulator<Source, Target>{
// some common implimentation
}
And now classes which will be used as actual implementations like
Type1Populator extends AbstractDataPopulator.
Type2Populator extends AbstractDataPopulator.
Each of these implementation needs a set of common dependencies based on what functionality is being executed by those Populators.
As of Now I am creating instance with new and than filling those dependencies with simple setter methods.
I am thinking about creating a simple factory pattern like
public interface PopulatorFactory{
<T extends Object> T create(String className) throws Exception;
<T extends Object> T create(Class populatorClass) throws Exception;
}
Abstract class
public abstract class DefaultPopulatorFactory impliments PopulatorFactory{
public <T> T create(final Class populatorClass) throws Exception{
return Class.forName(populatorClass);
}
// other method.
}
Implementation classes
public Type1PopulatorFactory extends DefaultPopulatorFactory {
public <T> T create(final Class populatorClass) throws Exception{
final T populator= super.create(populatorClass);
}
}
I also want to initialize newly created instances with some default values specific to each implementation, but I'm not sure what's the best way to do this?
Should I define another method say initDefaults?
What is the best way to pass those dependencies to these poulators.
Is the approach outlined by me fine or is it overly complicated?
In cases when you are building not-so-trivial objects it is usually better to use the Builder pattern instead of a Factory.
In your case if you don't need external data sources you can simply write constructors for your classes where you can supply the default values and get rid of the contraption in your question.
If you use the Builder pattern you can simplify your framework by using a Builder object for the common data and a SomeOtherBuilder which extends from Builder and adds the custom values of the specialized implementation. You can make your classes constructors which are taking a Builder object.
public class Builder {
// your fields go here
}
public class SomeOtherBuilder extends Builder {
// your specialized fields go here
}
public class YourClass {
public YourClass(Builder builder) {
// construct it here
}
}
You can also make your classes generic with using something like T extends Builder.