Read only objects produced by a factory in Java - java

In previous C++ code I've used friend classes when creating a factory that can output "read only" objects which means that as the objects are consumed throughout the code there is no risk that they can be inadvertently changed/corrupted.
Is there is there a similar way to implement this in Java or am I being overly defensive?

Make use of the final keyword. This keyword can mark a class/methods as non-extendable, and mark fields/variables as non-mutable.
You will hide the default constructor of the object using the private constructor, and force parameterised constructors which will initialise all necessary final fields.
Your only problem is that the factory is kind of redundant. Since all fields of the object are final, you will have to use all factory methods at object build-time.
Example:
public final class DataObject
{
protected final String name;
protected final String payload;
private DataObject()
{
}
public DataObject(final String name, final String payload)
{
this.name = name;
this.payload = payload;
}
}
// Using the factory
DataObject factory = new Factory().setName("Name").setPayload("Payload").build();
// As opposed to
DataObject dao = new DataObject("Name", "Payload");
// ==> Factory becomes redundant, only adding extra code
Solution without final:
I'm afraid you will have to forget about the immutability mechanism of C++. The factory pattern is never a bad choice if you have huge data objects (i.e. with a lot of setters), but you can't really avoid mutability of the constructed object. What you could do, is make the data object an inner class of the factory, and make the setters private. That way, ONLY the factory can access the setters. This would be the best approach for you (i.e. simulate immutability).
Example:
public class Factory
{
private String name;
private String payload;
public Factory setName(final String name)
{
this.name = name;
}
public Factory setPayload(final String payload)
{
this.payload = payload;
}
public DataObject build()
{
DataObject newObj = new DataObject();
newObj.setName( this.name );
newObj.setPayload( this.payload );
return newObj;
}
public class DataObject
{
// fields and setters, ALL PRIVATE
}
}

You can either put the object class and factory in the same package, and make the mutable methods package-scoped (this is the default visibility in Java, simply don't declare the methods to be public, private or protected), or make the class truly immutable and do all the work in the constructor. If you find that there are too many arguments in the constructor and it is difficult to understand, consider the Builder Pattern.

There is no direct equal to friend classes in Java. However have a look at http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html.

If your object implements an interface and the factory returns interface type rather than the concrete type (which is better) then you can use java.lang.reflect.Proxy to create dynamic proxy at runtime that intercepts all method calls to the target object. As in the following code example FooFactory class creates a Foo instance (every time its createFoo method is called) but does not directly return instance but instead returns a dynamic proxy that implements the same interface as Foo and dynamic proxy intercepts and delegates all method calls to the Foo instance. This mechanism can be helpful to control access to a class when you dont have class code.
public class FooFactory {
public static IF createFoo() {
//Create Foo instance
Foo target = new Foo(); // Implements interface IF
//Create a dynamic proxy that intercepts method calls to the Foo instance
IF fooProxy = (IF) Proxy.newProxyInstance(IF.class.getClassLoader(),
new Class[] { IF.class }, new IFInvocationHandler(target));
return fooProxy;
}
}
class IFInvocationHandler implements InvocationHandler {
private Foo foo;
IFInvocationHandler(Foo foo) {
this.foo = foo;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if (method.getName().equals("setMethod")) {
// Block call
throw new IllegalAccessException();
} else {
// Allow call
method.invoke(proxy, args);
}
return null;
}
}
class Foo implements IF {
public void setMethod() {
} // method that is not allowed to call
public void getMethod() {
}
}
interface IF {
void setMethod(); // method that is not allowed to call
void getMethod(); // method that is allowed to call
}

The closest thing to a C++ friend class in Java is package-private access.
SomeObject.java:
package somewhere.someobjandfriends;
public class SomeObject {
Object aField; // field and constructor
SomeObject() {} // are package-only access
public void aMethod() {
System.out.println(this);
}
}
SomeObjFactory.java:
package somewhere.someobjandfriends;
public class SomeObjFactory {
public SomeObject newHelloWorld() {
return new SomeObject() {
{
aField = "hello world!";
}
#Override
public String toString() {
return aField.toString();
}
};
}
}
Anywhere outside of the package can see SomeObject and aMethod but can only create new instances through the factory.

Related

Java: share object reference without passing as parameter

I have an ObjectFactory and a specialized case of implementation of that factory. I can't change the interface, that has 0 argument.
In one of the implementation I have to read a file and load some data. To pass the filename I can use the system properties because all I need to share is a string.
But in the other implementation I must start not from a file but from a memory structure. How can I do to pass the object (then I think the object reference) to the factory? Other methods? No way I serialize the object on a file and after I read it again because what I want to avoid is right the I/O footprint.
Thanks
OK, more informations:
This is the interface and the abstract factory I have to implement
public abstract interface A
{
public abstract Set<Foo> getFoo();
public abstract Set<Bar> getBar();
}
//this is otherpackage.AFactory
public abstract class AFactory
{
public static AccessFactory newInstance()
{
return a new built instance of the factory
}
public abstract A newA();
}
This is my implementation with my problem:
public class AFactory extends otherpackage.AFactory
{
#Override
public Access newA()
{
return new AA();
}
}
public class AA implements A
{
protected AA()
{
this.objectReferenceIWantToSaveHere = I retrieve from the shared memory zone;
use the object
}
}
Now I'd like to do something like this:
B b = something I built before
save b in a shared memory zone or something like that
otherpackage.AFactory f = mypackage.AccessFactory.newInstance();
A a = f.newA();
And inside the f.newA() call I'd like to access to the b object
Can't you simply use a constructor?
interface ObjectFactory { Object create(); }
class SpecialFactory implements ObjectFactory {
private final Object data;
public SpecialFactory(Object data) { this.data = data; }
#Override public Object create() { return somethingThatUsesData; }
}
Ass assylias proposes, you can pass the reference to the constructor. Or if you know where to find the reference, you could just ask for it before you use it? E.g. data = dataBank.giveMeTheData()
Agree it would help to get some more context around what you are doing... but could you use a shared static class in which your calling code places info into the static class, and your interface implementation references this same static class to obtain either the object and/or instructions?
So here's a client class. It has the entry point..and wants to pass an object to the interface implementer but it can't pass it directly...So it set's object it wants to pass in the MyStaticHelper.SetSharedObject method.
public class Client {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String mySharedObject = "Couldbeanyobject, not just string";
// Set your shared object in static class
MyStaticHelper.SetSharedObject(mySharedObject);
InterferfaceImplementer myInterfaceImplementer = new InterferfaceImplementer();
//
myInterfaceImplementer.RunMyMethod();
}
Here is the code for the static helper...
public class MyStaticHelper {
private static Object _insructionsObject;
public static void SetSharedObject(Object anObject)
{
_insructionsObject = anObject;
}
public static Object GetSharedObject()
{
return _insructionsObject;
}
}
and finally the the class that you call that uses the static helper to get the same object.
public class InterferfaceImplementer {
// no objects
public void RunMyMethod()
{
System.out.println(MyStaticHelper.GetSharedObject());
}
}
Again this works in a very simple scenario and wouldn't stand up if more than one implementer needs to be called simultaneously as this solution would only allow one obj to be in the static helper class.

How to use arguments in cloned object?

So let say I have such prototyping:
private static Hashtable<String, Furniture> map =
new Hashtable<String, Furniture>();
public My_product() {
loadCache();
}
public My_Product createProduct(String type, String name) {
Furniture cachedproduct = map.get(type);
return (Furniture) cachedproduct.clone();
}
private static void loadCache() {
Sub_product1 pr1 = new Sub_product1(null);
map.put("pr1", pr1);
Sub_product2 pr2 = new Sub_product2(null);
map.put("pr2", pr2);
}
So when I make an instance of an object, I don't know what value will be entered after cloning it (creating object using cloning). So I chosen null value for object instance. But when I clone it then I know what value needs to be assigned for that object. So how could I specify while cloning to put some value instead of null one from object instance?
As you can see in method createProduct method, there is argument called name. I would like that name to be used in cloned object, but how could I do that?
Can you use setter methods?
public My_Product createProduct(String type, String name) {
Furniture cachedproduct = map.get(type);
Furniture clonedProduct = (Furniture) cachedproduct.clone();
clonedProduct.setType(type);
clonedProduct.setName(name);
return clonedProduct;
}
However, I'm still not clear on the whole idea of this cloning of cached objects from the map. Is your product instantiation very expensive? What's the trick?
You cannot pass arguments through the Java built-in clone mechanism. You could provide a setter on the Furniture class to change the name after it has been cloned.
Note that cloning in Java is generally considered broken. It is a brittle way to create objects. Generally you are better of using the factory pattern, e.g. something like:
interface FurnitureBuilder {
Furniture build(String name);
}
class SubProduct1Builder implements FurnitureBuilder {
public Furniture build(String name) { return new SubProduct1(name); }
}
class MyFurnitureFactory {
private final Map<String, FurnitureBuilder> builderByType = ...
// initialization omitted
public Furniture create(String type, String name) {
return builderByType.get(type).build(name); // null check omitted!
}
}

Initialize supertype members based on subtype information

I have the following situation:
public abstract class A {
private Object superMember;
public A() {
superMember = initializeSuperMember();
// some additional checks and stuff based on the initialization of superMember (***)
}
protected abstract Object initializeSuperMember();
}
class B extends A {
private Object subMember;
public B(Object subMember) {
super();
subMember = subMember;
}
protected Object initializeSuperMember() {
// doesn't matter what method is called on subMember, just that there is an access on it
return subMember.get(); // => NPE
}
}
The problem is that I get a NPE on a new object B creation.
I know I can avoid this by calling an initializeSuperMember() after I assign the subMember content in the subclass constructor but it would mean I have to do this for each of the subclasses(marked * in the code).
And since I have to call super() as the first thing in the subclass constructor I can't initialize subMember before the call to super().
Anyone care to tell me if there's a better way to do this or if I am trying to do something alltogether wrong?
Two problems:
First, you should never call an overrideable member function from a constructor, for just the reason you discovered. See this thread for a nice discussion of the issue, including alternative approaches.
Second, in the constructor for B, you need:
this.subMember = subMember;
The constructor parameter name masks the field name, so you need this. to refer to the field.
Follow the chain of invocation:
You invoke the B() constructor.
It invokes the A() constructor.
The A() constructor invokes the overridden abstract methot
The method B#initializeSuperMember() references subMember, which has not yet been initialized. NPE.
It is never valid to do what you have done.
Also, it is not clear what you are trying to accomplish. You should ask a separate question explaining what your goal is.
Hum, this code does not look good and in all likelyhood this is a sign of a bad situation. But there are some tricks that can help you do what you want, using a factory method like this:
public static abstract class A {
public abstract Object createObject();
}
public static abstract class B extends A {
private Object member;
public B(Object member) {
super();
this.member = member;
}
}
public static B createB(final Object member) {
return new B(member) {
#Override
public Object createObject() {
return member.getClass();
}
};
}
The problem is when you call super(), the subMember is not initialized yet. You need to pass subMemeber as a parameter.
public abstract class A {
public A (Object subMember) {
// initialize here
}
}
class B extends A {
public B (Object subMember) {
super(subMember);
// do your other things
}
}
Since you don't want to have subMember in the abstract class, another approach is to override the getter.
public abstract class A {
public abstract Object getSuperMember();
protected void checkSuperMember() {
// check if the supberMember is fine
}
}
public class B extends A {
private Object subMember;
public B(Object subMember) {
super();
this.subMember = subMember;
checkSuperMemeber();
}
#Override
public Object getSuperMember() {
return subMember.get();
}
}
I hope this can remove your duplicate code as well.

How to construct a Non Instantiable AND Non Inheritable Class in Java

The question says it all.
I know the Singleton pattern (with final to its class) is a solution. Are there any other possible ways we can achieve this?
Abstracting a class makes it non-instantiable. Making it final makes it non-inheritable.
How do we combine both?
public final class SingletonObject
{
private SingletonObject()
{
// no code req'd
}
/*public static SingletonObject getSingletonObject()
{
if (ref == null)
// it's ok, we can call this constructor
ref = new SingletonObject();
return ref;
}*/
public Object clone()
throws CloneNotSupportedException
{
throw new CloneNotSupportedException();
// that'll teach 'em
}
private static SingletonObject ref;
}
Code Ref: http://www.javacoffeebreak.com/articles/designpatterns/index.html
Make the constructor private:
public final class Useless {
private Useless() {}
}
A private constructor is the normal object-oriented solution. However, it would still be possible to instantiate such a class using reflection, like this:
Constructor<Useless> con = Useless.class.getDeclaredConstructor();
con.setAccessible(true); // bypass "private"
Useless object = con.newInstance();
To prevent even reflection from working, throw an exception from the constructor:
public final class Useless {
private Useless() {
throw new UnsupportedOperationException();
}
}
You mean a class with static methods only? Class cannot be both final and abstract. But you can use private constructor to make it not instantinable.
final class StaticOnly {
private StaticOnly() {
throw new RuntimeException("Do not try to instantiate this");
}
public static String getSomething() {
return "something";
}
}
Below example will work to. You won't instantiate it because it's abstract. You won't inherit it because there is no way to call super constructor from external subclass (only inner subclass will work)
abstract class StaticOnly {
private StaticOnly() {}
public static String getSomething() {
return "something";
}
}
enum will work too
enum StaticOnly {
S;
public static String getSomething() {
return "something";
}
}
but it always have at least one instance (here it's S).
I would use the simplest Singleton pattern
enum Singleton {
INSTANCE;
}
The enum type is non-instance-able and non-inheritable and the classes initialisation is lazy and thread safe.
To declare there should never be an instance you can also use an enum
enum Utilities {
; // no instances
// add static methods here
}

Inheriting a class with constructor arguments in java

The situation is I want to inherit an object to have a cleaner constructor interface:
class BaseClass {
public BaseClass(SomeObject object){
...
}
}
class SubClass extends BaseClass{
private SubObject subObject = new SubObject();
public SubClass(){
super(new SomeObject(subObject)); // doesn't compile
}
}
But to do that I need to do stuff before the constructor like in the example above but can't because Java doesn't allow that. Is there any way around this? I'm starting to feel that if your class is designed to be subclassed it should always implement default constructor and provide setters for the values it needs... Sometimes you can get away with this if you create a new object straight into the super constructor as an argument but if you need a reference to the object you created then you are hosed.
You need to change it so that you're not referring to an instance member in the superconstructor call. Unfortunately if you need to then "save" the SubObject, it becomes tricky. I think you'd have to do it with constructor chaining:
class SubClass extends BaseClass{
private SubObject subObject;
public SubClass() {
this(new SubObject());
}
private SubClass(SubObject subObject) {
super(new SomeObject(subObject));
this.subObject = subObject;
}
}
public SubClass(){
super(new SomeObject(new SubObject())); // this should compile
}
Now in your super class, do something like this:
private final SomeObject foo;
public BaseClass(SomeObject foo){
this.foo = foo;
}
public /* or protected */ SomeObject getFoo(){return this.foo;}
Not exactly an answer since you would have no SubClass, but you could use a factory.
public BaseClassFactory {
public static BaseClass newBaseClass() {
// init some object
// ...
return new BaseClass(someObject);
}
}

Categories