Java类范围和库

我正在创建一个Java库,作为最终产品,打算将这个.jar分发给开发人员。

我正在从Objective-C“翻译”我的库,在那里我控制哪些类头文件可供开发人员使用。 换句话说,我只向开发人员展示他们可以处理的几个类。

在我的Java库中,我正在使用包,而且我的包已经变得非常大。 所以我决定将我的模型和控制器分成不同的包。 但是现在我希望保密的模型我需要标记为公共,以便从主包中使用。

我的问题是,这与我在Objective-C中做的事情有什么不同吗?

例如,我有一个Event类,它实际上只在内部使用,我不希望用户知道它或考虑它。 我有另一个类TimedEvent,用户可以获取一个管理实例。

在我的Objective-C中,我只是从库公共范围中排除了Event类,允许使用TimedEvent。

如果我在我的库中使事情变得更整洁,那么包装似乎不是那样的。 从现在开始,我的主控制器在主包中,所有模型都在另一个包中 – 被迫拥有一个公共范围。

意见?

这是可能的Java,但有理由(几乎)没有人这样做…

如果将实现和接口放在同一个包中,那么可以省略类和方法中的所有访问修饰符( privateprotectedpublic ),以赋予它们“默认”或“包”可见性:只有同一个包中的类才是允许查看/使用它们。

缺点:您必须混合使用API​​和实现。

另一种方法是将实现移动到包*.private.* 。 不再混合API和实现,但恶意用户可以轻松访问实现 – 它只是一个命名约定。 就像一个停止标志:它意味着什么(“小心”),但实际上并没有阻止你。

最后,您可以在界面内部实现接口。 例如:

 public interface IFoo { String getName(); private static class Foo implements IFoo { public String getName(); } public static class FooFactory { public static IFoo create() { return new Foo(); } } } 

丑,不是吗?

控制类暴露于世界的常用方法是隐藏接口和工厂背后的实现。

  • TimedEvent创建一个接口,并创建一个用于创建TimedEvent接口实例的TimedEvent
  • 将接口放在主包中,将工厂放在子包中
  • 让工厂公众可见
  • 在子包中实现接口,为其提供包可见性
  • 在工厂中创建实现TimedEvent接口的类的实例

以下是如何执行此操作的示例:

 package com.my.main; public interface TimedEvent { void fire(); } package com.my.main.events; import com.my.main; public class EventFactory { public TimedEvent makeTimedEvent() { return new TimedEvent (); } } // TimedEventImpl has package visibility - it is not public. class TimedEventImpl implements TimedEvent { public void fire() { // Fire a timed event } } 

用户可以像这样访问TimedEvent

 com.my.main.events.EventFactory f = new com.my.main.events.EventFactory(); com.my.main.TimedEvent evt = f.makeTimedEvent(); evt.fire();