案例研究:Singleton类继承 - 好还是坏?

时间:2014-01-10 07:07:37

标签: java inheritance singleton

我在下面有一个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。

请与我分享你的想法:)

3 个答案:

答案 0 :(得分:2)

使用私有构造函数的概念实现单例模式,即类本身负责创建类的单个实例(单例)并防止其他类创建对象。

现在构造函数是private你不能在第一个地方继承单例类在您的情况下,我没有看到私有构造函数,这使得它很容易从访问它的其他类创建对象。

单身模式示例:

  • 使用Java中的枚举
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)

单身人士通常拥有私人建设者。你的班级没有遵循正确的单身人士模式。否则你不会继承你的单身人士。

相关问题