简体   繁体   中英

How to correctly organize a set of concrete classes implementing an interface in different packages?

I have defined an interface my system will depend on:

IMethodCall

and I've created a bunch of classes that implement IMethodCall :

AbstractMethodCall
ConstructorCall
TargetConstructorCall
VoidMethodCall
TargetVoidMethodCall
NonVoidMethodCall
TargetNonVoidMethodCall

They are details of implementation, and my system doesn't know about them (or at least, doesn't need to know).

There is some tricky logic behind choosing which implementation to instantiate, based on a set of data I'll have at hand at the time, so I decided to create a factory to have all that logic grouped in a single place:

MethodCallFactory

I'm trying to understand what should be the package structure used here. My original idea was to put all the concrete classes in a methodCalls package, and set them as package-protected, so no-one would know about their very existance. Then I'd let IMethodCall and MethodCallFactory outside, so users of my system could use them. The problem is that if I put the concrete classes as package-protected then the factory must also be in their package, which in its turn would seem kinda odd, as for an outside viewer it would look as that's a package that only exists to contain a factory.

At the moment the best trade-off I see is to put the concrete classes as public, but I'm wondering how you guys usually handle this kind of situations?

When I am faced with this situation, I would put the concrete implementation classes and the factory in the same package, and make the implementation classes package private.

You mentioned that this approach seems odd, because of the outside viewpoint. I disagree that the outside user wouldn't know there are implementation classes. Most IDE's will show the classes within the package, even if they are not accessable. Also, if a programmer tries to use your implementation classes, the compiler will imply that the class exists while disallowing access.

I also would disagree that it's odd to have a package containing only a factory and it's private implementations. This group of classes are tightly related, which makes it logical to group them together in a single place.

You can put your factory class and interface in a public package, and put the implemented classes in an internal package.

The internal package is discouraged, the classes in the internal package may be changed anytime. User should call the api in the public package.

for example:

a public package is org.feeling.ui.dialogs

an internal package is org.feeling.internal.ui.dailogs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM