[Design Pattern] Factory Method 팩토리 메소드 패턴

이은수, Lee EunSoo·2024년 10월 5일
0

DesignPattern

목록 보기
6/12
post-thumbnail

개요

지난시간엔 템플릿 메소드 패턴에 대해 알아보았다.

팩토리 메소드 패턴은 구조가 비슷한데 인스턴스를 템플릿 메소드 패턴처럼 다루는 패턴이다.
(안봐도 되긴한데 보고오면 더 좋다, 템플릿메소드패턴)

설명

팩토리 메소드 패턴은 인스턴스 생성방법을 상위 클래스에서 형태만 정의하고 하위 클래스에서 정확하게 구현하는 패턴이다

이는 객체 생성을 특정 클래스의 인스턴스를 해당 클래스의 생성자를 통해서 만드는것이 아닌 특정 메소드를 통해서 객체를 생성(싱글톤에서 사용하는 방식) 하기에 가능한 형태이다.

템플릿 메소드 패턴처럼 팩토리 메소드 패턴에도 팩토리 메소드라는 존재가 있다
여기서 객체를 생성하고 템플릿메소드처럼 객체 생성에 필요한 클래스 내 추상 함수를 호출해서 구현한다.

형태

추상적인 구조는 이미지와 같다.

특징

  • 프레임워크와 내용 부분으로 나뉜다.
  • new와 생성자를 이용하지 않고 객체를 생성한다.
  • factory method를 구현하는 2가지 방법이 있다.
    • 추상메소드를 이용
    • 기본으로 의미없는 객체를 만드는 메소드를 만든다.
  • java의 static Factory Method
    • GoF의 Factory Method의 변형으로, Java에서 객체를 생성할 때new 를 사용하지 않고, static 메소드를 사용하는 기법
    • 싱글톤의 getInstanse()가 대표적인 예

코드

다음과 같은 구조의 소스코드이다

Java

package framework;

public abstract class Product {
    public abstract void use();
}

package framework;

public abstract class Factory {
    public final Product create(String owner) {
        Product p = createProduct(owner);
        //Product p = this.createProduct(owner);
        registerProduct(p);
        return p;
    }

    protected abstract Product createProduct(String owner);
    protected abstract void registerProduct(Product product);
}

package idcard;

public class IDCard extends Product {
    private String owner;

    IDCard(String owner) {
        System.out.println(owner + "의 카드를 만듭니다.");
        this.owner = owner;
    }
    @Override
    public void use() {
        System.out.println(this + "을 사용합니다.");
    }
    @Override
    public String toString() {
        return "[IDCard:" + owner + "]";
    }
    public String getOwner() {
        return owner;
    }
}

package idcard;

public class IDCardFactory extends Factory {

	//객체 생성
    @Override
    protected Product createProduct(String owner) {
        return new IDCard(owner);
    }

    @Override
    protected void registerProduct(Product product) {
        System.out.println(product + "을 등록했습니다");
    }
}

import framework.Factory;
import framework.Product;
import idcard.IDCardFactory;

public class Main {
    public static void main(String[] args) {
        Factory factory = new IDCardFactory();

        Product card1 = factory.create("Youngjin Kim");
        Product card2 = factory.create("Heungmin Son");
        Product card3 = factory.create("Kane");
        card1.use();
        card2.use();
        card3.use();
    }
}

Factory가 Creator
IDCardFactory가 Concreatecreator
Product는 그대로
IDCard는 ConcreateProduct의 역할을 수행한다.

전체적으로 factory가 생성을 Product가 틀의 역할을 맡는 느낌이라고 생각하면 된다.

실행결과

Swift

import Foundation

// Product 프로토콜 정의
//CustomStringConvertible: java의 toString()을 대체 하기 위해 print할때 문자열을 수정할 수 있게 해주는 프로토콜
protocol Product: CustomStringConvertible {
    func use()
}

// Factory 프로토콜 정의
protocol Factory {
    func createProduct(owner: String) -> Product
    func registerProduct(product: Product)
}

// Factory 프로토콜 확장, 기본 구현 메소드인 create를 위해서 확장을 사용함
extension Factory {
    func create(owner: String) -> Product {
        let product = createProduct(owner: owner)
        registerProduct(product: product)
        return product
    }
}

// IDCard 클래스
class IDCard: Product {
    private let owner: String
    
    init(owner: String) {
        self.owner = owner
        print("\(owner)의 카드를 만듭니다.")
    }
    
    func use() {
        // self를 사용하여 출력
        print("\(self) 을 사용합니다.")
    }
    
    // CustomStringConvertible을 사용하여 self를 출력
    var description: String {
        return "[IDCard: \(owner)]"
    }
    
    func getOwner() -> String {
        return owner
    }
}

// IDCardFactory 클래스
class IDCardFactory: Factory {
    
    func createProduct(owner: String) -> Product {
        return IDCard(owner: owner)
    }
    
    func registerProduct(product: Product) {
        // self를 사용하여 출력
        print("\(product) 을 등록했습니다.")
    }
}

// 메인 실행
let factory = IDCardFactory()

let card1 = factory.create(owner: "Youngjin Kim")
let card2 = factory.create(owner: "Heungmin Son")
let card3 = factory.create(owner: "Kane")

card1.use()
card2.use()
card3.use()

swift에는 추상클래스가 없어서 프로토콜을 사용하고 기본구현이 필요했던 create()메소드의 경우 extension의 기본구현 기능을 이용해서 구현했다

또한 toString()을 이용한 콘솔 출력방법이 Swift에서는 지원하지 않으므로 CustomStringConvertible프로토콜을 이용해서 print되는 텍스트를 수정하도록 하였다.

profile
iOS 개발자 취준생, 천 리 길도 한 걸음부터

0개의 댓글