Borg 패턴 이 Singleton 패턴 보다 나은 이유는 무엇 입니까?
나는 그들이 다른 결과를 낳지 않기 때문에 묻습니다.
보그 :
class Borg:
__shared_state = {}
# init internal state variables here
__register = {}
def __init__(self):
self.__dict__ = self.__shared_state
if not self.__register:
self._init_default_register()
하나씩 일어나는 것:
class Singleton:
def __init__(self):
# init internal state variables here
self.__register = {}
self._init_default_register()
# singleton mechanics external to class, for example this in the module
Singleton = Singleton()
여기에 표시하고 싶은 것은 Borg 또는 Singleton으로 구현 된 서비스 객체가 사소하지 않은 내부 상태를 가지고 있다는 것입니다 (이를 기반으로하는 일부 서비스를 제공합니다). 장난).
그리고이 상태는 초기화되어야합니다. 여기서 Singleton 구현은 더 간단합니다. init 를 전역 상태의 설정으로 취급 하기 때문입니다. Borg 개체가 자체적으로 업데이트해야하는지 확인하기 위해 내부 상태를 쿼리해야하는 것이 어색합니다.
내부 상태가 많을수록 악화됩니다. 예를 들어, 객체가 레지스터를 디스크에 저장하기 위해 응용 프로그램의 분해 신호를 수신해야하는 경우 해당 등록도 한 번만 수행해야하며 Singleton을 사용하면 더 쉽습니다.
답변
보그가 다른 진짜 이유는 서브 클래 싱에 있습니다.
보그를 서브 클래 싱하는 경우 해당 서브 클래스의 공유 상태를 명시 적으로 재정의하지 않는 한, 서브 클래스의 객체는 부모 클래스 객체와 동일한 상태를 갖습니다. 싱글 톤 패턴의 각 하위 클래스에는 자체 상태가 있으므로 다른 객체를 생성합니다.
또한 단일 패턴에서 객체는 상태뿐만 아니라 실제로 동일합니다 (상태가 실제로 중요한 유일한 것임에도 불구하고).
답변
파이썬에서 어디에서나 접근 할 수있는 고유 한 “객체”를 원한다면 Unique
정적 속성, @staticmethod
s 및 @classmethod
s 만 포함 하는 클래스 를 생성하십시오 . 고유 패턴이라고 부를 수 있습니다. 여기에서 3 가지 패턴을 구현하고 비교합니다.
독특한
#Unique Pattern
class Unique:
#Define some static variables here
x = 1
@classmethod
def init(cls):
#Define any computation performed when assigning to a "new" object
return cls
하나씩 일어나는 것
#Singleton Pattern
class Singleton:
__single = None
def __init__(self):
if not Singleton.__single:
#Your definitions here
self.x = 1
else:
raise RuntimeError('A Singleton already exists')
@classmethod
def getInstance(cls):
if not cls.__single:
cls.__single = Singleton()
return cls.__single
보그
#Borg Pattern
class Borg:
__monostate = None
def __init__(self):
if not Borg.__monostate:
Borg.__monostate = self.__dict__
#Your definitions here
self.x = 1
else:
self.__dict__ = Borg.__monostate
테스트
#SINGLETON
print "\nSINGLETON\n"
A = Singleton.getInstance()
B = Singleton.getInstance()
print "At first B.x = {} and A.x = {}".format(B.x,A.x)
A.x = 2
print "After A.x = 2"
print "Now both B.x = {} and A.x = {}\n".format(B.x,A.x)
print "Are A and B the same object? Answer: {}".format(id(A)==id(B))
#BORG
print "\nBORG\n"
A = Borg()
B = Borg()
print "At first B.x = {} and A.x = {}".format(B.x,A.x)
A.x = 2
print "After A.x = 2"
print "Now both B.x = {} and A.x = {}\n".format(B.x,A.x)
print "Are A and B the same object? Answer: {}".format(id(A)==id(B))
#UNIQUE
print "\nUNIQUE\n"
A = Unique.init()
B = Unique.init()
print "At first B.x = {} and A.x = {}".format(B.x,A.x)
A.x = 2
print "After A.x = 2"
print "Now both B.x = {} and A.x = {}\n".format(B.x,A.x)
print "Are A and B the same object? Answer: {}".format(id(A)==id(B))
산출:
하나씩 일어나는 것
At first B.x = 1 and A.x = 1 After A.x = 2 Now both B.x = 2 and A.x = 2 Are A and B the same object? Answer: True BORG At first B.x = 1 and A.x = 1 After A.x = 2 Now both B.x = 2 and A.x = 2 Are A and B the same object? Answer: False UNIQUE At first B.x = 1 and A.x = 1 After A.x = 2 Now both B.x = 2 and A.x = 2 Are A and B the same object? Answer: True
제 생각에는 Unique 구현이 가장 쉽고 Borg와 마지막으로 Singleton이 정의에 필요한 두 가지 기능이 있습니다.
답변
그렇지 않습니다. 일반적으로 권장되지 않는 것은 파이썬에서 다음과 같은 패턴입니다.
class Singleton(object):
_instance = None
def __init__(self, ...):
...
@classmethod
def instance(cls):
if cls._instance is None:
cls._instance = cls(...)
return cls._instance
생성자 대신 인스턴스를 가져 오기 위해 클래스 메서드를 사용합니다. 파이썬의 메타 프로그래밍은 훨씬 더 나은 방법을 허용합니다. 예를 들어 Wikipedia에있는 것 :
class Singleton(type):
def __init__(cls, name, bases, dict):
super(Singleton, cls).__init__(name, bases, dict)
cls.instance = None
def __call__(cls, *args, **kw):
if cls.instance is None:
cls.instance = super(Singleton, cls).__call__(*args, **kw)
return cls.instance
class MyClass(object):
__metaclass__ = Singleton
print MyClass()
print MyClass()
답변
클래스는 기본적으로 객체의 내부 상태에 액세스 (읽기 / 쓰기)하는 방법을 설명합니다.
싱글 톤 패턴에서는 단일 클래스 만 가질 수 있습니다. 즉, 모든 객체가 공유 상태에 대해 동일한 액세스 포인트를 제공합니다. 즉, 확장 API를 제공해야하는 경우 단일 항목을 감싸는 래퍼를 작성해야합니다.
보그 패턴에서 기본 “보그”클래스를 확장 할 수 있으므로 취향에 맞게 API를 더 편리하게 확장 할 수 있습니다.
답변
실제로 차이가있는 몇 안되는 경우에만 더 좋습니다. 당신이 하위 클래스를 할 때처럼. Borg 패턴은 매우 드문 경우입니다. 저는 10 년 동안 Python 프로그래밍에서 실제로 필요하지 않았습니다.
답변
또한 Borg와 유사한 패턴을 사용하면 클래스 사용자가 상태를 공유하거나 별도의 인스턴스를 만들 것인지 선택할 수 있습니다. (좋은 생각인지 아닌지는 별도의 주제입니다)
class MayBeBorg:
__monostate = None
def __init__(self, shared_state=True, ..):
if shared_state:
if not MayBeBorg.__monostate:
MayBeBorg.__monostate = self.__dict__
else:
self.__dict__ = MayBeBorg.__monostate
return
self.wings = ..
self.beak = ..