abstract initialize() method instead of dependency injection, good practice? - java

This is a simplified example of something I'm currently designing.
public class ExampleManager {
private Foo foo;
private ArrayList<Example> examples;
...
public ExampleManager() {
this.foo = new Foo();
this.examples = new ArrayList<Example>();
}
public void add(Example e) {
examples.add(e);
}
public void doSomethingWithExamples() {
for (int i = 0; i < examples.size(); i++) {
examples.get(i).doSomething();
}
}
...
}
public abstract class Example {
private Foo foo;
public Example(Foo foo) {
this.foo = foo;
}
...
}
In order to use the library, I have to extend the Example class and add examples to the ExampleManager, which should be the only class that modifies the Example objects.
So I have this Example1 class:
public class Example1 extends Example {
public Example1(Foo foo) {
super(foo);
}
...
}
and I currently initialize the manager like this:
ExampleManager manager = new ExampleManager();
Example1 example1 = new Example1(manager.getFoo());
manager.add(example1);
My Example needs the Foo object, but I'm wondering if I could get rid of the Foo argument in the Example1 constructor, so if someone uses the library, doesn't have to call manager.getFoo() in order to create an Example.
I'm thinking about the following solution, which will hide the Foo initialization, so the person who makes use of the library just have to implement the initialize(Foo) method, and the Foo would be initialized automatically when adding the example to the ExampleManager)
In ExampleManager: change the add(Example) method for:
public void add(Example e) {
e.initialize(foo);
examples.add(e);
}
In Example, initialize(Foo foo); would be an abstract method, so in Example1 I would have something like this:
#Override
public void initialize(Foo foo) {
this.foo = foo;
}
Is there any better way to do this?

It seems to me that you have some issues with your OO model in the first place if you need to hand objects around like you describe. - Or maybe your sample code does not reveal the real point of things.
Especially
ExampleManager [...] should be the only class that modifies the Foo objects
and
Example needs the Foo object
look somewhat 'special'.
Can you elaborate what the interactions are between the ExampleManager and the Foo instance, and between the Example and the Foo instance?
Ok, with regard to your comment, I propose the observer pattern, much like your initialize() approach:
public abstract class Example {
protected Foo callbackHandler;
public void setCallbackHandler( Foo handler ) {
this.callbackHandler = handler;
}
protected void doCallback( SomeType event ) {
if ( this.callbackHandler != null ) {
this.callbackHandler.doYourThing( event );
}
}
}
and have ExampleManager register itself or its Foo instance as the callback handler when an object is added to it. Non-abstract subclasses will then only need to call doCallback(...) whenever they want to communicate something and won't have to deal with any setup stuff for the callback.

Related

ClassName.this in extended classes

I've inherited some code, and I'm trying to refactor it in an attempt to clean it up.
This is a simplified case of how I received the code:
public class Foo
{
private void doSomething()
{
someOtherAction(Foo.this);
}
protected class FooChildClass
{
protected void anotherAction()
{
createDialogBox(Foo.this);
}
}
}
//totally not related to class Foo even though most code is duplicated
public class Bar
{
private void doSomething()
{
someOtherAction(Bar.this);
}
protected class BarChildClass
{
protected void anotherAction()
{
createDialogBox(Bar.this);
}
}
}
Now, here's the catch - after further examination of the code, Bar is almost a carbon-copy of Foo with some slight changes here and there.
I'd like to condense my code into something like this:
//superclass
public class Foo
{
protected void doSomething()
{
someOtherAction(Foo.this);
}
protected class ChildClass
{
protected void anotherAction()
{
createDialogBox(Foo.this);
}
}
}
//inherits from Foo and only overrides when necessary
public class Bar extends Foo
{
//rely on base implementation of doSomething
//override other functions only when necessary
}
Will my condensed code run successfully? I have a C# background, so I understand a good bit of Java syntax, but C# doesn't have anything similar to ClassName.this.
I'm figuring that ClassName.this is meant to resolve scoping issues by defining what 'this' is intended - and that with my modified code, Bar is indeed a Foo object too - but I figure I would ask to be sure!
Edited original question for clarification
Foo.this is equivalent to this. Therefore your condensed code is Okay with no requirement of being changed.
The following test code is to test your updated program:
Foo f = new Foo();
Foo.ChildClass fc = f.new ChildClass();
f.doSomething();
fc.anotherAction();
Bar b = new Bar();
Bar.ChildClass bc = b.new ChildClass();
b.doSomething();
bc.anotherAction();
The output is:
Foo#52e922
Foo#52e922
Bar#25154f
Bar#25154f
Referring to your most recent edit I composed the following example:
public class Foo {
public void printMe() {
System.out.println("I'm foo");
}
public class Child {
public void printMe() {
Foo.this.printMe();
}
}
}
public class Bar extends Foo {
#Override
public void printMe() {
System.out.println("I'm bar");
}
}
public class Main {
public static void main(String[] args) {
new Bar().new Child().printMe();
}
}
The result was:
I'm bar
Which concludes, that Foo.this.printMe() does not statically refer to the outer class Foo, but to the outer instance of the Child instance, which in this case is an instance of Bar.
For further reading:
The Classname.this syntax is used for inner classes.
You can use the following example to try a bit around and see its effects:
public class Foo {
private int value = 1;
public class Bar {
private int value = 2;
public void printValue() {
System.out.println(Foo.this.value);
}
}
}
Regarding derivation, there's no way to explicitly refer to a certain super type in java, like in C. However, you can refer to your super class using the super keyword.
With java 1.8 and default interface methods, the Classname.super syntax was introduced:
public interface Foo {
default int getValue() {
return 1;
}
}
public interface Bar {
default int getValue() {
return 2;
}
}
public class Impl implements Foo, Bar {
#Override
public int getValue() {
return Bar.super.getValue();
}
}
However, you can still only refer to direct super types. Everything other will be denied by the compiler.

How to move an anonymous Provider that references fields in the module into a separate class?

Toy example:
public class MyModule extends AbstractModule {
private static final Foo foo;
public MyModule(Foo foo) {
this.foo = foo;
}
#Override
public void configure() {
bind(Bar.class).toProvider(new Provider<Bar>() {
#Override public Bar get() {
return foo.getBar();
}
});
}
}
This lets me lazily invoke the .getBar() method of a user-provided Foo instance stored in a field of MyModule. However now the provider has its own dependencies - hence I need to define a non-anonymous class I specify an #Inject constructor on. Something like:
public class MyModule extends AbstractModule {
private static final Foo foo;
public MyModule(Foo foo) {
this.foo = foo;
}
#Override
public void configure() {
bind(Bar.class).toProvider(BarProvider.class);
}
BarProvider implements Provider<Bar> {
private Baz baz;
#Inject BarProvider(Baz baz) {
this.baz = baz;
}
#Override public Bar get() {
return foo.getBar(baz);
}
}
}
Perfect! Except Guice doesn't like this...
Exception in thread "main" com.google.inject.CreationException: Unable to create injector, see the following errors:
1) Injecting into inner classes is not supported. Please use a 'static' class (top-level or nested) instead of com.example.MyModule$BarProvider.
So, I'm in a bind. I need to access both a field on the module and an injected type from a Provider class at the same time. Is there any way to do this?
Note: this toy example excludes some of the actual complexity - in particular the bind() statement is more involved, which is why I can't simply define an #Provides method.
In part, injecting into an inner class is impossible because Guice can't reflectively create an inner instance without an outer parent instance (the equivalent of the arcane outerInstance.new InnerInstance() syntax).
Some options:
Make Foo injectable through your graph, possibly hidden in a PrivateModule so it's not exposed to your entire graph (if that's important to you).
Use an anonymous inner Provider (or an extracted equivalent), and get a Provider<Baz> from AbstractModule's getProvider(Class<T>) method. You'll get an exception if you try to call that before the Injector is created, but for creating a Provider the way you're doing, that's probably not a problem.
Post your bind outside of a toy problem, to see whether #Provides is possible with some cleverness.
Related: Accessing Guice injector in its Module?
I realize I was getting hung up on having Guice construct my Provider for me, which I don't actually need to do. Despite the example in Guice's documentation passing in a DatabaseTransactionLogProvider.class a better parallel to the first snippet would be to construct an instance of my Provider manually, and pass in both the Foo instance and a Provider<Baz> instance (provided by the module).
public class MyModule extends AbstractModule {
private static final Foo foo;
public MyModule(Foo foo) {
this.foo = foo;
}
#Override
public void configure() {
bind(Bar.class).toProvider(new BarProvider(foo, getProvider(Baz.class));
}
static BarProvider implements Provider<Bar> {
private final Foo foo;
private final Provider<Baz> bazProvider;
BarProvider(Foo foo, Provider<Baz> bazProvider) {
this.foo = foo;
this.bazProvider = bazProvider;
}
#Override public Bar get() {
return foo.getBar(bazProvider.get());
}
}
}

Can a custom class know the name of the object that called it?

Is there anyway, when calling a method through an object (instance) for that method to know which instance (object) called it?
Here's an example (pseudo code) of what I mean:
Pseudo code example
public class CustomClass{
public void myMethod(){
if (calling method is object1){
//Do something here
}
else {
//Do something else
}
}//End of method
}//End of class
And then in another class:
public SomeOtherClass{
CustomClass = object1;
public void someOtherMethod(){
object1 = new CustomClass();
object1.myMethod(); //This will call the 1st condition as the calling object is object1, if it were some other object name, it would call the 2nd condition.
}//End of method
}//End of class
Possible work-around
The only way I've found to do this is to get the method to take another argument, say an 'int' and then check the value of that int and perform whichever part of the 'if else' statement relates to it (or 'switch' statement if definitely using an 'int' value) but that just seems a really messy way of doing it.
What you need is the Strategy Pattern
public abstract class CustomClass {
public abstract void MyMethod();
}
public class Impl1 extends CustomClass {
#Override
public void MyMethod() {
// Do something
}
}
public class Impl2 extends CustomClass {
#Override
public void MyMethod() {
// Do something else
}
}
Use it this way
public static void main(String[] args) {
CustomClass myObject = new Impl1();
// or CustomClass myObject = new Impl2();
}
As your comment says what you really need is perhaps the Template method Pattern
public abstract class CustomClass {
public void myMethod(){ // this is the template method
// The common things
theDifferentThings();
}
public abstract void theDifferentThings();
}
public class Impl1 extends CustomClass {
#Override
public void theDifferentThings() {
// Do something
}
}
public class Impl2 extends CustomClass {
#Override
public void theDifferentThings() {
// Do something else
}
}
You can know the name of current class by calling getClass().getName(). However you cannot know the name of object, moreover this does not have any meaning:
MyClass myObject1 = new MyClass();
MyClass myObject2 = myObject1;
myObject1.foo();
myObject2.foo();
Do you wutant foo() to know that it was invoked using myObject1 or myObject1? But both references refer to the same object!
OK, there are extremely complicated ways to know this. You can use byte code engineering using one of popular libraries like javassist, ASM, CGLib and inject missing information about the "object name" into byte code and then read this information. But IMHO this is not what you need.
You can define a new attribute inside CustomClass which will store the identifier of the instance. If there will be only a few instances of CustomClass then you can use an enum type.
Replace:
object1 = new CustomClass();
with:
object1 = new CustomClass(1);
Add a new constructor and an attribute to CustomClass:
private int id;
public CustomClass(int id) {
this.id = id;
}
Then you can replace:
if (calling method is object1){
with:
if (id == 1){
However, please keep in mind that this is a bad design.
You should not have if conditions differing logic depending on the instance which called this method. You should should use polymorphism for such purpose.

Pass parameter to constructor with Guice

I have a factory as below,
public final class Application {
private static IFoo foo;
public static IFoo getFoo(String bar)
{
// i need to inject bar to the constructor of Foo
// obvious i have to do something, not sure what
Injector injector = Guice.createInjector();
logger = injector.getInstance(Foo.class);
return logger;
}
}
This is the Foo definition:
class Foo
{
Foo(String bar)
{
}
}
OK. I m not sure how I can pass this parameter to Foo constructor with Guice?
Any ideas?
All the "Guice Constructor Parameter" answers seem to be incomplete in some way.
Here is a complete solution, including usage and a visual:
interface FooInterface {
String getFooName();
}
// Annotate the constructor and assisted parameters on the implementation class
class Foo implements FooInterface {
String bar;
#Inject
Foo(#Assisted String bar) {
this.bar = bar;
}
// return the final name
public String getFooName() {
return this.bar;
}
}
// Create a factory interface with a create() method that takes only the assisted parameters.
// FooFactory interface doesn't have an explicit implementation class (Guice Magic)
interface FooFactory {
Foo create(String bar);
}
// Bind that factory to a provider created by AssistedInject
class BinderModule implements Module {
public void configure(Binder binder) {
binder.install(new FactoryModuleBuilder()
.implement(FooInterface.class, Foo.class)
.build(FooFactory.class));
}
}
// Now use it:
class FooAction {
#Inject private FooFactory fooFactory;
public String doFoo() {
// Send bar details through the Factory, not the "injector"
Foo f = fooFactory.create("This foo is named bar. How lovely!");
return f.getFooName(); // "This foo is named bar. How lovely!"
}
}
Lots of helps here: https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/assistedinject/FactoryModuleBuilder.html
What you are probably looking for is to use a Guice factory. Particularly easy with the AssistedInject functionality, but they have a manual example at the top of the page. The short of it for the manual example is that you get the factory under non-static getFoo method that you pass whatever parameters to that you need and build the object from there.
This won't work directly if you have method interception in Foo, but it will work in many other cases.
To use AssistedInject, which to me has somewhat cleaner semantics and means less manual wiring, you'll need the guice-assistedinject extension in the classpath, then when creating Foo (well, FooImpl, we should be using interfaces):
#Inject
public FooImpl(#Assisted String bar)
{
this.baz = bar;
}
Then you create a FooFactory interface:
public interface FooFactory {
public Foo create(String bar);
}
Then in your guice module:
install(new FactoryModuleBuilder()
.implement(Foo.class, FooImpl.class)
.build(FooFactory.class));
You can check out the javadoc for FactoryModuleBuilder for examples with more complex factories.
I know that this is old thread but I just hit the issue myself today.
I only need two or maximum three different instances of 'Foo' and I really didn't want to write all the bolierplate code of Factory.
With a little googling I found this Stubbisms – Tony’s Weblog I would suggest this solution which is perfect if you know exactly what instances you need.
In Guice module:
bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(new Provider<Foo>() {
#Override
public Foo get() {
return new FooImpl("topic A");
}
});
bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(new Provider<Foo>() {
#Override
public Foo get() {
return new FooImpl("topic B");
}
});
Or in java 8:
bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(() -> new FooImpl("first"));
bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(() -> new FooImpl("second"));
And in constructor of your service where you need Foo instances:
#Inject
public MyService (
#Named("firstFoo") Foo firstFoo,
#Named("secondFoo") Foo secondFoo) {
}
And Foo in my case:
public class FooImpl implements Foo {
private String name;
public FooImpl(String name) {
this.name = name;
}
#Override
public String getName() {
return name;
}
}
Hope it helps someone.
If this class is a factory, it should be a Guice-managed object, having a non static getFoo method, and the getFoo method would just use
new Foo(bar)
Not every class needs to be instantiated by Guice.
Also see AssistedInject, to avoid creating this factory yourself and let Guice create one for you.
Although this isn't a direct answer to what you're asking, hope it helps. I was trying to understand where the constructor parameters are being passed earlier. If they are custom classes, they should be bind-ed in the module.
Class CustomHandler {
private Config config;
#Inject
CustomHandler(Config config) {
this.config = config;
}
public void handle() {
// handle using config here
}
}
Binding:
class Module extends AbstractModule {
bind(Handler.class).to(CustomHandler.class);
bind(Config.class).to(CustomConfig.class);
}
Injection:
CustomHandler handler = injector.getInstance(CustomHandler.class);
handler.handle();

passing object of class to another class

I have two classes. Class A and Class B.
I have a function in Class A that i would like to use in class B. I was thinking about passing a reference of Class A to the constructor of Class B and then call the function after that.
Would that work? Can someone show me an example?
Thanks in advance!
Yes, it will work. And it's a decent way to do it. You just pass an instance of class A:
public class Foo {
public void doFoo() {..} // that's the method you want to use
}
public class Bar {
private Foo foo;
public Bar(Foo foo) {
this.foo = foo;
}
public void doSomething() {
foo.doFoo(); // here you are using it.
}
}
And then you can have:
Foo foo = new Foo();
Bar bar = new Bar(foo);
bar.doSomething();
Do something like this
class ClassA {
public ClassA() { // Constructor
ClassB b = new ClassB(this);
}
class ClassB {
public ClassB(ClassA a) {...}
}
The this keyword essentially refers to the object(class) it's in.

Categories

Resources