1

Ok, I'm used to structuring my projects like this

|--com.mycompany.interfaces
|         |--IFoo1(public)
|         |--IFoo2(public)
|         |--IBar1(public)
|         |--IBar2(public)
|
|--com.mycompany.foos.impl
|         |--Foo1(default) implements IFoo1
|         |--Foo2(default) implements IFoo2
|
|--com.mycompany.bars.impl
|         |--Bar1(default) implements IBar1
|         |--Bar2(default) implements IBar2
|
|--com.mycompany.services
|         |-FooBarService (public)

I have one package to organize all interfaces and then the implementations are in their own related pacakges.

The public class FooBarService has to return instances of Foo1, Foo2, etc via their interfaces IFoo1, IFoo2, etc to callers outside this project. But class FooBarService cannot access the concrete classes Foo1, Foo2, etc as they are package scoped.

What is a good way to not expose the concrete classes to outside libraries but stil keep implementations in meaningful multiple packages? or is that even possible? In .net I can just specify concrete classes as internal, where ever they are implemented and whatever their namespace is but I'm wondering if it's possible in java use such structure?

Professor Chaos
  • 8,850
  • 8
  • 38
  • 54
  • One thing to bear in mind is that reflection can change access levels if a SecurityManager is not present. – BevynQ Apr 03 '13 at 02:45

4 Answers4

2

First do you really need all those interfaces? Unless your building a framework, library, or you forsee multiple implementations don't go around making interfaces because it seems like good design. With modern AOP and mocking libraries and IDE's that can refactor like a charm there is very little benefit in making hundreds of interfaces. Its especially (IMHO) stupid to make an interface for every Java Bean POJO just to hide special (or all) setters. I know it seems like good design but KISS is better.

Lets assume you do. You should deal with package visibility with project dependencies. That is the best way is to make multiple projects e.g. a multi module maven project.

something like

myproject
|  | myproject-api  // interfaces here, depends on pretty much nothing
|  |  | src
|  |  | pom.xml // or build.xml or whatever
|  | myproject-foo // implementations here, depends on myproject-api
|  |  | src
|  |  | pom.xml // or build.xml or whatever
|  | myproject-bar //implementations here, depends on myproject-api and maybe foo.
|  |  | src
|  |  | pom.xml // or build.xml or whatever
|  pom.xml  // or build.xml or whatever

The myproject build would produce three different jars (names might be different): myproject-api.jar, myproject-foo.jar, myproject-bar.jar

If your looking for a more pedantic organization you should look at this guys blog but you can't really enforce it (like you can in C#) with out separating out into separate projects.

You should also be familiar with the canonical Java SPI practice and dependency injection (now that its sort of standardized with @Inject).

I really don't recommend you do the @his static method factory pattern for services (especially instantiating instances of an interface). If you do this what happens at best is the service locator pattern but something far worse can happen where developers will wire dependent objects in the constructors (ie aggregation construction pattern) and you end up sometimes with the evil singleton pattern. Finally static methods are always available leading to unpredictable usage and lifecycle (compared to DI).

Also if your really adventurous you can go look at OSGI.

Regardless of SPI and OSGI I highly recommend the multi-module approach.

Community
  • 1
  • 1
Adam Gent
  • 47,843
  • 23
  • 153
  • 203
  • Thanks, I'll keep your suggestions in mind for future projects; for my current problem, factory seems to be the way to go. – Professor Chaos Apr 03 '13 at 12:32
  • @his answer is not really the factory pattern. It's good indirection but its not really factory. SPI like how many of the Java libs work uses the true factory pattern. – Adam Gent Apr 03 '13 at 13:45
  • Sorry, that is not the core of the factory pattern. A static factory method is a "true" scotsman, er, implementation of the factory pattern. – Hauke Ingmar Schmidt Apr 03 '13 at 14:29
  • It is not a true factory. Read my previous comment: http://stackoverflow.com/questions/15777885/java-package-woes/15778111?noredirect=1#comment22451273_15778111 . The factory pattern by definition has two levels of indirection. – Adam Gent Apr 03 '13 at 14:42
1

I am not very happy with the separation of "every interface in one package, implementations separate by type in different packages". I would put implementations and interfaces in one package and separate further by functionality. But you certainly have your good reasons.

Apart from the "big" solution (a module system like OSGi that hides anything except published interfaces) you can only hide concrecte classes with factories and inner classes. The point is to put the factories inside the impl package and to make the concrete class an inner class of the factory. The factory obviously still is visible to the outside but as the point is to prevent programmers from using specifics of concrete implementations this is not a problem.

So:

package com.mycompany.foos.impl
public class FooFactory {
    private static class FooImpl implements IFoo1 {
        ...
    }
    public static IFoo getFoo() {
        return new FooImpl();
    }
}

If your intention is to prevent any deeper inspection of the classes than it indeed can't be done with pure Java; it is not the purpose of the visibility modifiers; and need some module system. But even then the class can be inspected by reflection.

Hauke Ingmar Schmidt
  • 11,559
  • 1
  • 42
  • 50
  • That is not the factory pattern. The method that creates the object should not be static. It's good indirection but its not the factory pattern. – Adam Gent Apr 03 '13 at 13:43
  • @AdamGent It is often useful for factories to be non-static so the factory itself can be replaced but that is not the core of the [factory pattern](http://en.wikipedia.org/wiki/Factory_pattern). Here we have a fixed set of classes to produce, it is of no use to introduce another indirection because we can. – Hauke Ingmar Schmidt Apr 03 '13 at 14:28
  • its just slightly annoying that you go and site wikipedia with out reading: *Strictly speaking this is not an example of the Factory Method pattern (we can not override static), but rather an example of static factory method, which has no direct equivalent in Design Patterns. See for example Effective Java 2nd edition by Joshua Bloch, page 5*. I'm not against Static method factories (as they're much better than constructors) but when used with services (which he shows in question) it clearly becomes the service locator pattern. – Adam Gent Apr 03 '13 at 14:40
  • apologies for the previous comment (that was rude of me). The point I am trying to make is if he is going to bother making interfaces then he expects multiple implementations. If he expects multiple implementations then the `static factory method` is not really helpful. If your going to make a bunch of interfaces for a library or framework. Do it right and use true factory or dependency injection. The `static factory method` is useful for immutable object creation (see Guava) and usually the method is in the object it creates. – Adam Gent Apr 03 '13 at 15:35
0

You need to have a factory class which will return you the implementation instances.

Something like

if(requestedClass.equals("IFoo1"))
     return(IFoo1)new Foo1();
Pradeep Pati
  • 5,779
  • 3
  • 29
  • 43
-1

It is not possible to do that in Java. A outside librabry can create a class with the same package of your app, and it will have package visibility.

DiogoSantana
  • 2,404
  • 2
  • 19
  • 24