GoF 디자인패턴 - Factory Method

Clean Code Big Poo·2025년 6월 3일
0
post-thumbnail

Overview

디자인패턴 시작하기를 보고 정리하기

Factory Method

객체 생성을 위한 디자인 패턴

  • 객체 생성에 필요한 과정을 템플릿 처럼 정해 놓고 각 과정(전처리/후처리)을 다양하게 구현이 가능함
  • 구체적으로 생성할 클래스를 유연하게 정할 수 있음
  • 객체 생성에 대한 인터페이스와 구현의 분리
    • 확장성, 유지보수성 높힘

다이어그램

  • Factory : Item 을 생성하는 절차를 정해주는 역할
    • 추상 클래스로 구체적인 구현은 정해져 있지 않음
  • Item : interface로, 생성될 다양한 종유의 item 을 동일한 타입으로 처리되도록 함.
  • ItemFactory : Factory 클래스를 구현, Item 을 생성하기 위한 각 절차를 구현한 클래스
  • Sword, Shield, Bow : Item 구현 클래스
    • 각 아이템은 생성할 수 있는 개수에 limit 이 있다고 가정

구현 코드

Item

public interface Item {
    void use();
}

Sword

public class Sword implements Item{

    @Override
    public void use() {
        System.out.println("검으로 공격");
    }
}

Bow

public class Bow implements Item{
    @Override
    public void use() {
        System.out.println("화살 쏘기");
    }
}

Shield

public class Shield implements Item{
    @Override
    public void use() {
        System.out.println("방패로 막기");
    }
}

Factory

public abstract class Factory {
    public Item create(String name){
        boolean bCreatable = this.isCreatable(name);
        if(bCreatable){
            Item item = this.createItem(name);
            postProcessItem(name);

            return item;
        }

        return  null;
    }

    public abstract boolean isCreatable(String name);
    public abstract Item createItem(String name);
    public abstract void postProcessItem(String name);
}

ItemFactory

import java.util.HashMap;

public class ItemFactory extends Factory{
    /// 각 아이템의 최대 생성 개수
    /// 현재 생성된 아이템 개수 저장 용도
    private class  ItemData{
        int maxCount;
        int currentCount;
        ItemData(int  maxCount){
            this.maxCount = maxCount;
        }
    }

    private HashMap<String, ItemData> reposioory;

    public ItemFactory(){
        reposioory = new HashMap<String,ItemData>();

        reposioory.put("sword", new ItemData(3));//최대 생성 개수 3
        reposioory.put("shield", new ItemData(2));//최대 생성 개수 2
        reposioory.put("bow", new ItemData(1));//최대 생성 개수 3
    }

    @Override
    public boolean isCreatable(String name) {
       ItemData itemData = reposioory.get(name);

       if(itemData == null){
           System.out.println(name + "은 알 수 없는 아이템");
           return false;
       }

       if (itemData.currentCount >= itemData.maxCount){
           System.out.println(name + "의 품절 아이템");
           return false;
       }

       return true;
    }

    @Override
    public Item createItem(String name) {
        Item item = null;

        if (name.equals("sword") ) item = new Sword();
        if (name.equals("shield")) item = new Shield();
        if (name.equals("bow")) item = new Bow();

        return item;
    }

    @Override
    public void postProcessItem(String name) {
        ItemData itemData = reposioory.get(name);
        if(itemData != null) itemData.currentCount++;
    }
}

Main


import java.util.ArrayList;

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

        Item item1 = factory.create("sword");
        if(item1 != null) item1.use();

        Item item2 = factory.create("sword");
        if(item2 != null) item2.use();

        Item item3 = factory.create("sword");
        if(item3 != null) item3.use();

        Item item4 = factory.create("sword");
        if(item4 != null) item4.use();

        Item item5 = factory.create("sword");
        if(item5 != null) item5.use();

        factory.create("shield");
        factory.create("shield");
        factory.create("shield");
        factory.create("shield");

        factory.create("bow");
        factory.create("bow");
        factory.create("bow");
    }
}

추가 기능 구현하기

Milk

public class Milk implements Item {
    @Override
    public void use() {
        System.out.println("우유를 마십니다.");
    }
}

Bread

public class Bread implements Item {
    @Override
    public void use() {
        System.out.println("빵을 먹습니다.");
    }
}

FoodFactory

public class FoodFactory implements Factory {
    @Override
    public Item create(String name) {
        if ("milk".equalsIgnoreCase(name)) return new Milk();
        if ("bread".equalsIgnoreCase(name)) return new Bread();
        return null;
    }
}

0개의 댓글