Java +Strategy + Factory + same package = how to hide specialized classes? - java

I want to hide the specialization classes from the external classes of the same package.
Example:
package com.app.letter;
public interface LetterChange {
void change();
}
public class A implements LetterChange{
public void change(){..}
}
public class B implements LetterChange{
public void change(){..}
}
To instantiate these classes I use a factory....
package com.app.letter;
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
return doesNotMatter.isA() ? new A() : new B();
}
Note, all of them are in the same package and I DO NOT WANT to put the factory and the specialized classes in a sub package and change the specialization classes' constructors to default (package).
Following this example, I have a third class in the same package
package com.app.letter;
public class DoesNotMatterClass{
public void situations(){
LetterFactory.getInstance(null); // Legal
new A(); Illegal
new B(); Illegal
}
}
I want to provide the A or B only by the factory LetterFactory.getInstance(doesNotMatter) which is in the same package.

Make A and B private static classes of the factory:
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
return doesNotMatter.isA() ? new A() : new B();
}
private static class A implements LetterChange{
public void change(){..}
}
private static class B implements LetterChange{
public void change(){..}
}
}
Only the factory knows the existence of these classes and can instanciate them.

First of all, I see no reason to not allow to instantiate your classes directly. Usually, you do not care who instantiated the class, as long as you are sure it was instantiated correctly.
Therefore, I believe you have not one problem, but two:
Provide a way for anyone to correctly create both class A and class B manually, if required.
Provide a way to instantiate either A or B given some set of abstract parameters (your Factory solution).
As for the first part, the are 3 ways to instantiate classes of different complexity correctly:
A constructor, which has a list of all required parameters and dependencies. This can be used for simple cases pretty well.
A factory method. This can be used for more complex scenarios.
A factory class/a builder class. These are usually used for complex scenarios.
Now, whichever one you choose, by all logic it should be allowed to be public. The constructor/factory method/factory class will enforce your rules to create a proper valid instance of either A or B. And, as I mentioned before, there is no possible scenario when you should disallow creating a perfectly good and valid instance of a class.
Let's say you went with a builder class as the most complex solution. Here's how your code might look:
package com.app.letter.A;
public class A {
A() { //Package visibility, we don't want anyone to create an invalid A class
...
}
...
}
public class ABuilder {
public void validateAndSetSomeCriticalParam(Param param) {
...
}
public A build() {
A a = new A();
a.setSomeCriticalParam(param);
...
return a;
}
}
The builder should be designed in a thought in mind, that it could not in any way produce an invalid instance of A. This way, you can allow the builder to be the only way of instantiating A and not worrying about it, because all instances it creates are always valid. You can utilize proper API on the builder or Exceptions to reach this.
Also, the builder approach is the most complex one, for some simpler scenarios you might use a bunch of public static factory methods. However the idea should remain the same - the public factory methods should ensure that they produce only valid instances of A.
Same stuff for B class, in other package:
package com.app.letter.B;
public class B {
...
}
public class BBuilder {
...
}
Now for the factory. Basically same thing you had, but with builders:
package com.app.letter;
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
if (doesNotMatter.isA()) {
ABuilder builder = new ABuilder();
builder.setSomeCriticalParam(...);
builder...
return builder.build();
} else {
BBuilder builder = new BBuilder();
builder.setSomeBSpecificParam(...);
builder...
return builder.build();
}
}
}
And about the usages:
public class DoesNotMatterClass{
public void situations(){
LetterFactory.getInstance(..whatever..); // Legal
new A(); //Illegal, as it is package protected
new B(); //Illegal, as it is package protected
new ABuilder(); //Legal, as ABuilder can ensure that only valid As are created
new BBuilder(); //Legal, as BBuilder can ensure that only valid Bs are created
}
}
I will add, repeating myself once again, you should only hide the parts of your system that can be abused in some ways. There is no point of hiding a class or a method if there is no way for it to be abused. Therefore, if you provide a way to correctly initialize a valid instance of A or B it should not matter to you that some other part of the system can see it or use it.

You can hide A and B from other packages by making them package-protected.
But that won't hide them from classes in the same package.
Since they have to be visible by the factory, but not by any other class of the same package, the only way to do that is to make them private static nested classes of the factory class.

Related

What is the best practice in Java to set a constant required in subclasses?

I have the following situation:
A parent class has a function that depends on a constant. But the only valid place to define that constant is in subclasses (parent class cannot define the constant's value, but it can be used with the constant undefined in 99% of use cases - the constant is a default to use if a specific configuration element is missing).
However, I would like to enforce that any child class inheriting from that parent class must define the value for the constant, since any child classes have to be able to use the other 1% of functionality.
What is the best practice to implement this enforcement in Java, ideally at compile time? (clearly, at runtime, I can simply check if the constant is null/empty in the method using it).
My own solution was to implement a value-getter for the constant as an abstract method in the parent class, and call that in combination with the real setter in the constructor; something like this:
public class HelperClass1 {
private String myConstant;
public void setMyConstant() {} // implemented obviousy
public void myMethod() { // Called from ParentClass's methods
// Do something useful with myConstant
}
}
import HelperClass1;
public abstract class ParentClass {
ParentClass() {
HelperClass1.setMyConstant( getMyConstantValue() );
}
public abstract void getMyConstantValue();
}
public class ChildClass1 extends ParentClass {
public void getMyConstantValue() { return "BUZZ"; }
}
public class ChildClass2 extends ParentClass {
} // Fails to compile without getMyConstantValue()
However, (a) This implementation has a problem (I can't use ParentClass itself, since it's now abstract) without subclassing; and (b) since I'm not a Java developer, I'm afraid that this isn't the best or the most elegant solution. So I'd like to know if there's a best practices approach that improves on what I implemented.
Provide two constructors for the parent class:
One is a protected constructor which takes the constant as an argument.
The other is private constructor which can construct instances of the parent class without setting the constant.
Provide a factory method for the parent class which can call the private no-constant constructor.
Classes that want to get an instance of the parent class can call the factory method. But child classes that want to inherit from the parent class have to call the protected constructer, which can validate that a valid constant was passed.
public class ParentClass {
private final SomeClass myConstant;
protected ParentClass(SomeClass aConstant) {
if (null == aConstant) {
throw new IllegalArgumentException("...");
}
myConstant = aConstant;
}
private ParentClass() {
myConstant = null;
}
public static ParentClass getInstance() {
return new ParentClass();
}
}
public class ChildClass {
public ChildClass() {
super(new SomeClass(42));
}
}
This isn't perfect. Someone could write a child class that passes a bad constant to the superclass constructor, and it wouldn't actually fail until some code tried to construct an instance of the child class.

Static block fails to execute for self-registering object in Java

This is a bit of a tricky one to explain, but let's say I have two classes A and B. A contains a static list of factory objects that are registered by each object that provides such a factor. In this example B is such a class and provides an imaginary Factory implementation.
Class A:
public class A {
protected static Map<String, Factory> registered = new HashMap<String, Factory>();
protected static register(String name, Factory factory) {
registered.put(name, factory);
}
public A() {
// Do something with the factories we've registered
}
}
Class B:
public class B {
static {
A.register("Foo", new Factory() {
public Object create() {
return new B();
}
});
}
public B() {
// Create a new instance of class B
}
}
In my program for some strange reason the static block within B is never called, so when I start interacting with A no factories have been registered so it can't do what it needs to do.
If I move the creation of each Factory into A directly there is no problem of course. I'm working under the assumption that because there are no clear references to B from any class that the compiler isn't recognising there's a link between A and B so doesn't bother with B at all. Is there anything I can do to work around this? I'd hoped to avoid adding each new factory into A directly as it makes maintenance more difficult than having new factories simply register themselves, but clearly having none of them work at all is even worse; still, I'd like to somehow get it to work as intended if I can.
In case it's relevant, the particular JVM I'm working with is the Android JVM, could this be a side-effect of some optimisation that that that JVM is using?
You can read about class loading in this blog post. The point is that a class won't be loaded until it is referenced. And the static blocks of a class won't be executed until the class is loaded. The rules are
an Instance of class is created using either new() keyword or using reflection using class.forName(), which may throw ClassNotFoundException in Java.
an static method of Class is invoked.
an static field of Class is assigned.
an static field of class is used which is not a constant variable.
if Class is a top level class and an assert statement lexically nested within class is executed.
A solution is to either instantiate B or call a no-op static method (or any of the above).
public class B {
static {
A.register("Foo", new Factory() {
public Object create() {
return new B();
}
});
}
public void static noOp() {}
public B() {
// Create a new instance of class B
}
}
...
B.noOp();
The Oracle JVM spec states this here.

How can I automatically put subclasses in an ArrayList?

I have a superclass, and then several subclasses, like this:
public abstract class A {
public abstract int getValue();
}
public class B extends A {
public int getValue() {
return 1;
}
}
public class C extends A {
public int getValue() {
return 123;
}
}
public class D extends A {
public int getValue() {
return 15234;
}
}
There are about 100 or so subclasses. I also have a manager:
public class Manager {
public static ArrayList<A> list = new ArrayList<A>();
}
How can I "magically" add an instance of all subclasses of A to list without manually creating an instance of every single subclass and adding it to the list? Perhaps with using an Initialization Block?
EDIT
It's not important how I access list in Manager. I edited it to be static.
(2nd attempt - my first attempt was based on a misunderstanding of the Question.)
I'm assuming that what you want to do is build a (static) list that:
contains exactly one instance of each of the subclasses,
is created and populated ahead of time, and
doesn't involve code in each subclass creating / adding an instance of itself to the list.
Firstly, an instance initializer block won't do this. An instance initializer is run when you create an instance ... and something has to new the class (i.e. each of the subclasses) for this to happen.
I think the only viable approach is to write some hairy reflective code that:
iterates over all classes on the classpath,
loads each one using Class.forName(),
reflectively tests to see if the class is a subclass of A,
if it is, reflectively invokes the classes no-args constructor and adds the resulting instance to "the list".
This is (IMO) pretty hacky!! And it is going to be expensive ... unless you can limit the "package space" that needs to be searched for these subclasses.
Actually, this could be a problem that would be better solved using an enum ... especially if the subclasses don't have behavioural differences that require different method implementations. (For instance your getValue() method could just return a private variable ... that you initialize using a constructor.) See #Paul Bellora's answer.
(The thing that would prevent this from being applicable would be if there needed to be multiple instances of some of the subclasses. That's not possible with enums.)
Each class is going to represent a command.
Based on the description of your problem, it sounds like A could be an enum:
public enum A {
B(1) {
#Override
public void execute() {
//code and stuff
}
},
C(123) {
#Override
public void execute() {
//code and stuff
}
},
D(15234) {
#Override
public void execute() {
//code and stuff
}
};
private final int value;
private A(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public abstract void execute();
}
Now, there is exactly one instance of each command, and you can easily iterate commands with A.values().
Although it doesn't quite make sense... one way you can do is, do things similar to Spring's component scanning: make use of things like PathMatchingResourcePatternResolver and find out all possible classes. Iterate through them and add to list if that is a subclass of A.
This is a bit of a hackish way to do it, but if all your subclasses are in one folder (the actual class files) you could iterate over the files in the folder and use the ClassLoader. You code would look something along the lines of -
for(String className : classNames){
Class clazz = classLoader.loadClass(className);
list.add(clazz.newInstance());
}
Look at the ClassLoader API for more info. Also keep in mind that this is not very efficient, but if you are just doing this once you should be fine.
Could be like this :
public abstract class A {
public A(Manager m) {
m.list.add(this);
}
public abstract int getValue();
}
public class B extends A {
public B(Manager m) {
super(m);
}
}
This way you never again have to deal with m.list.add(new A()); while subclassing. But I don't know if this is what you are looking for...
EDIT :
It's not important how I access list in Manager. I edited it to be static.
If you don't care about using singletons, here is a very basic implementation:
But read What is bad about singletons.
public class Manager {
private static Manager instance = null;
protected Manager() {
// Exists only to defeat instantiation.
}
public static Manager getInstance() {
if(instance == null) {
instance = new Manager();
}
return instance;
}
}
Then:
public abstract class A {
public A() {
Manager.getInstance().list.add(this);
}
public abstract int getValue();
}
public class B extends A {
}
But, again this is very not satisfying as a design...
1) You need to find all available subclasses of class A. For that you need to scan all classes on the Java classpath. To make things easier we can assume that all subclasses are in the same location as A.class. A is supposed to be in a jar or in a folder. We can find out its actual location as
URL url = A.class.getProtectionDomain().getCodeSource().getLocation();
2) Lets assume that it is a folder, eg file:/D:/workspace1/x/target/classes/. Now we should walk thru all .class files in this folder and subfolders. We can use File.listFiles or Java 7 NIO2 for that. We have 2 options
a) load each class and check its superclass
Class cls = Class.forName();
if (cls.getSuperClass() == A.class) {
...
b) use javaassist framework http://www.javassist.org or similar to work with class file directly
DataInputStream ds = new DataInputStream(new BufferedInputStream(path));
ClassFile cf = new ClassFile(ds);
String superClass = cf.getSuperClass();
if (superClass.equals("A")) {
Class cls = Class.forName(cf.getName());
...
option b is loads only the classes you actually need, option a is simpler but it loads all classes in the folder
In both cases you create of an instance as
A a = (A) cls.newInstance();
assuming that all subclasses have no-arg constructor
How about using a class path scanner to automatically detect your target classes :
List<Class<?>> classes = CPScanner.scanClasses(new ClassFilter().packageName("com.foo.*").superClass(A.class));
Since you've got the target classes, you can easily initialize them by using newInstance method.
By the way use the maven dependency below to use the given snippet:
<dependency>
<groupId>net.sf.corn</groupId>
<artifactId>corn-cps</artifactId>
<version>1.1.1</version>
</dependency>
Cheers.

Why we can't create protected methods in JAVA interfaces? [duplicate]

I know that an interface must be public. However, I don't want that.
I want my implemented methods to only be accessible from their own package, so I want my implemented methods to be protected.
The problem is I can't make the interface or the implemented methods protected.
What is a work around? Is there a design pattern that pertains to this problem?
From the Java guide, an abstract class wouldn't do the job either.
read this.
"The public access specifier indicates that the interface can be used by any class in any package. If you do not specify that the interface is public, your interface will be accessible only to classes defined in the same package as the interface."
Is that what you want?
You class can use package protection and still implement an interface:
class Foo implements Runnable
{
public void run()
{
}
}
If you want some methods to be protected / package and others not, it sounds like your classes have more than one responsibility, and should be split into multiple.
Edit after reading comments to this and other responses:
If your are somehow thinking that the visibility of a method affects the ability to invoke that method, think again. Without going to extremes, you cannot prevent someone from using reflection to identify your class' methods and invoke them. However, this is a non-issue: unless someone is trying to crack your code, they're not going to invoke random methods.
Instead, think of private / protected methods as defining a contract for subclasses, and use interfaces to define the contract with the outside world.
Oh, and to the person who decided my example should use K&R bracing: if it's specified in the Terms of Service, sure. Otherwise, can't you find anything better to do with your time?
When I have butted up against this I use a package accessible inner or nested class to implement the interface, pushing the implemented method out of the public class.
Usually it's because I have a class with a specific public API which must implement something else to get it's job done (quite often because the something else was a callback disguised as an interface <grin>) - this happens a lot with things like Comparable. I don't want the public API polluted with the (forced public) interface implementation.
Hope this helps.
Also, if you truly want the methods accessed only by the package, you don't want the protected scope specifier, you want the default (omitted) scope specifier. Using protected will, of course, allow subclasses to see the methods.
BTW, I think that the reason interface methods are inferred to be public is because it is very much the exception to have an interface which is only implemented by classes in the same package; they are very much most often invoked by something in another package, which means they need to be public.
This question is based on a wrong statement:
I know that an interface must be public
Not really, you can have interfaces with default access modifier.
The problem is I can't make the interface or the implemented methods protected
Here it is:
C:\oreyes\cosas\java\interfaces>type a\*.java
a\Inter.java
package a;
interface Inter {
public void face();
}
a\Face.java
package a;
class Face implements Inter {
public void face() {
System.out.println( "face" );
}
}
C:\oreyes\cosas\java\interfaces>type b\*.java
b\Test.java
package b;
import a.Inter;
import a.Face;
public class Test {
public static void main( String [] args ) {
Inter inter = new Face();
inter.face();
}
}
C:\oreyes\cosas\java\interfaces>javac -d . a\*.java b\Test.java
b\Test.java:2: a.Inter is not public in a; cannot be accessed from outside package
import a.Inter;
^
b\Test.java:3: a.Face is not public in a; cannot be accessed from outside package
import a.Face;
^
b\Test.java:7: cannot find symbol
symbol : class Inter
location: class b.Test
Inter inter = new Face();
^
b\Test.java:7: cannot find symbol
symbol : class Face
location: class b.Test
Inter inter = new Face();
^
4 errors
C:\oreyes\cosas\java\interfaces>
Hence, achieving what you wanted, prevent interface and class usage outside of the package.
Here's how it could be done using abstract classes.
The only inconvenient is that it makes you "subclass".
As per the java guide, you should follow that advice "most" of the times, but I think in this situation it will be ok.
public abstract class Ab {
protected abstract void method();
abstract void otherMethod();
public static void main( String [] args ) {
Ab a = new AbImpl();
a.method();
a.otherMethod();
}
}
class AbImpl extends Ab {
protected void method(){
System.out.println( "method invoked from: " + this.getClass().getName() );
}
void otherMethod(){
System.out.println("This time \"default\" access from: " + this.getClass().getName() );
}
}
Here's another solution, inspired by the C++ Pimpl idiom.
If you want to implement an interface, but don't want that implementation to be public, you can create a composed object of an anonymous inner class that implements the interface.
Here's an example. Let's say you have this interface:
public interface Iface {
public void doSomething();
}
You create an object of the Iface type, and put your implementation in there:
public class IfaceUser {
private int someValue;
// Here's our implementor
private Iface impl = new Iface() {
public void doSomething() {
someValue++;
}
};
}
Whenever you need to invoke doSomething(), you invoke it on your composed impl object.
I just came across this trying to build a protected method with the intention of it only being used in a test case. I wanted to delete test data that I had stuffed into a DB table. In any case I was inspired by #Karl Giesing's post. Unfortunately it did not work. I did figure a way to make it work using a protected inner class.
The interface:
package foo;
interface SomeProtectedFoo {
int doSomeFoo();
}
Then the inner class defined as protected in public class:
package foo;
public class MyFoo implements SomePublicFoo {
// public stuff
protected class ProtectedFoo implements SomeProtectedFoo {
public int doSomeFoo() { ... }
}
protected ProtectedFoo pFoo;
protected ProtectedFoo gimmeFoo() {
return new ProtectedFoo();
}
}
You can then access the protected method only from other classes in the same package, as my test code was as show:
package foo;
public class FooTest {
MyFoo myFoo = new MyFoo();
void doProtectedFoo() {
myFoo.pFoo = myFoo.gimmeFoo();
myFoo.pFoo.doSomeFoo();
}
}
A little late for the original poster, but hey, I just found it. :D
You can go with encapsulation instead of inheritance.
That is, create your class (which won't inherit anything) and in it, have an instance of the object you want to extend.
Then you can expose only what you want.
The obvious disadvantage of this is that you must explicitly pass-through methods for everything you want exposed. And it won't be a subclass...
I would just create an abstract class. There is no harm in it.
With an interface you want to define methods that can be exposed by a variety of implementing classes.
Having an interface with protected methods just wouldn't serve that purpose.
I am guessing your problem can be solved by redesigning your class hierarchy.
One way to get around this is (depending on the situation) to just make an anonymous inner class that implements the interface that has protected or private scope. For example:
public class Foo {
interface Callback {
void hiddenMethod();
}
public Foo(Callback callback) {
}
}
Then in the user of Foo:
public class Bar {
private Foo.Callback callback = new Foo.Callback() {
#Override public void hiddenMethod() { ... }
};
private Foo foo = new Foo(callback);
}
This saves you from having the following:
public class Bar implements Foo.Callback {
private Foo foo = new Foo(this);
// uh-oh! the method is public!
#Override public void hiddenMethod() { ... }
}
I think u can use it now with Java 9 release. From the openJdk notes for Java 9,
Support for private methods in interfaces was briefly in consideration
for inclusion in Java SE 8 as part of the effort to add support for
Lambda Expressions, but was withdrawn to enable better focus on higher
priority tasks for Java SE 8. It is now proposed that support for
private interface methods be undertaken thereby enabling non abstract
methods of an interface to share code between them.
refer https://bugs.openjdk.java.net/browse/JDK-8071453

Return a private class implementing an interface keeping the implementation private

Static method M returns an object implementing interface A:
interface A { ... }
static A M() { ... }
Within M I would like to construct an object of type B and return that, given that B implements A:
class B implements A { ... }
I do not want client code to know anything about how B is implemented, I would prefer for B not to be a static class, B must be immutable and there could be different B handed to different clients. I want to prevent instantiation of B outside method M at all costs (short of reflection, as one user commented).
How can I achieve the above? Where and how should I implement B? Could you please provide a short code example?
My main problem is: how can I have "different Bs?"
A static inner class is probably your best bet. You won't be able to "prevent instantiation of B at all costs" since with reflection, client code can bypass all access modifiers.
You can use anonymous inner class that won't be called B (is anonymous) but will implement A for example
interface A {
void someMethod();
}
public class Test {
static A M() {
return new A() {// it will create and return object of anonymous
// class that implements A
#Override
public void someMethod() {
}
};
}
}
Without using reflection object of anonymous class can be created only by method M. Also it can't be extended so it is good first step to immutability.
You could also use a Proxy implementation to hide the implementation class further
public interface A {
public Object getValue();
}
public class Factory {
public static A newInstance() {
return new ProxyA(AImpl);
}
}
public class ProxyA implements A {
private A proxy;
public ProxyA(A proxy) {
this.proxy = proxy;
}
public Object getValue() {
return proxy.getValue();
}
}
All this is really doing is hiding the implementation of A under another layout and makes it difficult to create a instance of ProxyA
But as #Asaph points out, with reflection, it becomes next to near impossible to truly guard against people accessing various parts of the classes and objects...
You could also separate your interface and implementations via different Classloaders, so that you only ever expose the interface's to the developers and implementations are delivered by dynamic class loading them at runtime. While not solving the underlying problem, it further complicates the matters for those trying to circumvent your factory.
IMHO

Categories

Resources