어느 덧 한 주를 마무리하는
일요일이 되었습니다
내일이 되면 다시 한주를 바쁘게
살아가야한다는...
아무튼 오늘은
지정한 클래스의 인스턴스가
한 개만 존재하는 것을 보증하고 싶을 때
사용하는 싱글톤(Singleton) 패턴과
클래스로부터 인스턴스를
만드는 것이 아니라 인스턴스를 복사해서
새로운 인스턴스를 만드는
프로토타입 패턴에 대해 알아보겠습니다
먼저 싱글톤을 구성하는 역할은
아래와 같이 Singleton 하나 뿐입니다
역할 | 설명 |
싱글톤(Singleton) | 유일한 인스턴스를 얻기 위한 static 메소드를 가지며 언제나 동일한 인스턴스를 반환 |
역시 실제로 구현을 해보아야겠죠?
1. 클래스(Class) Singleton.java
package singletonPattern;
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {
System.out.println("Created an instance");
}
public static Singleton getInstance() {
return singleton;
}
}
2. 클래스(Class) Test.java
import singletonPattern.*;
public class Test {
public static void main(String[] args) {
/* Singleton Pattern */
System.out.println("Start.");
Singleton obj1 = Singleton.getInstance();
Singleton obj2 = Singleton.getInstance();
if ( obj1 == obj2 ) {
System.out.println("obj1 and obj2 are the same instance");
} else {
System.out.println("obj1 and obj2 are difference instance.");
}
System.out.println("End.");
}
}
위의 코드에서 Singleton 클래스의
인스턴스는 프로그램 실행 후
최초로 getInstance() 메소드를 호출했을 때
유일하게 생성됩니다
이제 프로토타입 패턴에 대해 알아보겠습니다
프로토 타입을 구성하는
역할들은 아래와 같습니다
역할 | 설명 |
원형(Prototype) | 인스턴스를 복사하여 새로운 인스턴스를 만들기 위한 메소드를 결정 |
구체적인 원형(Concrete Prototype) | 인스턴스를 복사해서 새로운 인스턴스를 만드는 메소드를 실제로 구현 |
이용자(Client) | 인스턴스를 복사하는 메소드를 이용해서 새로운 인스턴스를 생성 |
자 그럼 실제로 구현해겠습니다
1. 인터페이스(Interface) Product.java
package prototypePattern.framework;
public interface Product extends Cloneable{
public abstract void use(String string);
public abstract Product createClone();
}
2. 클래스(Class) Manager.java
package prototypePattern.framework;
import java.util.*;
public class Manager {
private HashMap<String, Product> showcase = new HashMap<String, Product>();
public void register(String name, Product proto) {
showcase.put(name, proto);
}
public Product create(String protoname) {
Product p = (Product)showcase.get(protoname);
return p.createClone();
}
}
3. 클래스(Class) MessageBox.java
package prototypePattern.anonymous;
import prototypePattern.framework.*;
public class MessageBox implements Product {
private char decoChar;
public MessageBox(char decoChar) {
this.decoChar = decoChar;
}
public void use(String string ) {
int length = string.getBytes().length;
for ( int i = 0; i < length + 4; i++ ) {
System.out.print(decoChar);
}
System.out.println("");
System.out.println(decoChar + "" + string + "" + decoChar);
for ( int i = 0; i < length + 4; i++ ) {
System.out.print(decoChar);
}
System.out.println("");
}
public Product createClone() {
Product p = null;
try {
p = (Product)clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return p;
}
}
4. 클래스(Class) UnderlinePen.java
package prototypePattern.anonymous;
import prototypePattern.framework.*;
public class UnderlinePen implements Product {
private char ulChar;
public UnderlinePen(char ulChar) {
this.ulChar = ulChar;
}
public void use(String string ) {
int length = string.getBytes().length;
System.out.println("\"" + string + "\"");
System.out.print(" ");
for ( int i = 0; i < length; i++ ) {
System.out.print(ulChar);
}
System.out.println("");
}
public Product createClone() {
Product p = null;
try {
p = (Product)clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return p;
}
}
5. 클래스(Class) Test.java
import prototypePattern.anonymous.*;
import prototypePattern.framework.*;
public class Test {
public static void main(String[] args) {
// Ready
Manager manager = new Manager();
UnderlinePen upen = new UnderlinePen('~');
MessageBox mbox = new MessageBox('*');
manager.register("string message", upen);
manager.register("warning box", mbox);
// Create
Product p1 = manager.create("string message");
p1.use("Hello, prototype");
Product p2 = manager.create("warning box");
p2.use("Hello, prototype");
}
}
위의 코드를 자세히 보면
인터페이스 Product가 Cloneable 인터페이스를
상속하고 있는데 이는
Java에서 인스턴스 복사를 실행하는 도구로
clone 메소드가 있기 때문입니다
이 메소드가 하는 일은
원래의 인스턴스와 같은 크기의 메모리를 확보하고
그 인스턴스의 필드 내용을 복사하는 것입니다
이것은 필드의 앞에 있는 인스턴스의 내용까지는
고려하지 않는 필드 대 필드의 복사로써
피상적인 복사(shallow copy)라고 합니다
또 Cloneable 인터페이스를 구현하지 않는
클래스의 인스턴스가 clone 메소드를 호출하면
예외 CloneNotSupportedException이 발생합니다
또 java.lang 패키지는 암묵적으로 import되어있기 때문에
따로 import 하지 않아도 쓸 수 있습니다
마지막으로 프로토타입을 쓰는 경우를
살펴보고 오늘의 학습을 마치겠습니다
1. 종류가 너무 많아 각각을 별도의 클래스로 만들어 다수의 소스 파일을 작성해야해서 정리되지 않는 경우 2. 클래스로부터 인스턴스 생성이 어려운 경우 3. framework와 생성할 인스턴스를 분리하고 싶은 경우 |
그럼 이만-_-
'Java' 카테고리의 다른 글
[Design Pattern] 추상적인 공장 패턴(Abstract Factory Pattern) (0) | 2020.06.21 |
---|---|
[Design Pattern] 빌더 패턴(Builder Pattern) (0) | 2020.06.15 |
[Design Pattern] 팩토리 메소드 패턴(Factory Method Pattern) (0) | 2020.06.13 |
[Design Pattern] 템플릿 메소드 패턴(Template Method Pattern) (0) | 2020.06.11 |
[Design Pattern] 어댑터 패턴(Adapter Pattern) (0) | 2020.06.09 |