Yeongjun's Wicksome documents ๐ŸŒฑ

Factory Method Pattern

Topics: design pattern, java

์˜๋„

๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•˜์ง€๋งŒ, ์–ด๋–ค ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ• ์ง€์— ๋Œ€ํ•œ ๊ฒฐ์ •์€ ์„œ๋ธŒํด๋ž˜์Šค๊ฐ€ ๋‚ด๋ฆฌ๋„๋ก ํ•œ๋‹ค.

Factory Method๋ผ๋Š” ํŒจํ„ด ์ด๋ฆ„์ด ์ ์ ˆํ•˜์ง€ ๋ชปํ•œ๋ฐ, ์ด๋ฆ„์œผ๋กœ ์ธํ•ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ Factory method๋ผ ์˜คํ•ดํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋งŽ์ด ์žˆ๋‹ค(Allen Holub์˜ ๋ง์„ ์ธ์šฉ.) ์ด๋Ÿฐ ์ƒ์„ฑ ๋ฉ”์†Œ๋“œ๊ฐ€ ๋ชจ๋‘ Factory method ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. Template Method์˜ ์ƒ์„ฑ ํŒจํ„ด ๋ฒ„์ „์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ Template Method๋ฅผ ์•Œ์ง€ ๋ชปํ•œ๋‹ค๋ฉด ๊ทธ ํŒจํ„ด์„ ๋จผ์ € ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด Factory Method๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์ˆ˜์›”ํ•  ๊ฒƒ์ด๋‹ค.

์œ„ํ‚ค๋ฐฑ๊ณผ - ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด

๊ตฌ์กฐ

Factory Method Pattern

ํ™œ์šฉ์„ฑ

  • ์–ด๋–ค ํด๋ž˜์Šค๊ฐ€ ์ž์‹ ์ด ์ƒ์„ฑํ•ด์•ผ ํ•˜๋Š” ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๋ฅผ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†์„ ๋•Œ
  • ์ƒ์„ฑํ•  ๊ฐ์ฒด๋ฅผ ๊ธฐ์ˆ ํ•˜๋Š” ์ฑ…์ž„์„ ์ž์‹ ์˜ ์„œ๋ธŒํด๋ž˜์Šค๊ฐ€ ์ง€์ •ํ–ˆ์œผ๋ฉด ํ•  ๋•Œ
  • ๊ฐ์ฒด ์ƒ์„ฑ์˜ ์ฑ…์ž„์„ ๋ช‡ ๊ฐœ์˜ ๋ณด์กฐ ์„œ๋ธŒํด๋ž˜์Šค ๊ฐ€์šด๋ฐ ํ•˜๋‚˜์—๊ฒŒ ์œ„์ž„ํ•˜๊ณ , ์–ด๋–ค ์„œ๋ธŒํด๋ž˜์Šค๊ฐ€ ์œ„์ž„์ž์ธ์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ตญ์†Œํ™”์‹œํ‚ค๊ณ  ์‹ถ์„ ๋•Œ

์˜ˆ์ œ

์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ๋ฌธ์„œ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ์‘์šฉํ”„๋กœ๊ทธ๋žจ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์žˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ์ผ๋‹จ ๋‘ ๊ฐœ์˜ ํฐ ์ถ”์ƒํ™”๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ํ•˜๋‚˜๋Š” Creator(์‘์šฉํ”„๋กœ๊ทธ๋žจ) ์ถ”์ƒ ํด๋ž˜์Šค์ด๊ณ , ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” Product(๋ฌธ์„œ) ์ถ”์ƒ ํด๋ž˜์Šค(ํ˜น์€ ์ธํ„ฐํŽ˜์ด์Šค)์ด๋‹ค. Creator ํด๋ž˜์Šค๋Š” ๋ฌธ์„œ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์–ธ์ œ ๋งŒ๋“ค์ง€๋Š” ์•Œ์ง€๋งŒ, ์–ด๋–ค ๋ฌธ์„œ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š”์ง€๋Š” ์•Œ์ง€ ๋ชปํ•œ๋‹ค. Product ํด๋ž˜์Šค๊ฐ€ ์ถ”์ƒ ํด๋ž˜์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

abstract class Creator {
	public Product newProduct() { return createProduct(); }
	public abstract Product createProduct(); // factory method
}

interface Product {}

ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์€ ์ด๋Ÿฐ ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๋ฒ•์„ ์ œ์‹œํ•œ๋‹ค. Document์˜ ์„œ๋ธŒํด๋ž˜์Šค ์ค‘ ์–ด๋Š ๊ฒƒ์„ ์ƒ์„ฑํ•ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์บก์Šํ™”ํ•˜๊ณ , ๊ทธ๊ฒƒ์„ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๋–ผ์–ด๋‚ธ๋‹ค.

public class TextProduct implements Product {}
public class PhotoProduct implements Product {}

TextProduct ํด๋ž˜์Šค์™€ PhotoProduct ํด๋ž˜์Šค๋ฅผ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์„ ํ™œ์šฉํ•˜์—ฌ ์ƒ์„ฑํ•œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

๋ฐฉ๋ฒ• 1) ์ถ”์ƒ ํด๋ž˜์Šค

์‚ฌ์šฉ์ž๋Š” ํŠน์ • ์‘์šฉํ”„๋กœ๊ทธ๋žจ์— ์ข…์†์ ์ธ ๊ตฌํ˜„์„ ์œ„ํ•ด์„œ ๋‘ ํด๋ž˜์Šค์˜ ์„œ๋ธŒ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. Creator ํด๋ž˜์Šค๋Š” Product ๊ฐ์ฒด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ฑ…์ž„์„ ๋งก๊ณ  ์žˆ์œผ๋ฉฐ, ํ•„์š”์— ๋”ฐ๋ผ ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

// factory pattern example with abstract class
Creator textCreator = new TextCreator();
Product p1 = textCreator.newProduct();

Creator photoCreator = new PhotoCreator();
Product p2 = photoCreator.newProduct();
public class TextCreator extends Creator {
	@Override
	public Product createProduct() {
		return new WordProduct();
	}
}
public class PhotoCreator extends Creator {
	@Override
	public Product createProduct() {
		return new PhotoProduct();
	}
}
public class TextProduct implements Product {}
public class PhotoProduct implements Product {}

๋ฐฉ๋ฒ• 2) ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” - abstract factory pattern

ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„์„œ ์–ด๋–ค ์ข…๋ฅ˜์˜ ์ œํ’ˆ์„ ์ƒ์„ฑํ• ์ง€ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค. (์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด์€ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ•  ๋•Œ๊ฐ€ ๋งŽ๋‹ค)

// Factory pattern example using argument
Product p1 = Creator1.create(ProductType.TEXT);
Product p2 = Creator1.create(ProductType.PHOTO);
public enum ProductType {
	TEXT, PHOTO
}
public class Creator {
	static public Product create(ProductType type) {
		switch (type) {
			case TEXT:
				return new ExcelProduct();
			case PHOTO:
				return new ImageProduct();
			default:
				return null;
		}
	}
}

๋ฐฉ๋ฒ• 3) Lazy Initialization ๊ธฐ๋ฒ•

์ธ์Šคํ„ด์Šคํ™”ํ•˜๋Š” ์ ‘๊ทผ์ž ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์ธ์Šคํ„ด์Šค์— ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ, ์ƒ์„ฑ์ž์—์„œ ์•„๋ฌด ์˜๋ฏธ ์—†๋Š” ๊ฐ’์œผ๋กœ ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ , ์ ‘๊ทผ์ž ๋ฉ”์„œ๋“œ๊ฐ€ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ƒ์„ฑ์ž๊ฐ€ ์ดˆ๊ธฐํ™” ์‹œํ‚ค๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํ•„์š”ํ•œ ์‹œ์ ์—์„œ ์ดˆ๊ธฐํ™”๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฐ ๊ธฐ๋ฒ•์„ Lazy Initialization์ด๋ผ๊ณ  ํ•œ๋‹ค.

// factory pattern with lazy initialization
TextCreator textCreator = new TextCreator();
List collection = textCreator.newCollection();
public class TextCreator extends Creator {
	@Override
	protected List createCollection() {
		return new ArrayList<TextProduct>();
	}
}
public abstract class Creator {
	private List<Product> collection = null;

	public List newCollection() {
		// lazy initialization
		if (collection == null) {
			collection = createCollection();
		}
		return collection;
	}

	// factory method
	abstract protected List createCollection();
}

๋ฐฉ๋ฒ• 4) ํ…œํ”Œ๋ฆฟ ํ™œ์šฉ

ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ƒ๊ธธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์  ์ค‘ ํ•˜๋‚˜๋Š” Product ํด๋ž˜์Šค ํ•˜๋‚˜๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค ํ•  ๋•Œ๋งˆ๋‹ค Creator ํด๋ž˜์Šค๋ฅผ ์„œ๋ธŒํด๋ž˜์‹ฑํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค(๋ฐฉ๋ฒ• 1). ์ด๋กœ์จ ํด๋ž˜์Šค ๊ณ„ํ†ต์˜ ๋ถ€ํ”ผ๊ฐ€ ํ™•์žฅ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋Š” Creator ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š” ์ œ๋„ค๋ฆญ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๊ณ  Product ํด๋ž˜์Šค๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋˜๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค.

// factory pattern example whti template
StandardCreator<WordProduct> wordProductCreator = new StandardCreator<>(WordProduct.class);
Product p1 = wordProductCreator.newProduct();

StandardCreator<ImageProduct> imageProductCreator = new StandardCreator<>(ImageProduct.class);
Product p2 = imageProductCreator.newProduct();
/**
 * Creator Template
 * @param <T> product type
 */
public class StandardCreator<T extends Product> extends Creator {
	private Class<T> cls;

	public StandardCreator(Class<T> cls) {
		this.cls = cls;
	}

	@Override
	public Product createProduct() {
		T product = null;
		try {
			product = cls.newInstance();
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		}
		return product;
	}
}

์•„๋ž˜ ์ฑ…๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ํ•™์Šตํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌ/๊ธฐ๋กํ•œ ํฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ฑ…์„ ์ฐธ๊ณ ํ•˜์‹œ๊ธฐ ๋ฐ”๋ผ๋ฉฐ, ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ์—ฐ๋ฝ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

  • [GOF{kr}:156] - ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ
  • GoF, ๊น€์ •์•„(์˜ฎ๊ธด์ด), Design Patterns, ๊ฐœ์ •ํŒ, ํ”„๋กœํ…๋ฏธ๋””์–ด, 2015.

Comments

Previous Post
Next PostTemplate Method Pattern