먼저 유명한 디자인 패턴인 팩토리 패턴 (Factory Pattern) 은 상위 클래스와 여러개의 하위 클래스가 있을 때, 특정 상황에 따라 그에 맞는 하위 클래스 객체를 return 해야 될때 사용하는 디자인 패턴이다.
이번에 기록할 주제인 추상 팩토리 패턴은 이름만 봐서는 팩토리 메서드 패턴과 비슷해보이지만, 명확한 차이점이 있다.
팩토리 메서드 패턴
- 조건에 따른 객체 생성을 팩토리 클래스로 위임하여, 팩토리 클래스에서 객체를 생성하는 패턴
추상 팩토리 패턴
- 서로 관련이 있는 객체들을 통째로 묶어서 팩토리 클래스로 만들고, 이들 팩토리를 조건에 따라 생성하도록 다시 팩토리를 만들어서 객체를 생성하는 패턴
추상 팩토리 패턴은 어떻게 보면, 팩토리 메서드 패턴을 좀 더 캡슐화한 방식이라고 볼 수 있다.
if - else 와 함께 new 가 난무하는 코드를 보고 마음이 좋지않아 Abstract Factory Pattern을 간단한 실습으로 공부해본다.
실습은 핸드폰 새로 사고 싶어서 삼성과 애플 핸드폰을 만드는 코드로 해보았다.
마음 좋지않은 code
@Override
public SamsungDevice createMobile(String model){
SamsungDevice samsungDevice;
if(model.contentEquals("Note8"))
samsungDevice = new SamsungNote8();
else if(model.contentEquals("Note9"))
samsungDevice = new SamsungNote9();
else if(model.contentEquals("Note10"))
samsungDevice = new SamsungNote10();
...
return samsungDevice;
}
이런 코드에서 다른 제품라인의 공장을 만들어야하는 코드로 수정을 해야한다면?
Samsung device 에 맞춰서 코드가 구현되어있으므로 많은 부분이 수정되어야 할 것이다.
SamsungDevice 가 아닌 제품의 추가도 있다면, 유연성이 떨어지는 코드이므로 if문 추가는 물론 부가적인 많은 코드들을 수정해야할 것이다.
팩토리 메소드 패턴을 사용하는 이유는 클래스간의 결합도를 낮추기 위한 것이다.
결합도라는 것은 간단히 말해 클래스의 변경점이 생겼을 때 얼마나 다른 클래스에도 영향을 주는가이므로 팩토리 메소드 패턴을 사용하는 경우 직접 객체를 생성해 사용하는 것을 방지하고 서브 클래스에 위임함으로써 보다 효율적인 코드 제어를 할 수 있고 의존성을 제거할 수 있다.
베트남 공장을 생성자로 삼성공장화 시킨 후 modelNumber 에 따라 핸드폰을 만드는 부분을 캡슐화한 간단한 예제 코드이다.
public class VietnamFactory{
SamsungMobileFactory samsungMobileFactory;
public VietnamFactory(samsungMobileFactory samsungMobileFactory) {
this.samsungMobileFactory = samsungMobileFactory;
}
public MobileFactory createSamsungMobilePhone(String modelName){
MobileFactory mobileFactory = samsungMobileFactory.createMobile(modelName);
return mobileFactory;
}
}
//main
VietnamFactory vietnamFactory = new VietnamFactory(new SamsungMobileFactory());
MobileFactory mobileFactory = vietnamFactory.createSamsungMobilePhone("note8");
public class SamsungMobileFactory implements MobileFactory{
@Override
public MobileFactory createMobile(String modelName){
if(model.contentEquals("Note8"))
samsungDevice = new SamsungNote8();
else if(model.contentEquals("Note9"))
samsungDevice = new SamsungNote9();
else if(model.contentEquals("Note10"))
samsungDevice = new SamsungNote10();
}
}
상기 코드로 열심히 삼성폰을 모델에 맞춰서 만들고 있었지만, 갑자기 Apple과 계약이 되어 사과폰도 만들어야한다!
급급히 IOSMobileFactory도 만들 수 있도록 VietnamFactory class 를 수정하였다.
public interface MobilePhoneInterface{
MobilePhone createMobilePhone(String modelName);
}
public class VietnamFactory{
MobileFactory mobileFactory;
//MobileFactory - samsung과 ios super class
public VietnamFactory(MobileFactory mobileFactory) {
this.mobileFactory = mobileFactory
}
public MobilePhoneInterface createSamsungAndIOS(String modelName){
MobilePhoneInterface mobilePhoneInteface = mobileFactory.createMobilePhone(modelName);
return mobilePhone;
}
}
//main
VietnamFactory vietnamFactorySamsung = new VietnamFactory(new SamsungMobileFactory());
MobilePhoneInterface samsungPhone = vietnamFactorySamsung.createSamsungAndIOS("note8");
VietnamFactory vietnamFactoryIOS = new VietnamFactory(new IOSMobileFactory());
MobilePhoneInterface iosPhone = vietnamFactoryIOS.createSamsungAndIOS("iphone11");
종류별로 factory 를 주입하여 VietnamFactory class의 createMobilePhone method를 호출시에 각 핸드폰을 만들 수 있도록 구현하였으나, 두 개의 제품의 기능이 공통되지 않은 각자 다른 새로운 기능을 만들어야할때는 VietnamFactory에 의존성을 두어 개발하게되면 확장성이 부족한 코드라고 볼 수 있다.
IOS만 추가되는 기능을 위해 Samsung 과 같이쓰는 공장에 새로운 기계를 사게되면 혼동이 오지않겠는가??
그럼, 이런 문제를 방지하도록 추상 팩토리 패턴을 사용하여 업체별 핸드폰을 제작하는 유연한 코드를 만들어보자
- 팩토리 추상화
public interface MobilePhoneFactory {
public Camera createCamera();
public Battery createBattery();
public OSSoftware[] createOSSoftware();
public Antenna createAntenna();
}
- 팩토리별 구현부
public class IOSMobileFactory implements MobilePhoneFactory{
@Override
public Camera createCamera() {
return new IOSCamera();
}
@Override
public Battery createBattery() {
return new IOSBattery();
}
@Override
public OSSoftware[] createOSSoftware() {
OSSoftware[] osSoftwares = {
new TelephoneCallSoftware(),
new MessageSoftware(),
new MemoSoftware(),
new KakaoSoftware(),
new AppStore()
};
return osSoftwares;
}
@Override
public Antenna createAntenna() {
return new IOSAntenna();
}
}
public class SamsungMobileFactory implements MobilePhoneFactory{
@Override
public Camera createCamera() {
return new SamsungCamera();
}
@Override
public Battery createBattery() {
return new SamsungBattery();
}
@Override
public OSSoftware[] createOSSoftware() {
OSSoftware[] osSoftwares = {
new TelephoneCallSoftware(),
new MessageSoftware(),
new MemoSoftware(),
new KakaoSoftware(),
new PlayStore()
};
return osSoftwares;
}
@Override
public Antenna createAntenna() {
return new SamsungAntenna();
}
- 구성품 추상화
public abstract class MobilePhone {
public ModelDetailInformation modelInformation; //modelName, producer, release date,
public Camera camera;
public Antenna antenna;
public Battery battery;
public OSSoftware[] osSoftwares;
public abstract void producing();
}
public class SamsungNote8 extends MobilePhone {
private MobilePhoneFactory mobilePhoneFactory;
public SamsungNote8(MobilePhoneFactory mobilePhoneFactory){
this.mobilePhoneFactory = mobilePhoneFactory;
}
@Override
public void producing() {
modelInformation = new SamsungModelDetailInformation(ModelInformation.SamsungModel.Note8, "201901010000", "pjh");
camera = mobilePhoneFactory.createCamera();
antenna = mobilePhoneFactory.createAntenna();
battery = mobilePhoneFactory.createBattery();
osSoftwares = mobilePhoneFactory.createOSSoftware();
}
}
public class IOSIPhone11 extends MobilePhone {
MobilePhoneFactory mobilePhoneFactory;
public IOSIPhone11(MobilePhoneFactory mobilePhoneFactory){
this.mobilePhoneFactory = mobilePhoneFactory;
}
@Override
public void producing() {
modelInformation = new IOSModelDetailInformation(ModelInformation.IOSModel.IPhone11, "pjh", "201901010000");
camera = mobilePhoneFactory.createCamera();
antenna = mobilePhoneFactory.createAntenna();
battery = mobilePhoneFactory.createBattery();
osSoftwares = mobilePhoneFactory.createOSSoftware();
}
}
Main factory
public class VietnamFactory {
private MobilePhone SamsungVietnamFactory(SamsungModelDetailInformation samsungModelDetailInformation){
SamsungMobileFactory samsungMobileFactory = new SamsungMobileFactory();
MobilePhone mobilePhone = null;
switch (samsungModelDetailInformation.getSamsungModel()){
case Note8:
mobilePhone = new SamsungNote8(samsungMobileFactory);
break;
case Note9:
mobilePhone = new SamsungNote9(samsungMobileFactory);
break;
case Note10:
mobilePhone = new SamsungNote10(samsungMobileFactory);
break;
}
return mobilePhone;
}
private MobilePhone AppleVietnamFactory(IOSModelDetailInformation iosModelDetailInformation){
IOSMobileFactory iosMobileFactory = new IOSMobileFactory();
MobilePhone mobilePhone = null;
switch (iosModelDetailInformation.getIosModel()){
case IPhone11:
mobilePhone = new IOSIPhone11(iosMobileFactory);
break;
case IPhone11Pro:
mobilePhone = new IOSIPhone11Pro(iosMobileFactory);
break;
}
return mobilePhone;
}
}
객체를 사용해 제품을 만들고, 객체의 구성을 통해서 객체를 만든다.
추상팩토리패턴은 제품군을 만들기 위한 추상 형식을 제공하고 있다. 제품이 생산되는 방법은 서브 클래스에서 정의된다.
'Java > 디자인패턴' 카테고리의 다른 글
디자인 패턴 - 싱글톤 패턴 (Singleton pattern) (0) | 2020.02.10 |
---|