4
\$\begingroup\$

We have an object that needs to be converted to a different type before storing it in database. For that purpose, the library provides an annotation over the field that specifies the appropriate class[given as ClassName.class] to use for converting back & forth.

The class implements an interface of the library that has the marshall & unmarshall methods.

public class ObjectConverter implements Marshaller<Instant> {

    public static final ObjectConverter CONVERTER = new ObjectConverter();

    @Override
    public String marshall(Instant obj) {
        return obj.toString();
    }

    @Override
    public Instant unmarshall(Class<Instant> clazz, String obj) {
        return Instant.parse(obj);
    }
}

Now, we need to manually convert Instant to appropriate type at certain places. A straight-forward approach would be to create a new instance everywhere and invoke those public methods.

My colleague was suggesting to have a static final field of itself and use it wherever needed in order to avoid creating it each and every time. But, my argument was that nobody is stopping from creating a new instance, thus defeating the purpose of the static instance.

A better way to handle this, in case object creation is really costly would be to have a utility class that has static methods for converting back & forth. These can be invoked in both the marshaller and during manual conversions. Is there any better approach?

Is it a good practice to have both static instance and public constructor at the same time?

\$\endgroup\$
1
  • \$\begingroup\$ To get it clear: Are you talking about new ObjectConverter().marshall(...) vs. ObjectConverter.CONVERTER.marshall(...) ? \$\endgroup\$
    – oopexpert
    Commented Nov 23, 2016 at 20:00

2 Answers 2

1
\$\begingroup\$

The question is: what do you want to achieve.

As you store the singleton in the database it seems to me that your singleton is semantic and not technical.

Technical singletons have that unified structure of static instance field, maybe lazy initialization and private constructor to ensure only ONE instance per JVM.

Semantical singletons do not have the assertion to be unique per object identity in the JVM. Their assertion is they BEHAVE the same EVERYWHERE and they have semantic identity (equals) in ANY JVM to ensure identity beyond JVM boundaries.

Often this kind of singleton is used to have a central entry point to a domain/module.

To avoid the public constructor in the semantic singleton I have separated the requirement "central entry point" from "object instantiation". In my design I have a SingletonX class that adresses "central entry point". Furthermore I have a class X that is more or less a POJO Finally I have an interface InterfaceX to redefine the public interface of class X. Class X should be resolved at runtime and is mostly out of scope to be instantiated through client code. Class X is the class to be serialized.

\$\endgroup\$
3
  • \$\begingroup\$ I want to achieve two things: * reuse the conversion logic. * create the instance as less as possible. I want to know if it's OK to have both public constructor & static final instance, to achieve the above things. \$\endgroup\$
    – nitish712
    Commented Nov 23, 2016 at 7:32
  • \$\begingroup\$ A public constructor may be ok. But as I said: you should try to put the concrete class out of sight for API users (package scope, final, runtime resolution). The point is that with a private constructor you want to avoid unintentionally instantiation. If you make either your constructor private and internally you use reflection OR you use some other mechanics. But "reusage" and "generic" is valuable so I would break the encapsulation this time and try to make it very hard for other developers to misuse with other mechanics. \$\endgroup\$
    – oopexpert
    Commented Nov 23, 2016 at 7:49
  • \$\begingroup\$ But having a public constructor is defeating the whole purpose of static final instance right? I mean, someone tomorrow can come and create a new instance of the object without re-using the final instance. \$\endgroup\$
    – nitish712
    Commented Nov 23, 2016 at 8:15
0
\$\begingroup\$

What about the classic enum singleton?

public enum InstantMarshaller implements Marshaller<Instant> {
    INSTANCE {
        @Override
        public String marshall(Instant instantObj) {
            return obj.toString();
        }

        @Override
        public Instant unmarshall(String stringValue) {
            return Instant.parse(obj);
        }
    }
}

Example usage

InstantMarshaller.INSTANCE.marshall(obj);
InstantMarshaller.INSTANCE.unmarshall(string);

Effective Java is a good book.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.