我在下面有一个Singleton类继承的示例代码。但是,如果此代码可能出现任何隐藏问题,我也不会预料到。有人可以分析并给我一个提示吗?
interface ChairIF {
public int getLeg();
public void test();
}
class ChairImpl implements ChairIF {
private static final Lock lock = new ReentrantLock();
private static ChairIF instance = null;
public static ChairIF getInstance(String clazzName) {
//get class by clazzName
Class clazz = null;
try {
clazz = Class.forName(clazzName);
} catch (ClassNotFoundException ex) {
lock.lock();
try {
if (instance == null) {
instance = new ChairImpl();
}
} finally {
lock.unlock();
}
}
//init singleton instance of clazzName
if (instance == null) {
lock.lock();
try {
if (instance == null) {
instance = (ChairIF) clazz.newInstance();
} else {
if (instance.getClass() != clazz) {
instance = (ChairIF) clazz.newInstance();
}
}
} catch (Exception ex) {
instance = new ChairImpl();
} finally {
lock.unlock();
}
} else {
lock.lock();
try {
if (!instance.getClass().getName().equals(clazz.getName())) {
instance = (ChairIF) clazz.newInstance();
}
} catch (Exception ex) {
instance = new ChairImpl();
} finally {
lock.unlock();
}
}
return instance;
}
public int getLeg() {
return 4;
}
public void test() {
throw new UnsupportedOperationException();
}
}
class ThreeLegChair extends ChairImpl {
public ThreeLegChair() {}
public int getLeg() {
return 3;
}
public void test() {
int i = 0;
while(i < 10000) {
System.out.println("i: " + i++);
}
}
}
class NoLegChair extends ChairImpl {
public NoLegChair() {}
public int getLeg() {
return 0;
}
public void test() {
int j = 0;
while(j < 5000) {
System.out.println("j: " + j++);
}
}
}
public class Test {
public static void main(String[] args) {
System.out.println(ChairImpl.getInstance("ThreeLegChair").getLeg());
System.out.println(ChairImpl.getInstance("NoLegChair").getLeg());
/***
TODO: build logic to run 2 test() simultaneously.
ChairImpl.getInstance("ThreeLegChair").test();
ChairImpl.getInstance("NoLegChair").test();
****/
}
}
如您所见,我确实在2个子类中添加了一些测试代码。 ThreeLegChair将从0循环到10000并将其打印出来。 NoLegChair仅从0循环到5000并打印出来。
我在控制台日志中得到的结果是正确的。 ThreeLegChair从0到10000打印i.NoLegChair从0到5000打印j。
请与我分享你的想法:)
答案 0 :(得分:2)
使用私有构造函数的概念实现单例模式,即类本身负责创建类的单个实例(单例)并防止其他类创建对象。
现在构造函数是private
,你不能在第一个地方继承单例类。 在您的情况下,我没有看到私有构造函数,这使得它很容易从访问它的其他类创建对象。
单身模式示例:
enum SingletonEnum { SINGLE_INSTANCE; public void doStuff() { System.out.println("Singleton using Enum"); } }
class SingletonClass {
private static SingletonClass singleInstance; private SingletonClass() { // deny access to other classes } // The object creation will be delayed until getInstance method is called. public static SingletonClass getInstance() { if (null == singleInstance) { // Create only once singleInstance = new SingletonClass(); } return singleInstance; } }
但是,上述示例可能无法保证多线程环境中的单例行为。建议使用double checked locking机制来确保您已创建此类的单个实例。
答案 1 :(得分:1)
您发布的代码不是单例模式的实现。
很简单,你可以这样做:
ChairImpl ci = new ChairImpl();
并尽可能多地实例化。
实现单例模式的传统方法是使构造函数为私有,具有保存类的单个实例的私有静态字段,以及实例化该实例或返回现有实例的静态getInstance()
方法一。使线程安全涉及声明它synchronized
或使用锁定方案。
私有构造函数位使得无法继承它。
那就是说,在Java中,首选的方法是使用enum
免费提供所有硬件:
public enum MySingleton {
INSTANCE;
public int getLeg() {
return 4;
}
}
并使用as:
MySingleton ms = MySingleton.INSTANCE;
int leg = ms.getLeg();
答案 2 :(得分:0)
单身人士通常拥有私人建设者。你的班级没有遵循正确的单身人士模式。否则你不会继承你的单身人士。