추상 팩토리 패턴(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 객체지향 디자인 패턴 한빛 미디어
'JAVA > Design Pattern' 카테고리의 다른 글
옵저버 패턴 (Observer Pattern) (0) | 2018.05.27 |
---|---|
데코레이트 패턴 (Decorator Pattern) (0) | 2018.05.27 |
템플릿 메서드 패턴 (Template method) (0) | 2018.05.27 |
팩토리 메서드 패턴 (Factory method) (0) | 2018.05.27 |
컴퍼지트 패턴 (Composite pattern) (0) | 2018.05.27 |