싱글톤 싱글몰트 스카치 위스키가 좋다는 말을 들어보셨나요? 음, 술은 건강에 좋지 않습니다. 그래서 오늘은 대신 Java의 싱글톤 디자인 패턴에 대해 알려드리겠습니다.
우리는 이전에 객체 생성을 검토했으므로 Java에서 객체를 생성하려면 다음과 같이 작성해야 한다는 것을 알고 있습니다.
Robot robot = new Robot();
하지만 클래스의 인스턴스가 하나만 생성되도록 하려면 어떻게 해야 할까요?
new Robot() 문은 많은 객체를 생성할 수 있으며 그렇게 하는 것을 막을 수 있는 것은 없습니다. 이것은 싱글톤 패턴이 구출되는 곳입니다.
프린터에 연결할 애플리케이션(단지 프린터 하나만)을 작성하고 인쇄하라고 지시해야 한다고 가정해 보겠습니다.
public class Printer {
public Printer() {
}
public void print() {
…
}
}
이것은 평범한 수업처럼 보이지만... 하지만! 하나의 "하지만"이 있습니다. 프린터 개체의 여러 인스턴스를 만들고 다른 위치에서 메서드를 호출할 수 있습니다. 이로 인해 프린터가 손상되거나 파손될 수 있습니다. 따라서 우리는 프린터의 인스턴스가 하나만 있는지 확인해야 하며 이것이 싱글톤이 우리를 위해 할 일입니다!
싱글톤을 만드는 방법
싱글톤을 만드는 방법에는 두 가지가 있습니다.
- 개인 생성자를 사용하십시오.
- 단일 인스턴스에 대한 액세스를 제공하기 위해 공용 정적 메서드를 내보냅니다.
먼저 개인 생성자를 사용하는 것을 고려해 보겠습니다. 이렇게 하려면 클래스에서 필드를 final 로 선언하고 초기화해야 합니다. 우리는 그것을 final 로 표시했기 때문에 그것이 불변 이라는 것을 압니다 . 즉, 더 이상 변경할 수 없습니다.
또한 생성자를 전용 으로 선언하여 클래스 외부에서 개체를 만들지 않도록 해야 합니다 . 이는 프로그램에 프린터의 다른 인스턴스가 없음을 보장합니다. 생성자는 초기화 중에 한 번만 호출되며 Printer 를 생성합니다 .
public class Printer {
public static final Printer PRINTER = new Printer();
private Printer() {
}
public void print() {
// Printing...
}
}
우리는 개인 생성자를 사용하여 PRINTER 싱글톤을 생성했습니다. 인스턴스는 하나만 있을 것입니다. 그만큼인쇄기변수는 어떤 객체에도 속하지 않고 Printer 클래스 자체에 속하기 때문에 정적 수정자를 가집니다 .
이제 클래스의 단일 인스턴스에 대한 액세스를 제공하기 위해 정적 메서드를 사용하여 싱글톤을 생성하는 것을 고려해 보겠습니다(그리고 이제 필드는 private 입니다 ).
public class Printer {
private static final Printer PRINTER = new Printer();
private Printer() {
}
public static Printer getInstance() {
return PRINTER;
}
public void print() {
// Printing...
}
}
여기에서 getInstance() 메서드를 몇 번 호출하더라도 항상 같은 결과를 얻습니다.인쇄기물체.
개인 생성자를 사용하여 싱글톤을 만드는 것이 더 간단하고 간결합니다. 또한 public 필드가 final 로 선언되어 항상 동일한 개체에 대한 참조를 포함하도록 보장하므로 API가 분명합니다.
정적 메서드 옵션은 API를 변경하지 않고 싱글톤을 비싱글톤 클래스로 변경할 수 있는 유연성을 제공합니다. getInstance () 메서드는 개체의 단일 인스턴스를 제공하지만 이를 호출하는 각 사용자에 대해 별도의 인스턴스를 반환하도록 변경할 수 있습니다.
static 옵션을 사용하면 일반적인 싱글톤 팩토리를 작성할 수도 있습니다.
정적 옵션의 마지막 이점은 메서드 참조와 함께 사용할 수 있다는 것입니다.
위의 장점이 필요하지 않은 경우 공개 필드와 관련된 옵션을 사용하는 것이 좋습니다.
직렬화가 필요한 경우 Serializable 인터페이스를 구현하는 것만으로는 충분하지 않습니다. 또한 readResolve 메서드를 추가해야 합니다 . 그렇지 않으면 역직렬화 중에 새 싱글톤 인스턴스를 얻게 됩니다.
개체의 상태를 일련의 바이트로 저장하려면 직렬화가 필요하고 해당 바이트에서 개체를 복원하려면 역직렬화가 필요합니다. 직렬화 및 역직렬화에 대한 자세한 내용은 이 기사를 참조하십시오 . |
이제 싱글톤을 다시 작성해 보겠습니다.
public class Printer implements Serializable {
private static final Printer PRINTER = new Printer();
private Printer() {
}
public static Printer getInstance() {
return PRINTER;
}
}
이제 직렬화 및 역직렬화하겠습니다.
아래 예제는 Java의 직렬화 및 역직렬화를 위한 표준 메커니즘입니다. "I/O 스트림"(Java Syntax 모듈에서) 및 "Serialization"(Java Core 모듈에서)을 공부한 후에 코드에서 일어나는 일을 완전히 이해할 수 있습니다. |
var printer = Printer.getInstance();
var fileOutputStream = new FileOutputStream("printer.txt");
var objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(printer);
objectOutputStream.close();
var fileInputStream = new FileInputStream("printer.txt");
var objectInputStream = new ObjectInputStream(fileInputStream);
var deserializedPrinter =(Printer) objectInputStream.readObject();
objectInputStream.close();
System.out.println("Singleton 1 is: " + printer);
System.out.println("Singleton 2 is: " + deserializedPrinter);
결과는 다음과 같습니다.
싱글톤 2: Printer@3c756e4d
여기에서 역직렬화가 우리에게 싱글톤의 다른 인스턴스를 제공했음을 알 수 있습니다. 이 문제를 해결하기 위해 클래스에 readResolve 메서드를 추가해 보겠습니다 .
public class Printer implements Serializable {
private static final Printer PRINTER = new Printer();
private Printer() {
}
public static Printer getInstance() {
return PRINTER;
}
public Object readResolve() {
return PRINTER;
}
}
이제 싱글톤을 다시 직렬화 및 역직렬화합니다.
var printer = Printer.getInstance();
var fileOutputStream = new FileOutputStream("printer.txt");
var objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(printer);
objectOutputStream.close();
var fileInputStream = new FileInputStream("printer.txt");
var objectInputStream = new ObjectInputStream(fileInputStream);
var deserializedPrinter=(Printer) objectInputStream.readObject();
objectInputStream.close();
System.out.println("Singleton 1 is: " + printer);
System.out.println("Singleton 2 is: " + deserializedPrinter);
그리고 우리는 다음을 얻습니다.
싱글톤 2: com.company.Printer@6be46e8f
readResolve () 메서드를 사용하면 역직렬화한 동일한 객체를 얻을 수 있으므로 불량 싱글톤 생성을 방지할 수 있습니다.
요약
오늘 우리는 싱글톤에 대해 배웠습니다. 싱글톤을 생성하는 방법과 사용 시기, 용도, 생성을 위해 Java에서 제공하는 옵션. 두 옵션의 특정 기능은 다음과 같습니다.
개인 생성자 | 정적 방법 |
---|---|
|
|
GO TO FULL VERSION