03. 자바 프로토타입 패턴 (JAVA Prototype Pattern)
# 참고한 영상
# 설명
생산 비용이 높은 인스턴스를 복사를 통해서
쉽게 생성 할 수 있도록 하는 패턴
# 장점
[인스턴스 생산 비용이 높은 경우]
종류가 너무 많아서 클래스로 정리되지 않는 경우
클래스로부터 인스턴스 생성이 어려운 경우
똑같은 인스턴스를 간단하게 생성할 수 있다
# 단점
# 사용 여부
인스턴스 생산 비용 (작업율)이 많이 드는 객체를
복사하여 만들고자 할 때 사용한다.
DB에서 데이터를 가져와 객체를 생성하였는데,
똑같은 객체가 필요하고자 할 때
DB에서 다시 데이터를 검색하여 생성하는 방식은 비효율적이다.
이미 존재하는 객체를 복사하여 새로운 객체를 만드는게 효율적이다
# 사용 방법
1. 클래스생성 후 implement Cloneable
2. 위에서 만든 클래스를 상속
3. this.clone() 사용
# 구조
# 요구 사항
일러스트레이터와 같은 그림 그리기 툴을 개발 중입니다.
어떤 모양(Shape) 그릴 수 있도록 하고 복사 붙여넣기 기능을 구현해주세요.
# 변경 사항
복사 후 붙여넣기를 하면 두 도형이 겹치는데
안겹치도록 살짝 옆으로 이동하게 해주세요.
# 결과 - Deep Copy
# Prototype (Class) - Deep Copy
Shape.java
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Shape implements Cloneable {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
|
cs |
# Prototype (Class) - Deep Copy
Circle.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package design.A_creational.prototype.deep_copy.domain;
public class Circle extends Shape {
private int x, y, r;
public Circle(int x, int y, int r) {
this.x = x;
this.y = y;
this.r = r;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getR() {
return r;
}
public void setR(int r) {
this.r = r;
}
public Circle copy() throws CloneNotSupportedException {
Circle circle = (Circle) clone();
// 변경사항
circle.x +=1;
circle.y +=1;
//
return circle;
}
}
|
cs |
# Client - Deep Copy
Client.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Circle circle1 = new Circle(1,1,3);
Circle circle2 = circle1.copy();
System.out.println(circle2.getX() + "," + circle2.getY() + "," +
circle2.getR() );
}
}
|
cs |
# Diagram - Deep Copy
# Shallow Copy
Cat cat1 = new Cat();
Cat cat2 = cat1;
이렇게 되는 경우
cat1 의 내용을 복사하여 만드는 것이 아니라
이미 cat1로 인스턴스화 된 주소를 담는다.
때문에 cat2 에서 수정을 하면 cat1까지 수정 된다
# 결과 - Shallow Copy & Deep Copy
# Prototype (Class) - Shallow Copy & Deep Copy
Cat.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
/** 고양이 */
public class Cat implements Cloneable {
/** 이름 */
private String name;
/** 나이 Class */
private Age age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Age getAge() {
return age;
}
public void setAge(Age age) {
this.age = age;
}
/** 복사 (Clone) */
public Cat copy() throws CloneNotSupportedException {
// 새로 리턴할 객체
Cat cat = (Cat) this.clone();
// 사용자 자료형은 복사가 되지 않기 때문에 명시적으로 넣어준다
cat.setAge(new Age(this.age.getYear(), this.age.getValue()));
return cat;
}
}
|
cs |
Age.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/** 나이 */
public class Age {
/** 연도 */
int year;
/** 나이 실제 값 */
int value;
/** 생성자 */
public Age(int year, int value) {
this.year = year;
this.value = value;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
|
cs |
# Client - Shallow Copy & Deep Copy
Client.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
/** 사용자 */
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Cat cat1 = new Cat();
cat1.setName("navi");
cat1.setAge(new Age(2019,1)); // 2020 기준
Cat cat2 = cat1;
cat2.setName("yomi");
cat2.setAge(new Age(2015, 5)); // 2020 기준
System.out.println("[Shallow Copy]");
System.out.println("cat1.name = " + cat1.getName());
System.out.println("cat1.age.year = " + cat1.getAge().getYear());
System.out.println("cat1.age.value = " + cat1.getAge().getValue());
System.out.println();
System.out.println("cat2.name = " + cat2.getName());
System.out.println("cat2.age.year = " + cat2.getAge().getYear());
System.out.println("cat2.age.value = " + cat2.getAge().getValue());
System.out.println("---------------------");
Cat cat3 = new Cat();
cat3.setName("chobi");
cat3.setAge(new Age(2017,3)); // 2020 기준
Cat cat4 = cat3.copy();
cat4.setName("mio");
// 커스텀 자료형의 멤버변수들은 clone 이 되지 않는다
// 때문에 copy 메소드에서 명시적으로 new Age 를 하여 새롭게 메모리를 넣는다.
cat4.getAge().setYear(2015);
cat4.getAge().setValue(5);
System.out.println("[Deep Copy]");
System.out.println("cat3.name = " + cat3.getName());
System.out.println("cat2.age.year = " + cat3.getAge().getYear());
System.out.println("cat2.age.value = " + cat3.getAge().getValue());
System.out.println();
System.out.println("cat4.name = " + cat4.getName());
System.out.println("cat2.age.year = " + cat4.getAge().getYear());
System.out.println("cat2.age.value = " + cat4.getAge().getValue());
}
}
|
cs |
# Diagram - Shallow Copy & Deep Copy
# 참고용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
interface Person {
Person clone();
}
class Tom implements Person {
private final String NAME = "Tom";
@Override
public Person clone() {
return new Tom();
}
@Override
public String toString() {
return NAME;
}
}
class Dick implements Person {
private final String NAME = "Dick";
@Override
public Person clone() {
return new Dick();
}
@Override
public String toString() {
return NAME;
}
}
class Harry implements Person {
private final String NAME = "Harry";
@Override
public Person clone() {
return new Harry();
}
@Override
public String toString() {
return NAME;
}
}
class Factory {
private static final Map<String, Person> prototypes = new HashMap<>();
static {
prototypes.put("tom", new Tom());
prototypes.put("dick", new Dick());
prototypes.put("harry", new Harry());
}
public static Person getPrototype(String type) {
try {
return prototypes.get(type).clone();
} catch (NullPointerException ex) {
System.out.println("Prototype with name: " + type + ", doesn't exist");
return null;
}
}
}
public class PrototypeFactory {
public static void main(String[] args) {
if (args.length > 0) {
for (String type : args) {
Person prototype = Factory.getPrototype(type);
if (prototype != null) {
System.out.println(prototype);
}
}
} else {
System.out.println("Run again with arguments of command string ");
}
}
}
|
cs |
# 참고용2
'92. 디자인 패턴 > 생성(Creational)' 카테고리의 다른 글
02. 자바 싱글톤 패턴 (JAVA Singleton Pattern) (0) | 2020.06.22 |
---|---|
01. 자바 팩토리 메소드 패턴 (JAVA Factory Method Pattern) (0) | 2020.06.19 |
댓글
이 글 공유하기
다른 글
-
02. 자바 싱글톤 패턴 (JAVA Singleton Pattern)
02. 자바 싱글톤 패턴 (JAVA Singleton Pattern)
2020.06.22 -
01. 자바 팩토리 메소드 패턴 (JAVA Factory Method Pattern)
01. 자바 팩토리 메소드 패턴 (JAVA Factory Method Pattern)
2020.06.19