IT박스

GOF 싱글 톤 패턴에 대한 실행 가능한 대안이 있습니까?

itboxs 2020. 9. 7. 07:56
반응형

GOF 싱글 톤 패턴에 대한 실행 가능한 대안이 있습니까?


현실을 직시하자. 싱글 톤 패턴은 매우 논쟁 에 무리 프로그래머와 주제 모두 울타리의 측면. Singleton이 더 이상 영광스러운 전역 변수라고 느끼는 사람들과 패턴으로 맹세하고 그것을 끊임없이 사용하는 사람들이 있습니다. 그러나 나는 싱글 톤 논쟁 이 내 질문의 핵심에 놓여있는 것을 원하지 않습니다 . 누구나 줄다리기를하여 전투를 벌일 수 있으며 내가 관심을 갖는 모든 것을 누가이기는지 볼 수 있습니다. 제가 말하려는 것은 정답이 하나 있다고 믿지 않으며 의도적으로 당파 적 논쟁을 불러 일으키는 것도 아닙니다. 나는 질문을 할 때 단순히 단일 대안에 관심이 있습니다 .

GOF 싱글 톤 패턴에 대한 특정 대안이 있습니까?

예를 들어, 과거에 싱글 톤 패턴을 여러 번 사용했을 때 저는 단순히 하나 또는 여러 변수의 상태 / 값을 보존하는 데 관심이 있습니다. 그러나 변수의 상태 / 값은 단일 패턴을 사용하는 대신 정적 변수사용하여 클래스의 각 인스턴스화 사이에 보존 될 수 있습니다 .

다른 아이디어가 있습니까?

편집 : "싱글 톤을 올바르게 사용하는 방법"에 대한 또 다른 게시물이되기를 원하지 않습니다. 다시 말하지만, 나는 그것을 피할 방법을 찾고 있습니다. 재미로 알았지? 나는 당신의 최고의 영화 예고편 목소리로 순수하게 학문적 인 질문을하고있는 것 같아요. "싱글 톤이없는 평행 우주에서 우리는 무엇을 할 수 있을까요?"


" Patterns I Hate "의 Alex Miller 는 다음을 인용합니다.

"싱글 톤이 답처럼 보일 때 종종 다음이 더 현명하다는 것을 알게됩니다.

  1. 인터페이스 및 싱글 톤의 기본 구현 생성
  2. 시스템의 "상단"에 기본 구현의 단일 인스턴스를 생성합니다. 이것은 Spring 구성 또는 코드에 있거나 시스템에 따라 다양한 방식으로 정의 될 수 있습니다.
  3. 필요한 각 구성 요소에 단일 인스턴스 전달 (종속성 주입)

Singleton을 해결하는 적절한 방법을 이해하려면 Singleton (및 일반적으로 전역 상태)의 문제점을 이해해야합니다.

싱글 톤은 종속성을 숨 깁니다.

그게 왜 중요할까요?

종속성을 숨기면 커플 링 양을 추적하지 못하는 경향이 있기 때문입니다.

당신은

void purchaseLaptop(String creditCardNumber, int price){
  CreditCardProcessor.getInstance().debit(creditCardNumber, amount);
  Cart.getInstance().addLaptop();
}

보다 간단합니다

void purchaseLaptop(CreditCardProcessor creditCardProcessor, Cart cart, 
                    String creditCardNumber, int price){
  creditCardProcessor.debit(creditCardNumber, amount);
  cart.addLaptop();
}

하지만 적어도 두 번째 API는 메소드의 공동 작업자가 무엇인지 정확히 알려줍니다.

따라서 Singleton을 해결하는 방법은 정적 변수 또는 서비스 로케이터를 사용하는 것이 아니라 Singleton 클래스를 인스턴스로 변경하는 것입니다. IoC 프레임 워크를 사용하여이를 처리하거나 수동으로 수행 할 수 있지만 중요한 것은 전역 상태를 제거하고 종속성 및 공동 작업을 명시 적으로 만드는 것입니다.


내가 찾은 최고의 솔루션은 팩토리 패턴을 사용하여 클래스의 인스턴스를 구성하는 것입니다. 패턴을 사용하여 다음을 수행 할 수 있습니다 확신 을 사용하는 객체간에 공유되는 클래스의 하나의 인스턴스 만이 있음.

I though it would be complicated to manage, but after reading this blog post "Where Have All the Singletons Gone?", it seems so natural. And as an aside, it helps a lot with isolating your unit tests.

In summary, what you need to do? Whenever an object depends on another, it will receive an instance of it only through its constructor (no new keyword in your class).

class NeedyClass {

    private ExSingletonClass exSingleton;

    public NeedyClass(ExSingletonClass exSingleton){
        this.exSingleton = exSingleton;
    }

    // Here goes some code that uses the exSingleton object
}

And then, the factory.

class FactoryOfNeedy {

    private ExSingletonClass exSingleton;

    public FactoryOfNeedy() {
        this.exSingleton = new ExSingletonClass();
    }

    public NeedyClass buildNeedy() {
        return new NeedyClass(this.exSingleton);
    }
}

As you will instantiate your factory only once, there will be a single instantiation of exSingleton. Every time you call buildNeedy, the new instance of NeedyClass will be bundled with exSingleton.

I hope this helps. Please point out any mistakes.


Spring or any other IoC-Container does a reasonably good job in that. Since the classes are created and managed outside the app itself, the container can make simple classes singletons and inject them where needed.


You shouldn't have to go out of your way to avoid any pattern. The use of a pattern is either a design decision or a natural fit (it just falls into place). When you are designing a system, you have a choice to either use a pattern or not use the pattern. However, you shouldn't go out of your way to avoid anything that is ultimately a design choice.

I don't avoid the Singleton Pattern. Either it's appropriate and I use it or it's not appropriate and I don't use it. I believe that it is as simple as that.

The appropriateness (or lack thereof) of the Singleton depends on the situation. It's a design decision that must be made and the consequences of that decision must be understood (and documented).


The singleton pattern exists because there are situations when a single object is needed to provide a set of services.

Even if this is the case I still consider the approach of creating singletons by using a global static field/property representing the instance, inappropriate. It's inappropriate because it create a dependency in the code between the static field and the object not, the services the object provides.

So instead of the classic, singleton pattern, I recommend to use the service 'like' pattern with serviced containers, where instead of using your singleton through a static field, you obtain a reference to it through a a method requesting the type of service required.

*pseudocode* currentContainer.GetServiceByObjectType(singletonType)
//Under the covers the object might be a singleton, but this is hidden to the consumer.

instead of single global

*pseudocode* singletonType.Instance

This way when you want to change type of an object from singleton to something else, you'll have and easy time doing it. Also as an and added benefit you don't have to pass around allot of object instances to every method.

Also see Inversion of Control, the idea is that by exposing singletons directly to the consumer, you create a dependency between the consumer and the object instance, not the object services provided by the object.

My opinion is to hide the use of the singleton pattern whenever possible, because it is not always possible to avoid it, or desirable.


Monostate (described in Robert C. Martin's Agile Software Development) is an alternative to singleton. In this pattern the class's data are all static but the getters/setters are non-static.

For example:

public class MonoStateExample
{
    private static int x;

    public int getX()
    {
        return x;
    }

    public void setX(int xVal)
    {
        x = xVal;
    }
}

public class MonoDriver
{
    public static void main(String args[])
    {
        MonoStateExample m1 = new MonoStateExample();
        m1.setX(10);

        MonoStateExample m2 = new MonoStateExample();
        if(m1.getX() == m2.getX())
        {
            //singleton behavior
        }
    }
}

Monostate has similar behavior to singleton but does so in a way where the programmer is not necessarily aware of the fact that a singleton is being used.


If you're using a Singleton to represent a single data object, you could instead pass a data object around as a method parameter.

(although, I would argue this is the wrong way to use a Singleton in the first place)


If your issue is that you want to keep state, you want a MumbleManager class. Before you start working with a system, your client creates a MumbleManager, where Mumble is the name of the system. State is retained through that. Chances are your MumbleManager will contain a property bag which holds your state.

This type of style feels very C-like and not very object like - you'll find that objects that define your system will all have a reference to the same MumbleManager.


Use a plain object and a factory object. The factory is responsible for policing the instance and the plain object details only with the configuration information (it contains for example) and behaviour.


Actually if you design right from scratch on avoiding Singeltons, you may not have to work around not using Singletons by using static variables. When using static variables, you are also creating a Singleton more or less, the only difference is you are creating different object instances, however internally they all behave as if they were using a Singleton.

Can you maybe give a detailed example where you use a Singleton or where a Singleton is currently used and you are trying to avoid using it? This could help people to find a more fancy solution how the situation could be handled without a Singleton at all.

BTW, I personally have no problems with Singletons and I can't understand the problems other people have regarding Singletons. I see nothing bad about them. That is, if you are not abusing them. Every useful technique can be abused and if being abused, it will lead to negative results. Another technique that is commonly misused is inheritance. Still nobody would say inheritance is something bad just because some people horribly abuse it.


Personally for me а much more sensible way to implement something that behaves like singleton is to use fully static class(static members , static methods , static properties). Most of the time I implement it in this way (I can not think of any behaviour differences from user point of view)


I think the best place to police the singleton is at the class design level. At this stage, you should be able to map out the interactions between classes and see if something absolutely, definitely requires that only 1 instance of this class is ever in existence at any time of the applications life.

If that is the case, then you have a singleton. If you are throwing singletons in as a convenience during coding then you should really be revisiting your design and also stop coding said singletons :)

And yes, 'police' is the word I meant here rather than 'avoid'. The singleton isn't something to be avoided (in the same way that goto and global variables aren't something to be avoided). Instead, you should be monitoring it's use and ensuring that it is the best method to get what you want done effectively.


I use singleton mostly as "methods container", with no state at all. If I need to share these methods with many classes and want to avoid the burden of instantiation and initialization I create a context/session and initialize all the classes there; everything which refers to the session has also access to the "singleton" thereby contained.


Having not programmed in an intensely object-oriented environment (e.g. Java), I'm not completely up on the intricacies of the discussion. But I have implemented a singleton in PHP 4. I did it as a way of creating a 'black-box' database handler that automatically initialized and didn't have to be passed up and down function calls in an incomplete and somewhat broken framework.

Having read some links of singleton patterns, I'm not completely sure I would implement it in quite the same way again. What was really needed was multiple objects with shared storage (e.g. the actual database handle) and this is pretty much what my call turned into.

Like most patterns and algorithms, using a singleton 'just because it's cool' is The Wrong Thing To Do. I needed a truly 'black-box' call that happened to look a lot like a singleton. And IMO that's the way to tackle the question: be aware of the pattern, but also look at it's wider scope and at what level it's instance needs to be unique.


What do you mean, what are my techniques to avoid it?

To "avoid" it, that implies that there are many situations that I come across in which the singleton pattern is a naturally good fit, and hence that I have to take some measures to defuse these situations.

But there are not. I don't have to avoid the singleton pattern. It simply doesn't arise.

참고URL : https://stackoverflow.com/questions/162042/are-there-any-viable-alternatives-to-the-gof-singleton-pattern

반응형