为了维护全局对象,使用Monostate模式而不是singleton的情况是什么?
编辑: 我知道Singleton和Monostate模式是什么。在很多场景中也实现了Singleton。只想了解需要实现MonoState模式的场景(案例)。
例如。我需要在我的Windows窗体应用程序中维护每个屏幕的列列表。在这种情况下,我可以使用Singleton Dictionary。但是,我在静态全局var中存储了一个List,我想提供索引器(因为我需要动态地将新条目添加到列表中,如果key不存在),我可以将ScreenDetails.ScreenName指定为键和&获取ScreenDetails.ColumnsTable。由于索引器无法在静态类上操作,因此我将模式更改为Monostate。
所以我想知道哪些其他场景可能迫使用户使用Monostate而不是Singletons。
答案 0 :(得分:67)
monostate和singleton是同一枚牌的两面(全局状态):
即:
Singleton singleton = Singleton.getInstance();
即:
MonoState m1 = new MonoState();
MonoState m2 = new MonoState(); // same state of m1
答案 1 :(得分:41)
以下是 Robert C. Martin 对此所说的话:Singleton vs. Monostate (pdf)
当你有一个想要约束的现有类时,最好使用SINGLETON 通过派生,你不介意每个人都必须调用实例() 获取访问权限的方法。 Monostate最适合用于你想要的单一性质 class对用户透明,或者当你想使用多态衍生物时 单个对象。
答案 2 :(得分:17)
在它的基础Monostate只是Singleton周围的语法糖。 Monostate变得有趣的地方是你开始子类化时,因为子类可以用不同的行为来装饰共享状态。
一个简单的 - 如果有点做作,效率不高:) - 例如:
public class GlobalTable implements Iterable<Key> {
/** Shared state -- private */
private static final Map<Key, Value> MAP = new LinkedHashMap<Key, Value>();
/** Public final accessor */
public final Value get(Key key) {
return MAP.get(key);
}
/** Public final accessor */
public final boolean put(Key key, Value value) {
return MAP.put(key);
}
/** Protected final accessor -- subclasses can use this to access
the internal shared state */
protected final Set<Key> keySet() {
return MAP.keySet();
}
/** Virtual -- subclasses can override for different behavior */
public Iterator<Key> iterator() {
return Collections.unmodifiableSet(MAP.keySet()).iterator();
}
}
现在如果我们想要索引访问怎么办?
public class IndexedGlobalTable extends GlobalTable {
public List<Key> getKeysAsList() {
return Collections.unmodifiableList(new ArrayList<Key>(keySet()));
}
public Key getKeyAt(int index) {
return getKeysAsList().get(index);
}
public Value getValueAt(int index) {
return get(getKeyAt(index));
}
}
排序键怎么样?
public class SortedGlobalTable extends GlobalTable {
@Override
public Iterator <Key> iterator() {
return Collections
.unmodifiableSortedSet(new TreeSet<Key>(keySet())).iterator();
}
}
只要您需要一个或另一个数据视图,就可以实例化相应的子类。
当然,首先,全球数据是否真的是一个好主意是另一个问题,但至少Monostate为您提供了更灵活的使用方式。
答案 3 :(得分:8)
有人应该注意单身人士和单身人士是非常危险的模式。他们倾向于被懒惰的程序员误用,他们不想考虑他们想要成为单身人士的对象的生命周期。它们使测试更加困难,并创建了紧密绑定的不灵活系统。
找到真正需要单身人士或单人身份的情况极为罕见。对象协作的首选方法是依赖注入。
有很多人写过:
答案 4 :(得分:1)
两种模式之间的区别在于行为与结构之间的区别。 SINGLETON 模式强制执行奇点结构。它可以防止创建任何多个实例。而 MONOSTATE 强制执行奇点行为而不强加结构约束。
SINGLETON的好处
SINGLETON的费用
销毁未定义。没有好的方法来摧毁或 退役一个SINGLETON。如果添加一个使实例为空的decommission方法,则系统中的其他模块可能仍然持有a 引用SINGLETON实例。对Instance的后续调用将导致创建另一个实例,从而导致存在两个并发实例。
不继承。从SINGLETON派生的类不是单例。 如果它需要是SINGLETON,静态函数和变量需要 加入它。
效率。每次调用Instance都会调用if语句。对于大多数 在那些电话中,if语句没用。
非透明。 SINGLETON的用户知道他们正在使用 SINGLETON因为他们必须调用Instance方法。
MONOSTATE的好处
透明度。 MONOSTATE的用户行为不同于 常规对象的用户。用户不需要知道 对象是MONOSTATE。
导性。 MONOSTATE的衍生物是MONOSTATES。确实,所有 MONOSTATE的衍生物是同一个MONOSTATE的一部分。他们 所有人都拥有相同的静态变量。
多态性。由于MONOSTATE的方法不是静态的,所以它们 可以在衍生物中覆盖。因此不同的衍生物可以 在同一组静态变量上提供不同的行为。
明确定义的创建和破坏。 MONOSTATE的变量, 是静态的,具有明确定义的创建和破坏时间。
MONOSTATE的费用
无转换。普通类无法转换为MONOSTATE 通过推导来分类。
效率。 MONOSTATE可以经历许多创作和 破坏,因为它是一个真实的对象。这些操作经常是 昂贵的。
存在。 MONOSTATE的变量占用空间,即使是 从未使用过MONOSTATE。
敏捷软件开发,原则,模式和实践Robert C. Martin