Borg 패턴이 Python의 Singleton 패턴보다 나은 이유
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
생성자 대신 인스턴스를 가져 오기 위해 클래스 메서드를 사용합니다. Python의 메타 프로그래밍은 훨씬 더 나은 방법을 허용합니다. 예를 들어 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()
클래스는 기본적으로 객체의 내부 상태에 액세스 (읽기 / 쓰기)하는 방법을 설명합니다.
In the singleton pattern you can only have a single class, i.e. all your objects will give you the same access points to the shared state. This means that if you have to provide an extended API, you will need to write a wrapper, wrapping around the singleton
In the borg pattern you are able to extend the base "borg" class, and thereby more conveniently extend the API for your taste.
It's only better in those few cases where you actually have a difference. Like when you subclass. The Borg pattern is extremely unusual, I've never needed it for real in ten years of Python programming.
Also, Borg-like pattern allows users of the class to choice if they want to share the state or create a separate instance. (whether or not this may be a good idea is a separate topic)
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 = ..
'Programing' 카테고리의 다른 글
Google 크롬 개발 도구가 표시되지 않는 요소 스타일을 검사합니다. (0) | 2020.10.22 |
---|---|
Android 스튜디오 : Gradle 동기화 실패 : '…'HEAD를 보낼 수 없습니다. (0) | 2020.10.22 |
Chrome 개발자 도구 : html 스크립트가 비어 있습니다 (소스에서) 디버깅 자습서 (0) | 2020.10.22 |
새로운 asp.net 차트 컨트롤-MVC와 함께 작동합니까 (결국)? (0) | 2020.10.22 |
asp.net에서 캐시를 잠그는 가장 좋은 방법은 무엇입니까? (0) | 2020.10.21 |