我正在阅读有效的java 教科书。第一项是关于使用静态工厂方法而不是公共构造函数。我怀疑的是,如果我指定Interface
我如何在Interface
中指定静态工厂方法?因为java不支持interface
内的静态方法。教科书指定了如何创建包含公共静态工厂方法的不可实例化的类。但是这些方法如何访问实现类的私有构造函数呢?
教科书说如果要定义Interface Type
,请创建一个不可实例化的类Types
,并在该类中包含静态工厂方法。但是Types
类中定义的方法如何访问Interface Type
的具体实现的私有构造函数
编辑: - 以下句子引自教科书。请解释一下它的含义
“接口不能有静态方法,因此按照惯例,名为 Type 的接口的静态工厂方法放在名为 Types 的不可实例化的类(Item 4)中“
编辑: - 取自Effective Java By Joshua Bloch: Item1 - Static Factory Method
public interface Foo{ //interface without plural 's' (question 1)
public void bar();
}
public abstract class Foos(){ // abstract factory with plural 's' (question 1)
public static Foo createFoo(){
return new MyFoo();
}
private class MyFoo implements Foo{ // a non visible implementation (question 2)
public void bar(){}
}
}
我的问题是静态方法createFoo()
如何调用MyFoo
的私有构造函数
答案 0 :(得分:5)
这个问题在JAVA 8中得到解决。现在接口可以有静态方法。更多详情: - http://www.techempower.com/blog/2013/03/26/everything-about-java-8/
答案 1 :(得分:3)
您可以将工厂定义为返回接口,但在内部它会创建一个具体的类。
例如:
public Interface I { }
private class Impl implements I {
}
I buildI() {
return new Impl();
}
诀窍是创建包私有(或者即使它们是私有内部类)构造函数的实现,然后只有工厂可以构建它们。
这种方法的强大之处在于,工厂可以根据要求构建适当的实现,并且所有实现都对用户不可见。例如,当您使用工厂创建EnumSet
时,有多个内部实现,具体取决于Enum
中正在构建EnumSet
的条目数。一个超长版本,使用长Enums
的位域,少于64个条目,对于更长的枚举,速度较慢。
要指定工厂的界面,您只需:
public interface Factory {
I buildI();
}
现在,人们可以通过setFactory(new FactoryImpl());
给您打电话,然后您可以调用factory.buildI()
,然后他们的代码会返回具体的实现。
您可以更进一步,使用泛型:
public interface GenericFactory<T> {
T buildInstance();
}
然后你的setFactory
变为:
public void setFactory(GenericFactory<I> factory);
要创建工厂,他们会这样做:
public class FactoryImpl implements GenericFactory<I> {
@override
I buildInstance() {
return new impl();
}
}
但现在你可以使用同一个工厂类来完成任何需要工厂的工作,只需更改泛型要求。
它可以调用私有构造函数的原因非常简单 - 它在同一个类中声明!
在一个Java文件中,您可以使用私有构造函数创建类。然后在类中定义静态方法,即使它是静态的,它仍然具有访问构造函数所需的特权。
如果工厂和实现位于不同的类中,那么它们将被放置在同一个包中,并且该方法将包设为私有而不是私有。
答案 2 :(得分:0)
它讨论了在实现中通过静态工厂方法创建对象而不是接口
public Interface MyInterface {
public void myFunction();
}
public class MyClass implements MyInterface {
// constructor is made private
private MyClass() {}
// Use this to create object instead use static factory
public static MyClass getInstance() {
return new MyClass();
}
public void myFunction(){
// your implementation
}
}
上一篇文章还讨论了静态工厂方法.. What are static factory methods?
除了这本书之外,我还发现下面提到的链接很好 http://www.javacodegeeks.com/2013/01/static-factory-methods-vs-traditional-constructors.html
答案 3 :(得分:0)
您无法在接口中定义工厂方法,但也不能在接口中使用构造函数:接口无法实例化。关键是在实现接口的类中使用工厂方法而不是构造函数,而不是在接口本身。
答案 4 :(得分:0)
考虑这一点的一种方法是考虑封装。考虑下面的Java 9+代码:
public interface Engine {
void start();
static Engine getEngine(String type) {
switch (type) {
case "combustion":
return new CombustionEngine();
case "electric":
return new ElectricEngine();
default:
throw new IllegalArgumentException("Unknown engine type : " + type);
}
}
}
class CombustionEngine implements Engine {
CombustionEngine() {
}
@Override
public void start() {
// injecting fuel and igniting it to create combustion...
}
}
class ElectricEngine implements Engine {
ElectricEngine() {
}
@Override
public void start() {
// electric current from battery flowing through coil in magnetic field...
}
}
请注意,实现中的构造函数是程序包私有的,因此来自其他程序包的调用者无法直接实例化实现,而应使用factory方法。
界面中具有工厂方法
EngineFactory
类(Factory方法设计模式的传统实现)如果需要,还有一种方法可以将实现实例创建为单例,从而改善内存占用量:
public interface Engine {
enum EngineType {
COMBUSTION,
ELECTRIC;
private static EnumMap<EngineType, Engine> MAP = new EnumMap<>(EngineType.class);
static {
MAP.put(COMBUSTION, new CombustionEngine());
MAP.put(ELECTRIC, new ElectricEngine());
}
}
void start();
static Engine getEngine(EngineType type) {
return EngineType.MAP.get(type);
}
}