这是我第一次写Factory
课程。下面是我的Factory类,我不确定这是否是制作线程安全的Singleton Factory类的正确方法。我将使用这个工厂返回我客户的实例?
public class ClientFactory {
private static ClientFactory instance = null;
private ClientFactory() {
}
public static ClientFactory getInstance() {
if (instance == null)
{
instance = new ClientFactory();
}
return instance;
}
public IClient getClient() {
return new TestClient();
}
}
这是我的TestClient类 -
public class TestClient implements IClient {
}
这就是我将如何使用我的工厂 -
IClient client = ClientFactory.getInstance().getClient();
答案 0 :(得分:21)
事实上,您的工厂不是线程安全的,因为在竞争条件下,您可以在应用程序中使用多个ClientFactory。让我们假设两个线程:
在我看来,在Java中编写单例的最简单方法是使用枚举。在你的情况下它会看起来:
public enum ClientFactory {
INSTANCE;
public Company getClient() {
return new Company();
}
}
用法:
ClientFactory.INSTANCE.getClient()
答案 1 :(得分:5)
Wiki上的线程安全实现(示例) - Singleton Pattern on Wikipedia
与上面的链接一样,单元素enum
类型是为任何支持枚举的Java实现Singleton的最佳方式。
最简单的一个:
public class ClientFactory{
private ClientFactory() {}
private static ClientFactory INSTANCE=null;
public static ClientFactory getInstance() {
if(INSTANCE==null){
synchronize(ClientFactory.class){
if(INSTANCE==null) // check again within synchronized block to guard for race condition
INSTANCE=new ClientFactory();
}
}
return INSTANCE;
}
}
Source:
Wikipedia
答案 2 :(得分:2)
你的工厂是一个完美的Singleton(只是它不是线程安全的)。
答案 3 :(得分:2)
单身人士和工厂是不同的事情。对于属性构造一个Singleton,我想你可以把它的getInstance()方法看作一个工厂。工厂制造“事物”。单身人士意味着任何时候都只有0或正好有1个这样的“事物”。
如果您正在尝试制作一个合适的Singleton,那么在Java中以线程安全的方式执行此操作会非常麻烦。如果没有同步或其他线程安全对策,上面列出的代码在check-then-set代码周围有一个微妙的竞争条件来初始化ClientFactory实例变量。围绕这种竞争条件有两种方法。您选择哪种方式主要取决于通过ClientFactory构造函数的成本。我的构造函数通常是轻量级的,所以我走的是避免同步需要的路径。
public class ClientFactory {
private static final ClientFactory instance = new ClientFactory();
private ClientFactory() { }
public static ClientFactory getInstance() {
return instance;
}
}
如果你想在构造中“懒惰”,而不是在有人明确调用getInstance()之前建立,那么现在需要同步来避免竞争条件。
public class ClientFactory {
private static ClientFactory instance = null;
private ClientFactory() { }
public static synchronized ClientFactory getInstance() {
if ( instance == null ) {
instance = new ClientFactory();
}
return instance;
}
}
答案 4 :(得分:0)
ClientFactory是一个工厂,但既不是Singleton Factory,也不是线程安全的工厂。 在任何时候,当调用ClientFactory.getInstance()。getClinet()时,它将返回一个新的 例如,它不是绝对的Singleton Factory。如果我们修复这样的方法
private IClient iclient;
public IClient getClient() {
if ( iclient == null ){
iclient = new TestClient();
}
return iclient ;
}
然后工厂是一个单件工厂,但它不是线程安全的。 假设有多个线程调用getInstance,所有线程都会找到 客户端工厂实例为null,因此它们将分别构造实例, 问题与方法getClient()相同。
修复它很容易,你可以将这两个方法声明为同步。
首先,如果你真的想使用工厂parrtern,不要忘记隐藏客户端的构造函数
private TestClient(){
}