How to initialize my singleton object - java

public class FooClient {
private Foo foo;
private final static String key = "<api-key>";
private static FooClient client = new FooClient();
private FooClient() {
foo = new Foo(key);
}
public static FooClient getFooClient() {
return client;
}
}
Is it ok to initialize client in the above fashion.
Should I declare private Foo foo; as static, I am guessing its not the case.
If I have to support different singletons for different keys, should I modify getFooClient(String key) to take in a key and cache it, so that I can return singleton FooClients which are key specific.

Yes. In the constructor you can check if client != null and if it is - throw an error. (this will counter reflection instantiations)
No, it is an instance field of the singleton
Yes. And you should have a Map<String, Foo>. But note that that is not "different singletons" - your singleton is the "client". The other classes can be instantiated multiple times.

Usually you declare
private static final FooClient client = new FooClient();
This is the traditional Singleton implementation. See wikipedia page for other implementation options.
I would not declare Foo foo as static.
If your singleton can return different instances based on the key, then it's a good idea to pass the key value in the getFooClient() method.

If you have more than one of something, its not a singleton.
I would use enum in both cases.
For the case where this is just one.
enum FooClient {
INSTANCE;
private final Foo foo = new Foo("<api-key>");
}
for the case where there is more than one.
enum FooClient {
INSTANCE1("<api-key>"), INSTANCE2("<api-key2>");
private final Foo foo;
FooClient(String apiKey) {
foo = new Foo(apiKey);
}
}

Related

Instance controlling using enum

I have a factory class, which I have made singleton using enum. I want to make sure that the object being created is also singleton (Please note that I do not own the class being created, but I want to ensure that it's object is singleton).
I am trying something like this
public enum MyFactoryImpl implements MyFactory {
INSTANCE;
private final MyObject myObject = buildMyObject(); //I want to instance control this
private MyObject buildMyObject() {
return new MyObject();
}
public MyObject myFactoryMethod() {
return this.myObject;
}
}
I tried calling the factoryMethod in a test case in parallel fashion using testNG, and multiple invocation seem to return the same hashCode.
#Test(threadPoolSize = 10, invocationCount = 600, timeOut = 100000)
public void test_instanceControlledBehavior() {
final MyFactory f1 = MyFactoryImpl.INSTANCE;
final MyFactory f2 = MyFactoryImpl.INSTANCE;
Assert.assertEquals(f1.myFactoryMethod().hashCode(), f2.myFactoryMethod().hashCode());
}
Is this the correct way of implementing the behavior? Is there a better way I can instance control 'MyObject'?

Java child class that can be refreshed with new instances of the parent class

I'm working with the Java AWS API to monitor some EC2 instances and on every refresh I need to query the service which returns a bunch of Instance objects (freshly constructed). I want to extend the functionality of these objects, I figure I can maintain a map of MyInstance objects which can be refreshed with the new Instances on each poll.
Now I could easily do this with a simple wrapper class that holds the original Instance as a property the issue is I would like to keep access to the base Instance API as I already use these functions in my code. Would it be possible to replace only the super-class parts of an instantiated object? Contrived example of what I'm going for:
class Instance {
protected int prop;
public Instance(int prop) {
this.prop = prop;
}
}
class MyInstance extends Instance {
protected int prop2;
public MyInstance(int prop, int prop2) {
super(prop);
this.prop2 = prop2;
}
}
MyInstance foo = new MyInstance(1, 2);
Instance foster = new Instance(3);
//what i want to do
foo.adoptedBy(foster);
//with the result that foo.prop == 3
Obviously this example would be trivial to transform but in my actual case there are far more properties that need to be transferred. Can Reflection do this? What kind of performance impact am I looking at if I use Reflection for 10 of these every second? Thanks for reading!
The best solution is to combine both your ideas:
Wrap the original Instance in a class that extends the Instance class. (In the constructor of the child class, you can create a new Instance object and set it)
Delegate all methods to the wrapped instance (and add new properties)
In your foster method, you simply change the wrapped Instance.
class Instance {
private int prop;
public Instance(int prop) {
this.prop = prop;
}
public int getProp() {
return prop;
}
}
class MyInstance extends Instance {
private Instance delegate;
private int prop2;
public MyInstance(Instance delegate, int prop2) {
super(prop);
this.delegate = delegate;
this.prop2 = prop2;
}
#Override
public int getProp() {
return delegate.getProp();
}
public int getProp2() {
return prop2;
}
public void foster(Instance i) {
delegate = i;
}
}
MyInstance foo = new MyInstance(1, 2);
Instance foster = new Instance(3);
//what i want to do
foo.adoptedBy(foster);
//with the result that foo.getProp() == 3

Test a factory of a 3rd party class

My application uses a third party jar (no access to source, etc.) I have a factory that creates an object (call it Foo) correctly from settings, i.e.
public FooFactoryImpl implements FooFactory {
private final Settings settings;
private final OtherDependency other;
#Inject
public FooFactoryImpl(Settings settings, OtherDependency other) {
this.settings = settings;
this.other = other;
}
public Foo create(String theirArg) {
Foo newFoo = new Foo(theirArg); // there is no no-arg constructor
// This isn't exactly the way I do it but this is shorter and close enough
newFoo.setParamOne(settings.get("ParamOne"));
newFoo.setParamTwo(settings.get("ParamTwo"));
// etc.
}
}
I would like to unit test this factory using Mockito - make sure the created object is configured correctly. But of course, I run into this problem; that is, because my factory calls new, I can't inject a spy.
One possible solution is to introduce something like:
public FooFactoryDumb implements FooFactory {
public Foo create(String theirArg) {
return new Foo(theirArg);
}
}
And then something like:
public FooFactoryImpl implements FooFactory {
#Inject #Dumb private FooFactory inner;
// snip, see above
public create(String theirArg) {
Foo newFoo = inner.create(theirArg);
// etc.
}
}
This seems like a lot of boilerplate code just to enable unit testing. It smells bad to me, but I might be wrong. Is there a better way?
There is a similar but simpler way to do it: add a protected method to your factory to create a Foo:
protected Foo create(String theirArg){
return new Foo(theirArg);
}
then in your tests of your Factory, create a Test Double of your FactoryImpl and override the create method:
private class FooFactoryImplTestDouble extends FooFactoryImpl{
...
#Override
protected Foo create(String theirArg){
//create and return your spy here
}
}
Create a new class:
public class FooFactory3rd {
public Foo create3rdParty(String theirArg) {
return new Foo(theirArg);
}
}
Then change your class to:
public FooFactoryImpl implements FooFactory {
private final Settings settings;
private final OtherDependency other;
private final FooFactory3rd fooFactory3rd;
#Inject
public FooFactoryImpl(Settings settings, OtherDependency other, FooFactory3rd fooFactory3rd) {
this.settings = settings;
this.other = other;
this.fooFactory3rd = fooFactory3rd;
}
public Foo create(String theirArg) {
Foo newFoo = fooFactory3rd.create3rdParty(theirArg);
// This isn't exactly the way I do it but this is shorter and close enough
newFoo.setParamOne(settings.get("ParamOne"));
newFoo.setParamTwo(settings.get("ParamTwo"));
// etc.
}
}
And in your test code:
Foo fooMock = mock(Foo.class);
FooFactory3rd fooFactory3rdMock = mock(FooFactory3rd.class);
when(fooFactory3rdMock.create3rdParty(any(String.class)).thenReturn(fooMock);
FooFactoryImpl fooFactoryImpl = new FooFactoryImpl(settings, other, fooFactory3rdMock);
fooFactoryImpl.create("any string");
This way, you can inject your fooMock. When you call fooFactoryImpl.create("any string"), your mocked Foo is called under the cover.
Or if you want to go further clean, don't even need the constructor arg of FooFactory3rd. Just declare
private final FooFactory3rd fooFactory3rd = new FooFactory3rd();
And in your test, use reflection to change it to the mocked FooFactory3rd.
Well, it turns out that I had to use PowerMock anyway because the third party's methods were final. Since I'm already using PowerMock, I realized I can just do this:
#Before
public void setUp() throws Exception {
Foo toReturn = PowerMockito.mock(Foo.class);
PowerMockito.whenNew(Foo.class).withAnyArguments().thenReturn(toReturn);
}
And then I don't have to touch my original class at all.
Note: If you do this, you have to prepare both classes for PowerMock, i.e. do
#PrepareForTest( { Foo.class, FooFactoryImpl.class } )
Take a step back and think about what the contract of FooFactoryImpl is. It is that it must create a fully functional Foo, whatever that means. So if the contract of a Foo is that it does X, Y and Z, then the contract of a FooFactoryImpl is that it creates objects that do X, Y and Z.
This is a case for the kind of test in which the SUT consists of more than one class. I don't care whether you call this a unit test, an integration test, a subsystem test, a collaboration test, or some other name. The point is that the only meaningful test of FooFactoryImpl is a test that tests Foo as well. Instead of writing a test class for Foo alone, write a test class that tests the two classes jointly.
So, if the contract of Foo is to do X, Y and Z, then your test cases will do the following things with a FooFactoryImpl.
Call create and test that the created object does X.
Call create and test that the created object does Y.
Call create and test that the created object does Z.
I believe this is the only sensible way to attack this problem. The hard part is coming up with a convincing name for the test class.

Final attribute initialized AFTER the object instantiation

Well, I've a final property but I don't want to initialize it when I create my object because I can't. So I tried to not initialize it in my constructor but using a setter, I guessed it would have been something like a only-one-time usable setter, but I've this error :
Test.java:27: error: cannot assign a value to final variable foo
this.foo = new String(foo);
Here is a short code I used to test this :
class Test {
private final String foo;
public static void main(String[] args) {
Test test = new Test();
test.setFoo("gygygy");
System.out.println(test.getFoo());
}
public Test() {
System.out.println("Constructor");
}
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
So I assume the constructor implicitly makes something like this.foo = new String(); or this.foo = null; and I think I can't modify this behavior, but how can I have an equivalent to what I wanna do ? I think in something like :
private String foo;
/* ... */
public void setFoo(String foo) {
if( !(this.foo.isInitialized()) )
this.foo = foo;
}
but the Object.isInitialized() method obviously doesn't exist, and I can't find an equivalent x)
So here's my question in a few words : How can I do ? I want a final attribute that is not initialized at the instantiation of the object.
Thanks !
You can add a boolean field isInisialized but the best option is to pass the value in the constructor (possibly using a Builder pattern if you need to)
So here's my question in a few words : How can I do ? I want a final attribute that is not initialized at the instantiation of the object.
You simply can't do that. All you can do is have a separate field which you also update to note once you've set the "real" field - and if you try to set it a second time, throw an exception.
Alternatively, make your type immutable, but give it a method which constructs a new instance of the class, with the same data as before except the single new value, e.g.
public Test withFoo(String newFoo) {
// Call a private constructor here, passing in the other fields from
// "this", and newFoo for the value of foo
}
Rule says a final instance member variable should be initialized at the very place where it is declared or within the constructor. By this rule, your requirement cannot be satisfied with your piece of code as is. You can use a builder pattern to achieve it. See this link Builder Pattern in Effective Java

Refactoring classes that use global variables

I'm working on some classes that get part of their configuration from global variables, e.g.
class MyClass {
public void MyClass(Hashtable<String, String> params) {
this.foo = GlobalClass.GLOBALVAR.get("foo");
this.bar = GlobalClass.GLOBALVAR.get("bar");
this.params = params;
}
}
This is bad for a couple of reasons, GLOBALVAR talks to a database to get some of the variables and this makes it really hard to make unit tests. The other problem is that I have many (dozens) of classes that inherit from MyClass, so I can't easily change the constructor signature.
My current solution is to create an additional default constructor and setter methods for params, foo and bar.
class MyClass {
// Other code still here for backwards compatibility.
public void MyClass() {
// Do nothing much.
}
public void setParams(Hashtable<String, String> params) {
this.params = params;
}
public void setFoo(Foo foo) {
this.foo = foo;
}
public void setBar(Bar bar) {
this.bar = bar;
}
}
Any ideas on a good way to refactor this, besides the way I did it? My other thought would be to use a factory method, but I'm afraid I'll run into polymorphic substitution problems.
I think I would start by doing the following. It let's your existing code work without modification, and allows you to add new constructors to the subclasses as you can. Once all of the subclasses have the new constructor, and all of the calls to the old constructors are gone, you can get rid of the GlobalClass and the constructors that use it. You can also then, hopefully, work on cleaning up the GLOBALVAR (the Car class in my code).
import java.util.Hashtable;
class MyClass
{
private final Foo foo;
private final Bar bar;
private final Hashtable<String, String> params;
public MyClass(final Hashtable<String, String> params)
{
this(params, GlobalClass.GLOBALVAR);
}
// added constructor
public MyClass(final Hashtable<String, String> params,
final FooBar fooBar)
{
this.foo = fooBar.getFoo();
this.bar = fooBar.getBar();
this.params = params;
}
}
class MySubClass
extends MyClass
{
public MySubClass(final Hashtable<String, String> params)
{
super(params);
}
// added constructor
public MySubClass(final Hashtable<String, String> params,
final FooBar fooBar)
{
super(params, fooBar);
}
}
// unchanged
class GlobalClass
{
public static Car GLOBALVAR;
}
// added interface
interface FooBar
{
Foo getFoo();
Bar getBar();
}
class Car
// added implements
implements FooBar
{
private Foo foo = new Foo();
private Bar bar = new Bar();
public Object get(final String name)
{
if(name.equals("foo"))
{
return (foo);
}
if(name.equals("bar"))
{
return (bar);
}
throw new Error();
}
// added method
public Foo getFoo()
{
return ((Foo)get("foo"));
}
// added method
public Bar getBar()
{
return ((Bar)get("bar"));
}
}
// unchanged
class Foo
{
}
// unchanged
class Bar
{
}
I think you should introduce an interface to put a layer of abstraction between the global variable collection and its consumers.
interface GlobalVars {
String get(String key);
}
You should introduce a constructor with limited scope, probably package-private
MyClass(GlobalVars globals, Map<String, String> params) {
// create the object
}
And then provide public static factory methods to use this constructor.
public static MyClass newMyClass(Map<String, String> params) {
return new MyClass(GlobalClass.GLOBAL_VAR, params);
}
With this design you can pass in a mock implementation of GlobalVars in a unit test from within the same package by explicitly invoking the constructor.
Addendum: Since params seems to be a required field, I would definitely make it final and avoid the approach where you add mutators to overwrite them.
private final Map<String, String> params;
Also, make a defensive copy to prevent l33t h4x.
this.params = Collections.unmodifiableMap(params);
Your class should take all of its dependencies in the constructor. It's a good idea to make it impossible to create an invalid or uninitialized instance of classes. Make foo and bar private and final, and set them in the constructor.
A slight variation on your approach would be to have an object of type GLOBALVAR in the class and use that instead of the actual global (that refactoring should be a simple search/replace). You can default the new variable to the actual global variable and provide an override for testing.
This GlobalClass.GLOBALVAR should be chopped up up into logical units. That way it would be easier to make mock objects for the unit tests. For example in my CAD/CAM metal cutting application I have a MaterialList, a SheetSizeList, PartNestingParameters, etc.
I don't have a huge list of variables stuff into one giant AppParameter class. They all hang off a ShopStandards object. For Unit Test involving a specific PartNestingParmeters I will just go ShopStandards.PartNestingParmeters = new MockPartNestingParameterTest114(). The test will run not realizing that the Part Nesting Parameters are a mockup. Plus this save me from having to doing dozens of assignments just to get the ShopStandard setup correctly for the test.
We have even more automated where many of the Mock load from files saved during the test run during initial development.
Since you mention that you have the freedom to modify the class hierarchy.
Change the base MyClass ctor to take in 3 parameters params, foo and bar. Comment out the GlobalVar references and simply cache passed in values
Compile.. this should throw up a bunch of compile errors - no ctor which takes 1 parameter.
Fix each one to pass in GlobalVar.get("foo") and GlobalVar.get("bar"). Get it to build.
Refine: Now minimize hits to the DB by lazy load and caching the foo and bar values. Expose via some property on GlobalVar.

Categories

Resources