Delphi에서 싱글톤 모드를 구현하는 두 가지 방법
하오즈
Abstract 이 기사에서는 싱글톤 모드의 두 가지 Delphi 구현을 설명하고 비교 분석합니다.
키워드 디자인 패턴, 싱글톤
싱글톤 패턴은 매우 유용한 디자인 패턴입니다. 그 목적은 단순히 클래스의 인스턴스를 생성하고 이에 대한 전역 액세스 지점을 제공하는 것입니다. 전역 변수를 사용하면 개체에 쉽게 액세스할 수 있지만 여러 개체를 인스턴스화하는 데 방해가 되지는 않습니다. 싱글톤 패턴의 목적은 프로그램의 수명 주기 동안 하나의 인스턴스만 존재하도록 하는 것입니다.
아래 코드를 보세요:
PROcedure TForm1.Button1Click(Sender: TObject);
var lS1 : TSingleton;
S2: T싱글턴;
시작하다
try lS1 := TSingleton.Create ////클래스 생성자를 호출합니다.
lS2 := TSingleton.Create ////클래스 생성자를 호출합니다.
//// ...다른 코드
마지막으로
lS1.Free; ////객체 해제
lS2.Free; ////객체 해제
끝;
끝;
위 코드에서 TSingleton 클래스는 Create 함수가 처음 호출될 때 인스턴스화됩니다. lS1은 메모리 저장 개체의 주소를 가리킵니다. TSingleton.Create 함수가 두 번째로 호출되면 TSingleton 개체가 다시 호출됩니다. -인스턴스화됨. lS2는 메모리 할당 주소를 가리킵니다. 싱글톤 패턴은 클래스 자체가 유일한 인스턴스를 저장하도록 하는 것입니다.
위 코드에서 ls2가 생성되면 ls1이 가리키는 객체도 가리킵니다(즉, 동일한 메모리 주소가 할당됩니다). 마찬가지로 ls1을 해제할 때 메모리가 해제되지 않도록 해야 합니다. 객체는 ls2에서도 참조됩니다. 이렇게 하면 프로그램 수명 주기 동안 클래스 인스턴스가 하나만 존재하게 됩니다.
"디자인 패턴"의 C++ 샘플 코드는 C++ 정적 멤버 변수를 사용하여 인스턴스를 저장하고 보호된 생성자 함수를 사용합니다. 하지만 델파이에는 정적 멤버 변수가 없기 때문에 이 싱글톤 모드 예제의 메소드를 그대로 사용할 수는 없습니다. 아래에서는 DELPHI가 싱글톤 모드를 구현하는 여러 가지 방법을 분석합니다.
하나. 두 개의 Tobject 가상 함수 재정의를 기반으로 하는 방법
클래스 함수 NewInstance: TObject;
프로시저 FreeInstance;
NewInstance 함수는 클래스 객체가 생성될 때 객체에 대한 메모리 할당을 담당하는 반면, FreeInstance는 반대로 메모리를 해제합니다.
.
전자는 객체가 생성될 때 호출되고 후자는 객체가 소멸될 때 호출됩니다.
우리는 싱글톤 객체와 객체의 참조 카운트를 유지하기 위해 두 개의 전역 변수를 사용합니다.
varInstance: TSingleton = nil;
RefCount : 정수 = 0;
TSingleton 클래스의 단위:
////----------------------------------- -- -------------
////
단위 u싱글턴;
인터페이스
유형
TSingleton = 클래스(TObject)
공공의
class function NewInstance: TObject 재정의 ////기본 클래스 함수 재정의;
프로시저 FreeInstance; ////기본 클래스 함수 재정의
클래스 함수 RefCount: Integer;////현재 참조 카운트를 반환합니다.
끝;
//// 전역 변수 선언
var
인스턴스: TSingleton = nil;
RefCount: 정수 = 0;
구현
{TSingleton}
절차 TSingleton.FreeInstance;
시작하다
Dec( RefCount );////참조 카운트 감소
if (RefCount = 0) then////0이면 메모리를 해제합니다.
시작하다
인스턴스 := nil;
//// 싱글톤 클래스의 개인 변수를 해제합니다.
////…
상속된 FreeInstance;
끝;
끝;
클래스 함수 TSingleton.NewInstance: TObject;
시작하다
if ( 할당되지 않음( 인스턴스 ) ) then
시작하다
Instance := TSingleton(상속된 NewInstance);
////개인 변수 초기화의 예:
//// Instance.VariableName := 값;
끝;
결과 := 인스턴스 ;
Inc( RefCount );
끝;
클래스 함수 TSingleton.RefCount: 정수;
시작하다
결과 := RefCount;
끝;
끝.
////----------------------------------- -- -------------
////
TSingleton의 생성자가 호출되면 NewInstance 재정의 함수가 호출되고 NewInstance가 메모리를 할당하고 이를 생성자에 반환합니다. 이러한 방식으로 재정의 NewInstance 함수를 통해 Create 함수가 TSingleton 개체만 인스턴스화할 수 있도록 보장합니다. (몇 번 호출하든 관계 없음) Create는 처음 할당된 메모리 주소만 반환합니다. 동시에 RefCount 변수는 객체에 대한 참조 수를 보유합니다.
테스트 코드를 살펴보자
절차 TForm1.Button1Click(Sender: TObject);
var
lS1, lS2: TSingleton;
Ob1, Ob2: T객체;
시작하다
lS1 := TSingleton.Create;
ShowMessage(IntToStr(RefCount)) //// Ref_Count = 1
lS2 := TSingleton.Create;
ShowMessage(IntToStr(RefCount)) //// Ref_Count = 2
Ob1 := TObject.Create;
Ob2 := Tobject.Create;
lS1 = lS2이면
ShowMessage('주소가 동일합니다.') //// lS1 = lS2
또 다른
ShowMessage('주소가 동일하지 않습니다.');
Ob1 = Ob2이면
ShowMessage('주소가 같습니다.')
또 다른
ShowMessage('주소가 동일하지 않습니다'); //// Ob1 <> Ob2
끝;
프로그램이 소멸자를 호출할 때(즉, FREE 함수가 호출될 때) 소멸자는 FreeInstance 함수를 호출하여 생성자가 할당한 메모리를 해제합니다. Override의 FreeInstance 함수는 참조 횟수가 0에 도달할 때만 싱글톤 모드 개체의 메모리가 해제되도록 보장합니다.
테스트 코드는 다음과 같습니다.
var
lS1: TSingleton;
lS2: TSingleton;
시작하다
노력하다
lS1 := TSingleton.Create ////클래스 생성자를 호출합니다.
lS2 := TSingleton.Create ////클래스 생성자를 호출합니다.
//// ...다른 코드
마지막으로
lS1.Free; ////여기서 먼저 재정의로 정의된 FreeInstance를 호출합니다.
////이때 RefCount가 1 감소한 후 1이 되므로 싱글톤 객체는 해제되지 않습니다.
lS2.Free; ////dec(RefCount)= 0은 싱글톤 객체를 해제합니다.
끝;
끝;
위의 싱글톤 패턴 구현 방법은 클래스 자체가 자신의 고유한 인스턴스를 저장하는 일을 담당한다는 것을 깨닫는 좋은 방법입니다(새 개체를 생성하라는 요청을 가로채서 - "디자인 패턴" 참조). 사용에 특별한 제한은 없습니다. TSingleton 클래스 - —프로그래머는 마음대로 Create 및 Free 함수를 호출할 수 있습니다.
이 모드의 단점은 TSingleton 클래스를 상위 클래스로 상속하여 하위 클래스를 생성할 수 없다는 것입니다. 상속이 두 개의 하위 클래스를 생성하는 경우 생성 중에 하나의 개체만 생성됩니다.
절차 TForm1.Button1Click(Sender: TObject);
var
lS1: 하위 범주 1;
lS2: 하위 범주 2;
시작하다
lS1 := 하위 클래스 1.Create;
lS2 := Subclass 2.Create; ////Subclass 2는 생성되지 않습니다. lS2는 lS1이 가리키는 메모리를 가리킵니다.
////즉, lS1 = lS2end;
둘. "디자인 패턴"에 있는 예제의 델파이 구현
"디자인 패턴"의 구현 예는 전용 생성자 함수를 통해 하나의 객체 인스턴스만 제어하는 것입니다. 그러나 주어진 C++ 코드 구현에서는 객체가 해제되는 방법을 제공하지 않습니다. Create 함수는 Delphi에서 사유화될 수 없습니다. 우리는 Create 함수를 대체하고 상위 클래스의 Create 함수를 보호하는 새로운 함수를 정의합니다. 코드는 다음과 같습니다
:
////----------------------------------- -- -------------
////
단위 uSingletonUnit;
인터페이스
용도
클래스, SysUtils;
유형
TCSingleton = class(TComponent) ////TcomComponent 클래스에서 상속됩니다.
사적인
constructor CreateInstance(AOwner: TComponent) ////소유자 매개변수 전달
//// 이렇게 하면 TCSingleton 클래스 객체가 Owner와 함께 소멸됩니다. (TCSingleton 객체 소멸은 소유자가 담당합니다.)
공공의
생성자 Create(AOwner: TComponent);
클래스 함수 Instance(AOwner: TComponent): TCSingleton;
끝;
var
gCSingleton: TCSingleton //// 전역 변수
구현
{TC싱글턴}
생성자 TCSingleton.Create(AOwner: TComponent);
시작하다
////Create 함수의 기능을 보호합니다.
raise Exception.CreateFmt('인스턴스를 통해서만 클래스 %s에 액세스',
[클래스 이름]);
끝;
생성자 TCSingleton.CreateInstance(AOwner: TComponent);
시작하다
////새로 정의된 생성자는 Private입니다.
상속받은 Create(AOwner);
끝;
클래스 함수 TCSingleton.Instance(AOwner: TComponent): TCSingleton;
시작하다
할당되지 않은 경우(gCSingleton)
gCSingleton := TCSingleton.CreateInstance(AOwner);
결과 := gCSingleton;
끝;
끝.
////----------------------------------- -----------------/
/
위의 구현 클래스를 사용하는 동안 프로그래머는 싱글톤 모드 개체의 소멸을 고려할 필요가 없습니다. Create를 호출할 수는 없으며 Instance 함수를 호출하여 객체의 인스턴스를 얻고 싱글톤 소유자를 함수에 매개 변수로 전달해야 합니다. 이 구현 방법은 기본 클래스로 상속될 수 있으며 실행 시간 다형성을 달성하기 위해 상태 패턴(참조 4 참조)의 싱글톤에서 사용될 수 있습니다.
삼. 결론
싱글톤 모드의 델파이 구현은 인터넷에서도 찾을 수 있습니다. 이 기사에는 두 가지 구현 방법이 있습니다.
가장 일반적이고 간단합니다. 동시에 다른 방법의 아이디어도 위의 두 가지 방법과 매우 유사합니다.