面试题答案
一键面试滥用场景
在某些场景下,系统中有多个模块可能会独立运行且互不干扰,每个模块都有自己的业务逻辑和数据状态,这种情况下如果为每个模块都使用单例模式,就可能造成资源浪费。比如,在一个电商系统中,订单模块和商品模块是相对独立的,若都使用单例模式,即使两个模块之间没有交互,单例对象也会一直占用内存资源,而实际上这两个模块可以独立实例化以节省资源。
解决方案
根据业务需求,合理判断是否真的需要单例。如果不需要单例模式的强一致性和全局唯一性,可以采用普通的实例化方式创建对象。若某些模块确实需要共享数据,可以考虑使用其他设计模式如享元模式,它与单例模式不同,享元模式注重对象的复用,通过共享对象来减少内存开销,而单例模式强调全局唯一实例。
代码示例
- 滥用单例模式的代码示例
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
// 模拟不同模块使用单例
class OrderModule {
private Singleton singleton;
public OrderModule() {
singleton = Singleton.getInstance();
}
}
class ProductModule {
private Singleton singleton;
public ProductModule() {
singleton = Singleton.getInstance();
}
}
- 采用普通实例化方式的改进示例
public class NormalObject {
public NormalObject() {}
}
class OrderModuleNew {
private NormalObject normalObject;
public OrderModuleNew() {
normalObject = new NormalObject();
}
}
class ProductModuleNew {
private NormalObject normalObject;
public ProductModuleNew() {
normalObject = new NormalObject();
}
}
- 享元模式示例(简单示意)
import java.util.HashMap;
import java.util.Map;
// 享元对象接口
interface Flyweight {
void operation();
}
// 具体享元对象
class ConcreteFlyweight implements Flyweight {
private String intrinsicState;
public ConcreteFlyweight(String state) {
this.intrinsicState = state;
}
@Override
public void operation() {
System.out.println("ConcreteFlyweight operation with intrinsic state: " + intrinsicState);
}
}
// 享元工厂
class FlyweightFactory {
private static Map<String, Flyweight> flyweights = new HashMap<>();
public static Flyweight getFlyweight(String key) {
if (!flyweights.containsKey(key)) {
flyweights.put(key, new ConcreteFlyweight(key));
}
return flyweights.get(key);
}
}
// 使用享元模式
class ModuleUsingFlyweight {
private Flyweight flyweight;
public ModuleUsingFlyweight(String key) {
flyweight = FlyweightFactory.getFlyweight(key);
}
public void doSomething() {
flyweight.operation();
}
}