由于常见的单例模式,饿汉式单例和懒汉式单例,构造方法都私有了,因此不能被继承.
最近在开发中遇到问题了,恰好需要继承单例类.找资料才找到了这个解决办法---登记式单例.
登记式单例类是为了克服饿汉式单例类及懒汉式单例类均不可继承的缺点而设计的。当单例类需要被继承时适用.
代码清单3:登记式单例类
import java.util.HashMap; private List<Player> plsyers=new linkedList<Player>();
public void remove(Player player){ players.remove(Player); } public List<Player> getPlayers(){ return players; } } |
它的子类RegSingletonChild 需要父类的帮助才能实例化。下图所示是登记式单例类子类的一个例子。图中的关系表明,此类是由父类将子类实例化的。
下面是子类的源代码。
代码清单4:登记式单例类的子类
import java.util.HashMap; public void test(){ int a= getPlayers().size(); int b =RegSingleton .getInstance().getPlayers().size(); } |
在GoF 原始的例子中,并没有getInstance() 方法,这样得到子类必须调用的getInstance(String name)方法并传入子类的名字,因此很不方便。在登记式单例类子类的例子里,加入了getInstance() 方法,这样做的好处是RegSingletonChild 可以通过这个方法,返还自已的实例。而这样做的缺点是,由于数据类型不同,无法在RegSingleton 提供这样一个方法。由于子类必须允许父类以构造方法调用产生实例,因此,它的构造方法必须是公开的。这样一来,就等于允许了以这样方式产生实例而不在父类的登 记中。这是登记式单例类的一个缺点。
在使用过程中还有另一个发现,当时我是这样做的.
在RegSingleton的players中添加了几个player.然后调用remobe(player)方法删除了一个元素
最后在RegSingletonChild中调用test()方法,你会发现 a 和 b 是不等的?
子类拿父类的属性和父类自己拿到的 为什么会不一样呢?父类不是单例的吗?
最后我的结论是这样的:父类是单例,子类继承父类后子类是另一个单例(这时的子类并不会因为父类是单例而拿到的还是同一个单例对象了).其实是产生了两个相互依赖的单例;单独的操作父类或者子类是单例的,所以就会出现操作了父类的属性(remove(player)),然后在子类里面去拿同一属性时产生不同的结果(getPlayers()).这时父类的players和子类的players应该是两个不同的集合.
不知道我的理解是否有错,有在行的朋友欢迎讨论.