반응형
팩토리 메소드 패턴
부모 클래스와 자식 클래스가 있을때, 팩토리 클래스를 이용하여 자식 클래스의 인스턴스를 생성하는 패턴
공장처럼 팩토리 클래스가 객체를 생성하게 된다
생성과 처리로직을 분리하여 결합도를 낮추기 위한 패턴
- 클래스의 인스턴스 생성을 서브 클래스가 결정하도록 할 때
- 클래스가 자신이 생성해야 하는 객체의 클래스를 예측할 수 없을 때
단점
- 팩토리 메소드 패턴으로 인해 extends를 남발하게 되면 프로그램의 엔트로피가 높아질 수 있다.
템플릿 메소드 패턴과 차이점
템플릿 메소드 패턴은 행위 패턴으로 부분적으로 다른 로직을 가지는 메소드의 코드 중복을 최소화할 때 사용
코드
public class FactoryMethod {
public static void main(String[] args){
Bank bank = new Bank();
Account saveAccount = bank.createAccount(AccountType.SAVE, "yaini");
saveAccount.deposit(100);
CheckingAccount checkAccount = (CheckingAccount) bank.createAccount(AccountType.CHECK, "yaini");
checkAccount.withdraw(100);
}
}
enum AccountType { SAVE, CHECK }
class Bank extends AccountFactory{
@Override
protected Account createAccount(AccountType type, String holder) {
switch ( type ){
case SAVE:
return new SavingAccount(holder);
case CHECK:
return new CheckingAccount(holder);
default:
throw new RuntimeException("Invalid Type");
}
}
}
abstract class AccountFactory{
protected abstract Account createAccount(AccountType type, String holder);
}
abstract class Account{
public String holder;
public int balance;
public abstract void deposit(int money);
public Account(String holder){
this.holder = holder;
}
}
class SavingAccount extends Account{
public SavingAccount(String holder) {
super(holder);
}
@Override
public void deposit(int money) {
this.balance += money;
}
}
class CheckingAccount extends Account{
public CheckingAccount(String holder) {
super(holder);
}
@Override
public void deposit(int money) {
this.balance -= money;
}
public void withdraw(int money){
this.balance -= money;
}
}
실제로 사용해 봤을때, 객체 생성을 위한 enumType을 정의해야 하거나, if else문의 굉장히 많아지는 단점이 있었다.
예제와 같이 파라미터가 적은 생성자를 가진 객체엔 유용하지만, 파라미터가 많은 객체를 사용하면 Builder 패턴을 사용해도 코드가 장황해지게 된다.
또한 팩토리 클래스를 따로 생성하여 객체를 만드는 방식이 가독성에 유용한지도 생각을 해봐야 할 것 같다.
추상 팩토리 패턴
비슷한 속성을 인터페이스로 규격화하여 팩토리에서 일관된 방식으로 생성하도록 하는 패턴.
생성된 객체 끼리 쉽게 교체될 수 있도록 함
팩토리 메소드 패턴과 차이점
추상 팩토리 패턴은 팩토리 메소드 패턴을 좀 더 캡슐화한 방식이다.
UML 다이어그램을 보면 알 수 있듯이 사용자는 Factory에 직접 접근하지 않는다.
사용자가 타입을 지정해서 직접 Product를 생성하던 팩토리 메소드와는 달리 생성과정과 객체를 캡슐화 했다.
- 팩토리 메소드 패턴
- 조건에 따른 객체 생성을 팩토리 클래스로 위임
- 추상 팩토리 패턴
- 서로 관련이 있는 객체들을 묶어서 팩토리 클래스 생성
코드
public class AbstractFactory {
public static void main(String[] args){
Card creditCard = CardFactory.getCreditCard(new HyundaiCardFactory());
Card debitCard = CardFactory.getDebitCard(new KBCardFactory());
}
}
interface CardAbstractFactory{
Card createCreditCard();
Card createDebitCard();
}
class HyundaiCardFactory implements CardAbstractFactory{
@Override
public Card createCreditCard() {
return new CreditCard();
}
@Override
public Card createDebitCard() {
return new DebitCard();
}
}
class KBCardFactory implements CardAbstractFactory{
@Override
public Card createCreditCard() {
return new CreditCard();
}
@Override
public Card createDebitCard() {
return new DebitCard();
}
}
class CardFactory{
static public Card getCreditCard(CardAbstractFactory cardFactory){
return cardFactory.createCreditCard();
}
static public Card getDebitCard(CardAbstractFactory cardFactory){
return cardFactory.createDebitCard();
}
}
class DebitCard extends Card{
}
class CreditCard extends Card{
}
abstract class Card{
int payment;
}
동일하고 일관된 동작(객체 생성)을 하는 팩토리가 많을 때 사용하면 좋을 것 같다.
참고
https://bamdule.tistory.com/157
https://stackoverflow.com/questions/1673841/examples-of-gof-design-patterns-in-javas-core-libraries/2707195#2707195
https://velog.io/@ha0kim/Design-Pattern-%EC%83%9D%EC%84%B1-%ED%8C%A8%ED%84%B4Creational-Patterns
https://gmlwjd9405.github.io/2018/08/08/abstract-factory-pattern.html
반응형
'Clean Code' 카테고리의 다른 글
[Design Pattern] 구조 패턴 - 데코레이터 패턴 (0) | 2022.03.03 |
---|---|
[Design Pattern] 생성 패턴 - 싱글톤 패턴 (0) | 2022.03.03 |
[Design Pattern] 생성 패턴 - 프로토 타입 패턴 (0) | 2022.03.03 |
[Design Pattern] 생성 패턴 - 빌더 패턴 (0) | 2022.03.01 |
[Architecture] 아키텍처 개념 정리 (0) | 2022.02.23 |