简体   繁体   English

单态与单态

[英]Monostate vs. Singleton

What are the scenarios when one would use a Monostate pattern instead of singleton inorder to maintain a global object?什么情况下会使用单态模式而不是单例来维护全局对象?

Edit: I know what Singleton and Monostate patterns are.编辑:我知道单例模式和单态模式是什么。 Have also implemented Singleton in quite a few scenarios.在很多场景中也实现了 Singleton。 Just want to know the scenarios (case examples) where MonoState pattern needs to be implemented.只想知道需要实现 MonoState 模式的场景(案例)。

For eg.例如。 I need to maintain list of columns per screen in my windows forms app.我需要在我的 Windows 窗体应用程序中维护每个屏幕的列列表。 I could use a Singleton Dictionary in this case.在这种情况下,我可以使用单例字典。 However, I am storing a List in the static global var and I wanted to provide indexers (since I need to dynamically add new entry to the list if key is not present) where I could specify ScreenDetails.ScreenName as a key & get the ScreenDetails.ColumnsTable.但是,我将 List 存储在静态全局变量中,并且我想提供索引器(因为如果键不存在,我需要动态地将新条目添加到列表中),我可以将 ScreenDetails.ScreenName 指定为键并获取 ScreenDetails .ColumnsTable。 Since indexers can't operate on a static class I changed the pattern to Monostate.由于索引器无法对静态类进行操作,因此我将模式更改为 Monostate。

So I would like to know which other scenarios may compel a user to use Monostate instead of Singletons.所以我想知道哪些其他场景可能会迫使用户使用 Monostate 而不是 Singletons。

monostate and singleton are two faces of the same medal (global state): monostate 和 singleton 是同一个奖牌的两个面(全局状态):

  • monostate forces a behaviour (only one value along all class instances)单态强制一种行为(所有类实例中只有一个值)
  • singleton forces a structural constraint (only one instance)单例强制结构约束(只有一个实例)

singleton usage is not transparent单例使用不透明

ie: IE:

Singleton singleton = Singleton.getInstance();

monostate usage is transparent单态使用是透明的

ie: IE:
 MonoState m1 = new MonoState(); MonoState m2 = new MonoState(); // same internal state of m1 (eg static)

Here's what Robert C. Martin has to say about it: Singleton vs. Monostate (pdf)以下是Robert C. Martin对此的看法: Singleton vs. Monostate (pdf)

SINGLETON is best used when you have an existing class that you want to constrain through derivation, and you don't mind that everyone will have to call the instance() method to gain access. SINGLETON 最适用于您想要通过派生来约束现有类的情况,并且您不介意每个人都必须调用 instance() 方法才能获得访问权限。 Monostate is best used when you want the singular nature of the class to be transparent to the users, or when you want to employ polymorphic derivatives of the single object.当您希望类的单一性质对用户透明,或者当您希望使用单个对象的多态派生时,最好使用 Monostate。

At its base Monostate is just syntactic sugar around Singleton.在它的基础上,Monostate 只是 Singleton 周围的语法糖。 Where Monostate gets interesting is when you start subclassing, because the subclasses can decorate the shared state with different behavior.当您开始子类化时,Monostate 变得有趣,因为子类可以用不同的行为装饰共享状态。

A simple -- if somewhat contrived and not very efficient :) -- example:一个简单的——如果有点做作而且效率不高:)——例子:

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();
  }
}

Now what if we want indexed access?现在如果我们想要索引访问怎么办?

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));
  }
}

How about sorted keys?排序键怎么样?

public class SortedGlobalTable extends GlobalTable {

  @Override
  public Iterator <Key> iterator() {
    return Collections
      .unmodifiableSortedSet(new TreeSet<Key>(keySet())).iterator();
  }

}

Any time you need one or the other view of the data, you just instantiate the appropriate subclass.每当您需要数据的一个或另一个视图时,您只需实例化适当的子类。

Of course, whether global data is really a good idea in the first place is another question, but at least Monostate gives you more flexibility in how you use it.当然,首先全局数据是否真的是一个好主意是另一个问题,但至少 Monostate 让您在使用它时有了更大的灵活性。

Someone should just note that singletons and monostates are extremely dangerous patterns.有人应该注意到单例和单态是极其危险的模式。 They tend to get misused by lazy coders who don't want to have to think about the lifetime of the object they want to make into a singleton.他们往往会被懒惰的程序员滥用,他们不想考虑他们想要制作成单例的对象的生命周期。 They make testing more difficult and create inflexible systems that are tightly bound.它们使测试变得更加困难,并创建了紧密绑定的不灵活系统。

It's extremely rare to find a situation where a singleton or monostate is genuinely needed.真正需要单身或单态的情况极为罕见。 The prefered method of object collaboration is Dependency Injection.对象协作的首选方法是依赖注入。

Lots has been written about this:关于这个已经写了很多:

The difference between the two patterns is one of behavior vs. structure.两种模式之间的区别在于行为与结构之一。 The SINGLETON pattern enforces the structure of singularity. SINGLETON模式强制执行奇点结构。 It prevents any more than one instance from being created.它可以防止创建一个以上的实例。 Whereas MONOSTATE enforces the behavior of singularity without imposing structural constraints.MONOSTATE在不施加结构约束的情况下强制执行奇点行为。

Benefits of the SINGLETON SINGLETON 的好处

  • Applicable to any class.适用于任何班级。 You can change any class into a SINGLETON simply by making its constructors private and by adding the appropriate static functions and variable.您可以将任何类更改为 SINGLETON,只需将其构造函数设为私有并添加适当的静态函数和变量即可。
  • Can be created through derivation.可以通过派生来创建。 Given a class, you can create a subclass that is a SINGLETON.给定一个类,您可以创建一个 SINGLETON 的子类。
  • Lazy evaluation.懒惰的评价。 If the SINGLETON is never used, it is never created.如果从未使用过 SINGLETON,则永远不会创建它。

Costs of the SINGLETON SINGLETON的成本

  • Destruction is undefined.破坏是未定义的。 There is no good way to destroy or decommission a SINGLETON.没有很好的方法来销毁或停用 SINGLETON。 If you add a decommission method that nulls out the instance, other modules in the system may still be holding a reference to the SINGLETON instance.如果您添加使实例无效的停用方法,系统中的其他模块可能仍持有对 SINGLETON 实例的引用。 Subsequent calls to Instance will cause another instance to be created, causing two concurrent instances to exist.对 Instance 的后续调用将导致另一个实例被创建,从而导致两个并发实例存在。

  • Not inherited.不继承。 A class derived from a SINGLETON is not a singleton.从 SINGLETON 派生的类不是单例。 If it needs to be a SINGLETON, the static function, and variable need to be added to it.如果它需要是 SINGLETON,则需要添加静态函数和变量。

  • Efficiency.效率。 Each call to Instance invokes the if statement.对 Instance 的每次调用都会调用 if 语句。 For most of those calls, the if statement is useless.对于大多数这些调用,if 语句是无用的。

  • Nontransparent.不透明。 Users of a SINGLETON know that they are using a SINGLETON because they must invoke the Instance method. SINGLETON 的用户知道他们正在使用 SINGLETON,因为他们必须调用 Instance 方法。

Benefits of MONOSTATE MONOSTATE 的好处

  • Transparency.透明度。 Users of a MONOSTATE do not behave differently than users of a regular object. MONOSTATE 用户的行为与常规对象的用户没有什么不同。 The users do not need to know that the object is MONOSTATE.用户不需要知道对象是 MONOSTATE。

  • Derivability.可推导性。 Derivatives of a MONOSTATE are MONOSTATES.单态的衍生物是单态。 Indeed, all the derivatives of a MONOSTATE are part of the same MONOSTATE.事实上,一个 MONOSTATE 的所有衍生物都是同一个 MONOSTATE 的一部分。 They all share the same static variables.它们都共享相同的静态变量。

  • Polymorphism.多态性。 Since the methods of a MONOSTATE are not static, they can be overridden in a derivative.由于 MONOSTATE 的方法不是静态的,它们可以在派生中被覆盖。 Thus different derivatives can offer different behavior over the same set of static variables.因此,不同的导数可以在同一组静态变量上提供不同的行为。

  • Well-defined creation and destruction.定义明确的创造和毁灭。 The variables of a MONOSTATE, being static, have well-defined creation and destruction times. MONOSTATE 的变量是静态的,具有明确定义的创建和销毁时间。

Costs of MONOSTATE MONOSTATE 的费用

  • No conversion.没有转换。 A normal class cannot be converted into a MONOSTATE class through derivation.普通类不能通过派生转换为 MONOSTATE 类。

  • Efficiency.效率。 A MONOSTATE may go through many creations and destructions because it is a real object.一个 MONOSTATE 可能会经历许多创建和破坏,因为它是一个真实的对象。 These operations are often costly.这些操作通常成本高昂。

  • Presence.在场。 The variables of a MONOSTATE take up space, even if the MONOSTATE is never used. MONOSTATE 的变量会占用空间,即使从未使用过 MONOSTATE。

Agile Software Development, Principles, Patterns, and Practices Robert C. Martin敏捷软件开发、原则、模式和实践 Robert C. Martin

I think most of people have wrong understanding of monostate pattern.我认为大多数人对单态模式的理解是错误的。

These days I have read pages about category theory.这些天来,我阅读了有关范畴论的页面 In category theory, a singleton set is defined as a set only has one element.在范畴论中,单例集合被定义为只有一个元素的集合。 So there are many good feature for a singleton set, for example, you can create an element of a singleton set at any time and the element is always the same.所以单例集有很多好的特性,比如你可以随时创建一个单例集的元素,并且元素总是相同的。 In fact, that's what monostate should means.事实上,这就是单态应该意味着的。 You can create an instance of an monostate at any time and the instance is always the same.您可以随时创建单态的实例,并且该实例始终相同。

However, does the element really the same for our ordinary use of monostate?但是,对于我们普通使用的单态来说,元素真的一样吗? As we known, a element is defined by its interface, so interface of same element should always do the same thing and return same result.众所周知,一个元素是由它的接口定义的,所以同一个元素的接口应该总是做同样的事情并返回同样的结果。 So even though monostate don't have non-static member itselt, they are not the same.因此,即使 monostate 没有非静态成员 itelt,它们也不相同。 It has no good feature at all.它根本没有什么好的功能。

What is really monostate?什么是真正的单态? In fact, std::allocator is a good example.事实上, std::allocator就是一个很好的例子。 It use a global unique memory heap but define a monostate and all instance of std::allocator has same behavior.它使用全局唯一内存堆,但定义了一个单态,并且std::allocator的所有实例都具有相同的行为。 You can randomly create instance of std::allocator and use it.您可以随机创建std::allocator的实例并使用它。

What's more.更重要的是。 Does ordinary singleton pattern define a singleton set?普通单例模式是否定义了单例集? In fact, the singleton class itself is not a singleton set, but the pointer of reference of singleton set is singleton set.)其实单例类本身并不是单例集,但是单例集的引用指针是单例集。)

ordinary use of monostate and singleton that I'm talked in this answer:我在这个答案中谈到的单态和单态的普通使用:

class Singleton {
public:
    static Singleton& getInstance() {
        static Singleton instance;
        return instance;
    }
private:
    ~Singleton() = default;
};

class MonoState {
public:
    void setValue(int v) {
        _v = v;
    }
    int getValue() {
        return _v;
        // getValue may return different result at different time.
    }

private:
    static inline int _v;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM