추상 팩토리 패턴 (Abstract Factory Pattern)
JAVA/Design Pattern

추상 팩토리 패턴 (Abstract Factory Pattern)

반응형

추상 팩토리 패턴(Abstract Factory Pattern)은 관련성 있는 여러 종류의 객체를 일관된 방식으로 생성하는 경우에 유용하다.

아래에서 예를 통해 알 수 있겠지만 
Door와 Motor를 종류에 따라 얻기 위해 Factory 클래스를 정의해서 사용하기 보다는
관련 객체들을 일관성 있게 생성할 수 있도록 Factory 클래스를 정의하는 것이 효과적이다.




예를 들어보자.

[문제상황]
엘레베이터 모터를 움직여야 할 경우

엘레베이터 브랜드에 따라 door와 motor를 별도로 설정해주어야 하는 경우에는 
다음과 같이 별도로 두 개의 과정을 거쳐야해서 불편하다.



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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// door 추상클래스
public abstract class Door {
    private DoorStatus doorStatus;
 
    public Door() {
        this.doorStatus = DoorStatus.CLOSED;
    }
    
    public static Door getDoor(String id){
        switch(id) {
        case "Apple":
            return new AppleDoor();
        case "Samsung":
            return new SamsungDoor();
        default:
            return null;
        }
    }
 
    public DoorStatus getDoorStatus() {
        return doorStatus;
    }
 
    // 동일하게 사용하는 메서드를 정의해놓는 템플릿 메서드
    public void close() {
        if (doorStatus == DoorStatus.CLOSED)
            return;
 
        doClose();
        doorStatus = DoorStatus.CLOSED;
    }
 
    abstract void doClose();
}
 
// 삼성 문
public class SamsungDoor extends
        Door {
 
    @Override
    void doClose() {
        System.out.println("SamsungDoor");
    }
 
}
 
// Apple 문
public class AppleDoor extends
        Door {
 
    @Override
    void doClose() {
        System.out.println();
    }
 
}
 
// 모터 추상클래스
public abstract class Moter {
    protected Door door;
    public Moter() {}
    
    public static Moter CreateMotor(String id) {
        switch(id) {
        case "Apple":
            return new AppleMoter();
        case "Samsung":
            return new SamsungMoter();
 
        default:
            return null;
        }
    }
    
    public void setDoor(Door door) {
        this.door = door;
    }
    
    public DoorStatus getDoorStatus() {
        return this.door.getDoorStatus();
    }
    
    abstract void move(Direction direction);
}
 
// 삼성 모터
public class SamsungMoter extends
        Moter {
 
    @Override
    public void move(Direction direction) {
        if (getDoorStatus() == DoorStatus.OPENED) {
            
        }
        
        System.out.println(direction.name() + " moved by samsung moter.");
    }
}
 
// Apple 모터
public class AppleMoter extends Moter {
 
    @Override
    public void move(Direction direction) {
        System.out.println(direction.name() + " moved by apple moter.");
    }
 
}
 
// 메인 클래스
public class Main {
    public static void main(String[] args) {
        Door door = Door.getDoor("Samsung");
        Moter motor = Moter.CreateMotor("Samsung");
        
        motor.setDoor(door);
        motor.move(Direction.DOWN);
        
        door = Door.getDoor("Apple");
        motor = Moter.CreateMotor("Apple");
        
        motor.setDoor(door);
        motor.move(Direction.UP);
    }
}
cs





[추상 팩토리 메서드 패턴을 이용한 해결방법]

Motor 클래스, Door 클래스를 위한 Factory 클래스를 정의하는 대신 각 
종류에 맞는 통합 Factory를 정의하여 사용하는 것이 더욱 바람직하다.



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
package abstractPattern2;
 
public class ElevatorFactory {
    public static ElevatorFactory getFactory(String id) {
        switch(id) {
        case "Apple":
            return AppleElevatorFactory.getInstance();
        
        case "SamSung":
            return SamSungElevatorFactory.getInstance();
        
        default:
            return null;
        }
    }
}
 
package abstractPattern2;
 
public class SamSungElevatorFactory extends
        ElevatorFactory {
    
    private static SamSungElevatorFactory instance;
 
    public static synchronized SamSungElevatorFactory getInstance() {
        if (instance == null) {
            instance = new SamSungElevatorFactory();
        }
        
        return instance;
    }
    
    public Motor createMotor() {
        return new SamsungMotor();
    }
    
    public Door createDoor() {
        return new SamsungDoor();
    }
}
 
package abstractPattern2;
 
public class AppleElevatorFactory extends
        ElevatorFactory {
    
    private static AppleElevatorFactory instance;
 
    public static synchronized AppleElevatorFactory getInstance() {
        if (instance == null) {
            instance = new AppleElevatorFactory();
        }
        
        return instance;
    }
    
    public Motor createMotor() {
        return new AppleMotor();
    }
    
    public Door createDoor() {
        return new AppleDoor();
    }
}
 
// 나머지 구성들은 위의 예와 동일
cs



위의 그려진 UML에 
빗대어 본다면 ElevatorFactory가  AbstractFactory
ConcreateFactory는 AppleElevatorFactory와 SamsungElevatorFactory
그리고 AbstractProduct는 Motor와 Door
그리고 마지막으로 ConcreatedProduct들은 각 Apple과 Samsung들의 door와 motor들이다.


정리하면.
여러 종속되는 다양한 종류들이 있어 Factory 클래스를 여러개 정의해야 하는 경우에는
큰 부분을 관리하는 Factory를 만들어서 사용하는 것이 더 바람직하다.

출처 : JAVA 객체지향 디자인 패턴 한빛 미디어

반응형