Design patterns 什么时候应该使用单例模式而不是静态类?
在决定使用静态类还是静态类时,请列出设计注意事项。在这样做的过程中,你被迫将两者进行对比,因此,无论你能想出什么样的对比,都有助于展示你的思维过程!此外,每个面试官都喜欢看到说明性的例子 当单个类需要状态时。单例保持全局状态,静态类不保持全局状态 例如,在注册表类周围创建一个助手:如果您有可更改的配置单元(HKey Current User vs.HKey Local Machine),您可以:Design patterns 什么时候应该使用单例模式而不是静态类?,design-patterns,Design Patterns,在决定使用静态类还是静态类时,请列出设计注意事项。在这样做的过程中,你被迫将两者进行对比,因此,无论你能想出什么样的对比,都有助于展示你的思维过程!此外,每个面试官都喜欢看到说明性的例子 当单个类需要状态时。单例保持全局状态,静态类不保持全局状态 例如,在注册表类周围创建一个助手:如果您有可更改的配置单元(HKey Current User vs.HKey Local Machine),您可以: RegistryEditor editor = RegistryEditor.GetInstance
RegistryEditor editor = RegistryEditor.GetInstance();
editor.Hive = LocalMachine
现在,对该单例的任何进一步调用都将在本地机器配置单元上运行。否则,使用静态类,每次都必须指定本地机器配置单元,或者使用类似于
ReadSubkeyFromLocalMachine
的方法。我认为唯一的区别是语法:MySingleton.Current.Whatever()与MySingleton.Whatever()。正如大卫所提到的,无论哪种情况,国家最终都是“静态的”
编辑:伯里旅从迪格过来。。。不管怎样,我想到了一个需要单身汉的案子。静态类不能从基类继承,也不能实现接口(至少在.Net中不能)。所以,如果您需要此功能,那么必须使用单例。如果“静态类”指的是只有静态变量的类,那么它们实际上可以维护状态。我的理解是唯一的区别是你如何访问这个东西。例如:
MySingleton().getInstance().doSomething();
对
MySingleton.doSomething();
<> Py> MyStLon的内部结构将明显不同,但线程安全问题除外,它们对客户端代码的执行都是相同的。 < P>不应该使用单体(除非你考虑一个没有可变状态的类)。“静态类”应该没有可变状态,除了线程安全缓存等
几乎任何一个单独的例子显示了如何不去做它。
< P>如果一个单独的东西是你可以处理的,在它之后清理,你可以考虑它是一个有限的资源(即只有1个),你不需要所有的时间,并且在分配时有某种内存或资源成本。 与包含静态状态字段的静态类相比,使用单例时,清理代码看起来更自然但是,无论哪种方式,代码看起来都是一样的,因此如果您有更具体的原因询问,也许您应该详细说明。这两者可能非常相似,但请记住,真正的单例本身必须实例化(授予,一次)然后提供服务。返回
mysqli
实例的PHP数据库类并不是一个真正的单例(有些人称之为单例),因为它返回的是另一个类的实例,而不是将实例作为静态成员的类的实例
因此,如果您正在编写一个新类,并且计划在代码中只允许一个实例,那么您不妨将其作为一个单例来编写。可以将其视为编写一个简单的jane类并添加到其中以满足单一实例化需求。如果您使用的是无法修改的其他类(如
mysqli
),则应该使用静态类(即使您没有在其定义前面加上关键字)。单例更灵活,当您希望实例方法根据某些上下文返回Singleton类型的不同具体子类时,这非常有用。静态类不能作为参数传递;单例实例可以是。正如其他答案中提到的,注意静态类的线程问题
rp单例可以有构造函数和析构函数。根据您的语言,构造函数可能在第一次使用singleton时自动调用,如果根本不使用singleton,则永远不会调用。静态类不会有这样的自动初始化 一旦获得对单例对象的引用,它就可以像任何其他对象一样使用。如果前面存储了对单例的引用,则客户端代码甚至可能不需要知道其使用单例:
Foo foo = Foo.getInstance();
doSomeWork(foo); // doSomeWork wont even know Foo is a singleton
当您选择放弃单例模式而选择真正的模式(如IoC)时,这显然会使事情变得更容易。当您需要在运行时计算一些您可能在编译时计算的东西时,如查找表,请使用单例模式。将单例想象为一种服务。它是一个提供特定功能集的对象。例如
ObjectFactory.getInstance().makeObject();
对象工厂是执行特定服务的对象
相反,一个充满静态方法的类是您可能想要执行的操作的集合,组织在一个相关的组(类)中。例如
这里的StringUtils示例是可以应用于任何地方的功能集合。singleton factory对象是一种特定类型的对象,具有明确的责任,可以在需要时创建和传递。关于这个问题,我最喜欢的讨论之一是(原始站点已关闭,现在链接到。) 要总结单身人士的灵活性优势,请执行以下操作:
- 单件可以很容易地转换 进工厂
- 一个单身汉可以很容易地 修改为返回不同的 子类
- 这可以产生一个更易于维护的应用程序
/**
* Grotty static semaphore
**/
public static class Ugly {
private static int count;
public synchronized static void increment(){
count++;
}
public synchronized static void decrement(){
count--;
if( count<0 ) {
count=0;
}
}
public synchronized static boolean isClear(){
return count==0;
}
}
/**
*Grotty静态信号量
**/
/**
* Grotty static semaphore
**/
public static class Ugly {
private static int count;
public synchronized static void increment(){
count++;
}
public synchronized static void decrement(){
count--;
if( count<0 ) {
count=0;
}
}
public synchronized static boolean isClear(){
return count==0;
}
}
/**
* Grotty static semaphore
**/
public static class LessUgly {
private static LessUgly instance;
private int count;
private LessUgly(){
}
public static synchronized getInstance(){
if( instance==null){
instance = new LessUgly();
}
return instance;
}
public synchronized void increment(){
count++;
}
public synchronized void decrement(){
count--;
if( count<0 ) {
count=0;
}
}
public synchronized boolean isClear(){
return count==0;
}
}
public static class LessUgly {
private static Hashtable<String,LessUgly> session;
private static FIFO<LessUgly> freePool = new FIFO<LessUgly>();
private static final POOL_SIZE=5;
private int count;
private LessUgly(){
}
public static synchronized getInstance(){
if( session==null){
session = new Hashtable<String,LessUgly>(POOL_SIZE);
for( int i=0; i < POOL_SIZE; i++){
LessUgly instance = new LessUgly();
freePool.add( instance)
}
}
LessUgly instance = session.get( Session.getSessionID());
if( instance == null){
instance = freePool.read();
}
if( instance==null){
// TODO search sessions for expired ones. Return spares to the freePool.
//FIXME took too long to write example in blog editor.
}
return instance;
}
MyStaticClass.GetInstance().DoSomething();
MyStaticClass.DoSomething();
var svc = new MyComplexServce(MyStaticClass.GetInstance());