๐ ์ถ์ ํฉํ ๋ฆฌ(Abstract Factory) ํจํด - ์๋ฒฝ ๋ง์คํฐํ๊ธฐ
Abstract Factory Pattern
์ถ์ ํฉํ ๋ฆฌ ํจํด์ ์ฐ๊ด์ฑ์ด ์๋ ๊ฐ์ฒด ๊ตฐ์ด ์ฌ๋ฌ๊ฐ ์์ ๊ฒฝ์ฐ ์ด๋ค์ ๋ฌถ์ด ์ถ์ํํ๊ณ , ์ด๋ค ๊ตฌ์ฒด์ ์ธ ์ํฉ์ด ์ฃผ์ด์ง๋ฉด ํฉํ ๋ฆฌ ๊ฐ์ฒด์์ ์งํฉ์ผ๋ก ๋ฌถ์ ๊ฐ์ฒด ๊ตฐ์ ๊ตฌํํ ํ๋ ์์ฑ ํจํด์ด๋ค. ํด๋ผ์ด์ธํธ์์ ํน์ ๊ฐ์ฒด์ ์ฌ์ฉํ ๋ ํฉํ ๋ฆฌ ํด๋์ค๋ง์ ์ฐธ์กฐํ์ฌ ํน์ ๊ฐ์ฒด์ ๋ํ ๊ตฌํ๋ถ๋ฅผ ๊ฐ์ถ์ด ์ญํ ๊ณผ ๊ตฌํ์ ๋ถ๋ฆฌ์ํฌ ์ ์๋ค.
์ฆ, ์ถ์ ํฉํ ๋ฆฌ์ ํต์ฌ์ ์ ํ '๊ตฐ' ์งํฉ์ ํ์ ๋ณ๋ก ์ฐ์ด๋ผ์ ์๋ค๋ ์ ์ด ํฌ์ธํธ ์ด๋ค. ์๋ฅผ๋ค์ด ๋ชจ๋ํฐ, ๋ง์ฐ์ค, ํค๋ณด๋๋ฅผ ๋ฌถ์ ์ ์ ์ ํ๊ตฐ์ด ์๋๋ฐ ์ด๋ค์ ๋ ์ผ์ฑ ์ ํ๊ตฐ์ด๋ ์ ํ ์ ํ๊ตฐ์ด๋ ๋ก์งํ ์ ํ๊ตฐ์ด๋์ ๋ฐ๋ผ ์งํฉ์ด ๋ธ๋๋ ๋ช ์ผ๋ก ์ฌ๋ฌ๊ฐ๋๋ก ๋๋๊ฒ ๋ ๋, ๋ณต์กํ๊ฒ ๋ฌถ์ด๋ ์ด๋ฌํ ์ ํ๊ตฐ๋ค์ ๊ด๋ฆฌ์ ํ์ฅํ๊ธฐ ์ฉ์ดํ๊ฒ ํจํดํ ํ๊ฒ์ด ์ถ์ ํฉํ ๋ฆฌ ์ด๋ค.
์ถ์ ํฉํ ๋ฆฌ ํจํด ๊ตฌ์กฐ
- AbstractFactory : ์ต์์ ๊ณต์ฅ ํด๋์ค. ์ฌ๋ฌ๊ฐ์ ์ ํ๋ค์ ์์ฑํ๋ ์ฌ๋ฌ ๋ฉ์๋๋ค์ ์ถ์ํ ํ๋ค.
- ConcreteFactory : ์๋ธ ๊ณต์ฅ ํด๋์ค๋ค์ ํ์ ์ ๋ง๋ ์ ํ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋๋ก ๋ฉ์๋๋ค์ ์ฌ์ ์ํ๋ค.
- AbstractProduct : ๊ฐ ํ์ ์ ์ ํ๋ค์ ์ถ์ํํ ์ธํฐํ์ด์ค
- ConcreteProduct (ProductA ~ ProductB) : ๊ฐ ํ์ ์ ์ ํ ๊ตฌํ์ฒด๋ค. ์ด๋ค์ ํฉํ ๋ฆฌ ๊ฐ์ฒด๋ก๋ถํฐ ์์ฑ๋๋ค.
- Client : Client๋ ์ถ์ํ๋ ์ธํฐํ์ด์ค๋ง์ ์ด์ฉํ์ฌ ์ ํ์ ๋ฐ๊ธฐ ๋๋ฌธ์, ๊ตฌ์ฒด์ ์ธ ์ ํ, ๊ณต์ฅ์ ๋ํด์๋ ๋ชจ๋ฅธ๋ค.
Abstract Factory vs Factory Method
๋๋ค ํฉํ ๋ฆฌ ๊ฐ์ฒด๋ฅผ ํตํด ๊ตฌ์ฒด์ ์ธ ํ์ ์ ๊ฐ์ถ๊ณ ๊ฐ์ฒด ์์ฑ์ ๊ด์ฌํ๋ ํจํด ์์๋ ๋์ผํ๋ค. ๋ํ ๊ณต์ฅ ํด๋์ค๊ฐ ์ ํ ํด๋์ค๋ฅผ ๊ฐ๊ฐ ๋๋์ด ๋์จํ ๊ฒฐํฉ ๊ตฌ์กฐ๋ฅผ ๊ตฌ์ฑํ๋ ๋ชจ์ต ์ญ์ ๋์ด ์ ์ฌํ๋ค.
๊ทธ๋ฌ๋ ์ฃผ์ํ ๊ฒ์ ์ถ์ ํฉํ ๋ฆฌ ํจํด์ด ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ์์ ํธํ์ด ์๋๋ผ๋ ์ ์ด๋ค. ๋ ํจํด์ ์ฐจ์ด๋ ๋ช
ํํ๊ธฐ ๋๋ฌธ์ ์ํฉ์ ๋ฐ๋ผ ์ ์ ํ ์ ํ์ ํด์ผ ํ๋ค.
์๋ฅผ๋ค์ด ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ๊ฐ์ฒด ์์ฑ ์ดํ ํด์ผ ํ ์ผ์ ๊ณตํต์ ์ ์ ์ํ๋๋ฐ ์ด์ ์ ๋ง์ถ๋ ๋ฐ๋ฉด, ์ถ์ ํฉํ ๋ฆฌ ํจํด์ ์์ฑํด์ผ ํ ๊ฐ์ฒด ์งํฉ ๊ตฐ์ ๊ณตํต์ ์ ์ด์ ์ ๋ง์ถ๋ค.
๋จ, ์ด ๋์ ์ ์ฌ์ ๊ณผ ์ฐจ์ด์ ์ ์กฐํฉํด์ ๋ณตํฉ ํจํด์ ๊ตฌ์ฑํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ค.
ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด | ์ถ์ ํฉํ ๋ฆฌ ํจํด | |
๊ณตํต์ | ๊ฐ์ฒด ์์ฑ ๊ณผ์ ์ ์ถ์ํํ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณต ๊ฐ์ฒด ์์ฑ์ ์บก์ํํจ์ผ๋ก์จ ๊ตฌ์ฒด์ ์ธ ํ์ ์ ๊ฐ์ถ๊ณ ๋์จํ ๊ฒฐํฉ ๊ตฌ์กฐ๋ฅผ ํ๋ฐฉ |
|
์ฐจ์ด์ | ๊ตฌ์ฒด์ ์ธ ๊ฐ์ฒด ์์ฑ๊ณผ์ ์ ํ์ ๋๋ ๊ตฌ์ฒด์ ์ธ ํด๋์ค๋ก ์ฎ๊ธฐ๋ ๊ฒ์ด ๋ชฉ์ | ๊ด๋ จ ์๋ ์ฌ๋ฌ ๊ฐ์ฒด๋ฅผ ๊ตฌ์ฒด์ ์ธ ํด๋์ค์ ์์กดํ์ง ์๊ณ ๋ง๋ค ์ ์๊ฒ ํด์ฃผ๋ ๊ฒ์ด ๋ชฉ์ |
ํ Factory๋น ํ ์ข ๋ฅ์ ๊ฐ์ฒด ์์ฑ ์ง์ | ํ Factory์์ ์๋ก ์ฐ๊ด๋ ์ฌ๋ฌ ์ข ๋ฅ์ ๊ฐ์ฒด ์์ฑ์ ์ง์. (์ ํ๊ตฐ ์์ฑ ์ง์) | |
๋ฉ์๋ ๋ ๋ฒจ์์ ํฌ์ปค์ค๋ฅผ ๋ง์ถค์ผ๋ก์จ, ํด๋ผ์ด์ธํธ์ ConcreteProduct ์ธ์คํด์ค์ ์์ฑ ๋ฐ ๊ตฌ์ฑ์ ๋ํ ์์กด์ ๊ฐ์ | ํด๋์ค(Factory) ๋ ๋ฒจ์์ ํฌ์ปค์ค๋ฅผ ๋ง์ถค์ผ๋ก์จ, ํด๋ผ์ด์ธํธ์ ConcreteProduct ์ธ์คํด์ค ๊ตฐ์ ์์ฑ ๋ฐ ๊ตฌ์ฑ์ ๋ํ ์์กด์ ๊ฐ์ |
์ถ์ ํฉํ ๋ฆฌ ํจํด ํ๋ฆ
ํด๋์ค ๋ค์ด์ด๊ทธ๋จ ๊ทธ๋ฆผ์ ๋ณด๋ฉด ๊ตฌ์ฑ์์์ ํ์ดํ๊ฐ ์ผํค๊ณ ์ฅํ ๋ณต์กํ๊ฒ ๋ณด์ผํ ์ง๋ง, ์ค์ ํ๊ณ ๋ณด๋ฉด ๋ณ๊ฑฐ ์๋ ๊ตฌ์กฐ์ด๋ ๊ฒ ๋จน์ ํ์๊ฐ ์๋ค.
ํด๋์ค ๊ตฌ์ฑ
์ ํ(Product) ํด๋์ค
// Product A ์ ํ๊ตฐ
interface AbstractProductA {
}
// Product A - 1
class ConcreteProductA1 implements AbstractProductA {
}
// Product A - 2
class ConcreteProductA2 implements AbstractProductA {
}
// Product B ์ ํ๊ตฐ
interface AbstractProductB {
}
// Product B - 1
class ConcreteProductB1 implements AbstractProductB {
}
// Product B - 2
class ConcreteProductB2 implements AbstractProductB {
}
๊ณต์ฅ(Factory) ํด๋์ค
interface AbstractFactory {
AbstractProductA createProductA();
AbstractProductB createProductB();
}
// Product A1์ B1 ์ ํ๊ตฐ์ ์์ฐํ๋ ๊ณต์ฅ๊ตฐ 1
class ConcreteFactory1 implements AbstractFactory {
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
}
// Product A2์ B2 ์ ํ๊ตฐ์ ์์ฐํ๋ ๊ณต์ฅ๊ตฐ 2
class ConcreteFactory2 implements AbstractFactory {
public AbstractProductA createProductA() {
return new ConcreteProductA2();
}
public AbstractProductB createProductB() {
return new ConcreteProductB2();
}
}
ํด๋์ค ํ๋ฆ
class Client {
public static void main(String[] args) {
AbstractFactory factory = null;
// 1. ๊ณต์ฅ๊ตฐ 1์ ๊ฐ๋์ํจ๋ค.
factory = new ConcreteFactory1();
// 2. ๊ณต์ฅ๊ตฐ 1์ ํตํด ์ ํ๊ตฐ A1๋ฅผ ์์ฑํ๋๋ก ํ๋ค (ํด๋ผ์ด์ธํธ๋ ๊ตฌ์ฒด์ ์ธ ๊ตฌํ์ ๋ชจ๋ฅด๊ณ ์ธํฐํ์ด์ค์ ์์กดํ๋ค)
AbstractProductA product_A1 = factory.createProductA();
System.out.println(product_A1.getClass().getName()); // ConcreteProductA1
// 3. ๊ณต์ฅ๊ตฐ 2๋ฅผ ๊ฐ๋์ํจ๋ค.
factory = new ConcreteFactory2();
// 4. ๊ณต์ฅ๊ตฐ 2๋ฅผ ํตํด ์ ํ๊ตฐ A2๋ฅผ ์์ฑํ๋๋ก ํ๋ค (ํด๋ผ์ด์ธํธ๋ ๊ตฌ์ฒด์ ์ธ ๊ตฌํ์ ๋ชจ๋ฅด๊ณ ์ธํฐํ์ด์ค์ ์์กดํ๋ค)
AbstractProductA product_A2 = factory.createProductA();
System.out.println(product_A2.getClass().getName()); // ConcreteProductA2
}
}
์ฝ๋๋ฅผ ๋ณด๋ฉด ๋๊ฐ์ createProductA() ๋ฉ์๋๋ฅผ ํธ์ถํ์ง๋ง ์ด๋ค ํฉํ ๋ฆฌ ๊ฐ์ฒด์ด๋์ ๋ฐ๋ผ ๋ฐํ๋๋ ์ ํ๊ตฐ์ด ๋ค๋ฅด๊ฒ ๋๋ค.
์ถ์ ํฉํ ๋ฆฌ ํจํด ํน์ง
ํจํด ์ฌ์ฉ ์๊ธฐ
- ๊ด๋ จ ์ ํ์ ๋ค์ํ ์ ํ ๊ตฐ๊ณผ ํจ๊ป ์๋ํด์ผ ํ ๋, ํด๋น ์ ํ์ ๊ตฌ์ฒด์ ์ธ ํด๋์ค์ ์์กดํ๊ณ ์ถ์ง ์์ ๊ฒฝ์ฐ
- ์ฌ๋ฌ ์ ํ๊ตฐ ์ค ํ๋๋ฅผ ์ ํํด์ ์์คํ ์ ์ค์ ํด์ผํ๊ณ ํ ๋ฒ ๊ตฌ์ฑํ ์ ํ์ ๋ค๋ฅธ ๊ฒ์ผ๋ก ๋์ฒดํ ์๋ ์์ ๋
- ์ ํ์ ๋ํ ํด๋์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ๊ณตํ๊ณ , ๊ทธ๋ค์ ๊ตฌํ์ด ์๋ ์ธํฐํ์ด์ค๋ฅผ ๋ ธ์ถ์ํค๊ณ ์ถ์ ๋
ํจํด ์ฅ์
- ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ์ฝ๋๋ฅผ ๋ถ๋ฆฌํ์ฌ ํด๋ผ์ด์ธํธ ์ฝ๋์ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ ์ ์๋ค.
- ์ ํ ๊ตฐ์ ์ฝ๊ฒ ๋์ฒด ํ ์ ์๋ค.
- ๋จ์ผ ์ฑ ์ ์์น ์ค์
- ๊ฐ๋ฐฉ / ํ์ ์์น ์ค์
ํจํด ๋จ์
- ๊ฐ ๊ตฌํ์ฒด๋ง๋ค ํฉํ ๋ฆฌ ๊ฐ์ฒด๋ค์ ๋ชจ๋ ๊ตฌํํด์ฃผ์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด๊ฐ ๋์ด๋ ๋ ๋ง๋ค ํด๋์ค๊ฐ ์ฆ๊ฐํ์ฌ ์ฝ๋์ ๋ณต์ก์ฑ์ด ์ฆ๊ฐํ๋ค. (ํฉํ ๋ฆฌ ํจํด์ ๊ณตํต์ ์ธ ๋ฌธ์ ์ )
- ๊ธฐ์กด ์ถ์ ํฉํ ๋ฆฌ์ ์ธ๋ถ์ฌํญ์ด ๋ณ๊ฒฝ๋๋ฉด ๋ชจ๋ ํฉํ ๋ฆฌ์ ๋ํ ์์ ์ด ํ์ํด์ง๋ค. ์ด๋ ์ถ์ ํฉํ ๋ฆฌ์ ๋ชจ๋ ์๋ธํด๋์ค์ ์์ ์ ๊ฐ์ ธ์จ๋ค.
- ์๋ก์ด ์ข ๋ฅ์ ์ ํ์ ์ง์ํ๋ ๊ฒ์ด ์ด๋ ต๋ค. ์๋ก์ด ์ ํ์ด ์ถ๊ฐ๋๋ฉด ํฉํ ๋ฆฌ ๊ตฌํ ๋ก์ง ์์ฒด๋ฅผ ๋ณ๊ฒฝํด์ผํ๋ค.
์์ ๋ฅผ ํตํด ์์๋ณด๋ ์ถ์ ํฉํ ๋ฆฌ ํจํด
๋ง์ ์ฌ๋๋ค์ด ์ถ์ ํฉํ ๋ฆฌ์ ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด ์ฐจ์ด์ ๋ํด ํ๊น๋ ค ํ๋ค. ์๋ํ๋ฉด ๋์ด ํฉํ ๋ฆฌ ๊ฐ์ฒด๊ฐ ๋์ ์ ํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค๋ ์ ์์ ๊ตฌ์กฐ๊ฐ ๊ฑฐ์ ๋์ผํ๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋์ ์ด๋ค ๋์์ธ ํจํด ์์ ์์๋ ์ถ์ ํฉํ ๋ฆฌ์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ํ๋์ ํฉํ ๋ฆฌ ํจํด ์นดํ ๊ณ ๋ฆฌ๋ก์ ๋ค๋ฃจ๊ธฐ๋ ํ๋ค.
ํ์ง๋ง ์ด ๋์ ์์ ํ ๋ณ๊ฐ์ ํจํด์ด๋ค. ๋ฐ๋ผ์ ์ด๋ฒ ์น์ ์์๋ ๋ ์๋ค์ ์๋ฒฝํ ์ดํด๋ฅผ ๋๊ธฐ ์ํด ์์ ๋ฅผ ํตํด ํฉํ ๋ฆฌ ๋ฉ์๋์ ์ถ์ ํฉํ ๋ฆฌ๋ฅผ ๊ฐ๊ฐ ๊ตฌํํด๋ณด๊ณ ์ด ๋์ ์งฌ๋ฝํด๋ณด๋ ์๊ฐ์ ๊ฐ์ ธ๋ณผ ์์ ์ด๋ค.
์ปดํจํฐ ํ๋ฉด์ ์ปดํฌ๋ํธ ์์๋ค์ ํ๋ฉด์ ๊ทธ๋ฆฌ๋ ๋ก์ง์ ๊ตฌํํ๋ค๊ณ ํ๋ค. ๋ฒํผ(Button), CheckBox(์ฒดํฌ๋ฐ์ค), TextEdit(ํ ์คํธ๋ฐ์ค) 3๊ฐ์ง ์์๋ฅผ ํ๋ฉด์ ๊ทธ๋ฆฌ๊ธฐ ์ํด ๊ฐ๊ธฐ ๊ฐ์ฒด๋ก ์ง์ ํ๋ค. ๊ทธ๋ฐ๋ฐ ์ปดํจํฐ OS์๋ ์๋์ฐ(Window)์ ๋งฅ(Mac) ์ข ๋ฅ๊ฐ ๋๋๋๋ฐ ์ด๋ค OS๋์ ๋ฐ๋ผ์ ๋ชจ์์ด ๋ฌ๋ผ์ง ์ ์๊ธฐ ๋๋ฌธ์ ๊ฐ๊ธฐ ์์ฑํ์ฌ ๊ตฌํํ์ฌ์ผ ํ๋ค๊ณ ํ๋ค.
์ ๋ฆฌํ๋ฉด ์ด 3๊ฐ์ง ๊ฐ์ฒด๋ค์ ํ๋์ ์ปดํฌ๋ํธ(Component) ๊ตฐ์ผ๋ก ๋ฌถ์์ ์์ผ๋ฉฐ ๋ํ OS๋ณ ๊ตฐ์ผ๋ก ๋๋๊ฒ ๋๋ค.
์์ ์ปดํฌ๋ํธ๋ค์ ์ฝ๋๋ก ํํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
interface Component {
void render(); // ์์ ๊ทธ๋ฆฌ๊ธฐ
}
/* ---------------------------------------------------------- */
abstract class Button implements Component {
}
class WindowButton extends Button {
@Override
public void render() {
System.out.println("์๋์ฐ ๋ฒํผ ์์ฑ ์๋ฃ");
}
}
class MacButton extends Button {
@Override
public void render() {
System.out.println("๋งฅ ๋ฒํผ ์์ฑ ์๋ฃ");
}
}
/* ---------------------------------------------------------- */
abstract class CheckBox implements Component {
}
class WindowCheckBox extends CheckBox {
@Override
public void render() {
System.out.println("์๋์ฐ ์ฒดํฌ๋ฐ์ค ์์ฑ ์๋ฃ");
}
}
class MacCheckBox extends CheckBox {
@Override
public void render() {
System.out.println("๋งฅ ์ฒดํฌ๋ฐ์ค ์์ฑ ์๋ฃ");
}
}
/* ---------------------------------------------------------- */
abstract class TextEdit implements Component {
}
class WindowTextEdit extends TextEdit {
@Override
public void render() {
System.out.println("์๋์ฐ ํ
์คํธ๋ฐ์ค ์์ฑ ์๋ฃ");
}
}
class MacTextEdit extends TextEdit {
@Override
public void render() {
System.out.println("๋งฅ ํ
์คํธ๋ฐ์ค ์์ฑ ์๋ฃ");
}
}
ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ผ๋ก ๊ตฌํ
์์ ๊ตฌ์ฑ์ ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ผ๋ก ๊ตฌํํด๋ณด์. ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ๊ณต์ฅ ๊ฐ์ฒด๋ ํ๊ฐ์ง ์ข ๋ฅ์ ์ปดํฌ๋ํธ๋ง ์์ฑํ๋ ๊ตฌ์กฐ์ด๋ค. ํฉํ ๋ฆฌ ๋ฉ์๋์ ์ด์ ์ ์ถ์ํ๋ ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ๊ฐ ์๋ธ ๊ณต์ฅ ํด๋์ค๊ฐ ์ฌ์ ์ํ์ฌ ๊ฑธ๋ง๋ ์ ํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋ฒํผ์ ์์ฑํ๋ค๊ณ ํ๋๋ผ๋ ์ด๋ OS ์คํํ๊ฒฝ์ธ์ง๋ ๋ฉ์๋ ๋ด์์ ๋ถ๊ธฐ๋ฌธ์ ํตํด ๊ตฌ๋ถํด ์ฃผ์ด์ผ ํ๋ค.
interface ComponentFactoryMethod {
Component createOperation(String type); // ํ
ํ๋ฆฟ
Component createComponent(String type); // ํฉํ ๋ฆฌ ๋ฉ์๋
}
class ButtonFactory implements ComponentFactoryMethod {
public Button createOperation(String type) {
Button button = createComponent(type);
button.์ถ๊ฐ์ค์ ();
return button;
}
public Button createComponent(String type) {
Button button = null;
switch (type.toLowerCase()) {
case "window":
button = new WindowButton();
break;
case "mac":
button = new MacButton();
break;
}
return button;
}
}
class CheckBoxFactory implements ComponentFactoryMethod {
public CheckBox createOperation(String type) {
CheckBox checkbox = createComponent(type);
checkbox.์ถ๊ฐ์ค์ ();
return checkbox;
}
public CheckBox createComponent(String type) {
CheckBox checkbox = null;
switch (type.toLowerCase()) {
case "window":
checkbox = new WindowCheckBox();
break;
case "mac":
checkbox = new MacCheckBox();
break;
}
return checkbox;
}
}
class TextEditFactory implements ComponentFactoryMethod {
public TextEdit createOperation(String type) {
TextEdit txtedit = createComponent(type);
txtedit.์ถ๊ฐ์ค์ ();
return txtedit;
}
public TextEdit createComponent(String type) {
TextEdit txtedit = null;
switch (type.toLowerCase()) {
case "window":
txtedit = new WindowTextEdit();
break;
case "mac":
txtedit = new MacTextEdit();
break;
}
return txtedit;
}
}
public static void main(String[] args) {
ComponentFactoryMethod factory = null;
Button btn = null;
CheckBox chkBox = null;
// ์๋์ฐ ๋ฒํผ ์์ฑ
factory = new ButtonFactory();
btn = (Button) factory.createOperation("Window");
btn.render();
// ๋งฅ ๋ฒํผ ์์ฑ
btn = (Button) factory.createOperation("Mac");
btn.render();
// ์๋์ฐ ์ฒดํฌ ๋ฐ์ค ์์ฑ
factory = new CheckBoxFactory();
chkBox = (CheckBox) factory.createOperation("Window");
chkBox.render();
// ๋งฅ ์ฒดํฌ ๋ฐ์ค ์์ฑ
chkBox = (CheckBox) factory.createOperation("Mac");
chkBox.render();
}
ํฉํ ๋ฆฌ ๋ฉ์๋์ ๋ฌธ์ ์
ํฉํ ๋ฆฌ ๋ฉ์๋ก ๊ตฌํํด๋ณธ ์ฝ๋๋ ์คํ ์์ฒด๋ ๋ฌธ์ ๊ฐ ์์ด ๋ณด์ด์ง๋ง, ๋ง์ผ ๊ธฐ๋ฅ์ ํ์ฅํ ํ์๊ฐ ์์ ๋ ๋ฌธ์ ๊ฐ ์๊ธฐ๊ฒ ๋๋ค. ์๋ฅผ ๋ค์ด OS ์ข ๋ฅ์ Linux๋ฅผ ์๋ก ์ถ๊ฐํ๋ค๊ณ ์๊ฐํด๋ณด์. ๊ทธ๋ฌ๋ฉด ๊ฐ ๋ฉ์๋๋ง๋ค ์๋ ๋ถ๊ธฐ๋ฌธ ๋ก์ง์ ์ผ์ผํ ์์ ํ์ฌ์ผ ํ๋๋ฐ, ๊ทธ๋ฌ๋ฉด OCP ์์น์ ์๋ฐฐ๋๋ ๊ผด์ด ๋๋ค.
์ถ์ ํฉํ ๋ฆฌ ํจํด์ผ๋ก ๊ตฌํ
๊ทธ๋ผ ์ถ์ ํฉํ ๋ฆฌ ํจํด์ผ๋ก ๊ตฌํํ๋ฉด ์ด๋จ๊น?
ํฉํ ๋ฆฌ ๋ฉ์๋์ ๊ณต์ฅ ๊ฐ์ฒด๋ ํ ์ข ๋ฅ์ ์ปดํฌ๋ํธ๋ง ์์ฑํ์ง๋ง, ์ถ์ ํฉํ ๋ฆฌ์ ๊ณต์ฅ ๊ฐ์ฒด๋ ํ๋์ ๊ฐ์ฒด์์ ์ฌ๋ฌ ์ข ๋ฅ์ ์ปดํฌ๋ํธ๋ค์ ๊ณจ๋ผ ์์ฐํ ์ ์๋๋ก ๊ตฌ์ฑํ๋ค.
interface ComponentAbstractFactory {
Button createButton();
CheckBox createCheckBox();
TextEdit createTextEdit();
}
class WindowFactory implements ComponentAbstractFactory {
@Override
public Button createButton() {
return new WindowButton();
}
@Override
public CheckBox createCheckBox() {
return new WindowCheckBox();
}
@Override
public TextEdit createTextEdit() {
return new WindowTextEdit();
}
}
class MacFactory implements ComponentAbstractFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public CheckBox createCheckBox() {
return new MacCheckBox();
}
@Override
public TextEdit createTextEdit() {
return new MacTextEdit();
}
}
public static void main(String[] args) {
ComponentAbstractFactory factory = null;
// ์๋์ฐ ๋ฒํผ ์์ฑ
factory = new WindowFactory();
Button WindowBtn = createBtn(factory);
WindowBtn.render();
// ๋งฅ ๋ฒํผ ์์ฑ
factory = new MacFactory();
Button MacBtn = createBtn(factory);
MacBtn.render();
}
// ์ถ์ ํฉํ ๋ฆฌ์์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ถ๋ถ ์ฝ๋๋ ๊ฐ๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ๋ฉ์๋๋ก ๋ฌถ์ ๋ถ๋ฆฌ
public static Button createBtn(ComponentAbstractFactory fac) {
return fac.createButton();
}
๊ธฐ์กด ํฉํ ๋ฆฌ ๋ฉ์๋์์๋ ๋ค๋ฅธ OS์ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ๊ธฐ ์ํด์ ๋ฌธ์์ด์ ์ธ์๋ก ์ฃผ์ด ๋ฉ์๋ ๋ด์์ ๋ถ๊ธฐ๋ฌธ์ผ๋ก ๊ฐ์ฒด ์์ฑ์ ์ฒ๋ฆฌํ์์ง๋ง, ์ถ์ ํฉํ ๋ฆฌ์์ ์ด๋ ํ ํฉํ ๋ฆฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋๋์ ๋ฐ๋ผ ๋๊ฐ์ ๋ฉ์๋๋ฅผ ํธ์ถํด๋ ๋ฐํ๋๋ ๊ฒฐ๊ณผ๊ฐ ๋ค๋ฅด๊ฒ ๋๋ค.
ํ์ง๋ง ์ฐฉ๊ฐํ์ง ๋ง์์ผ ํ ๊ฒ์ด ์ถ์ ํฉํ ๋ฆฌ๊ฐ ํฉํ ๋ฆฌ ๋ฉ์๋๋ณด๋ค ๋ฌด์กฐ๊ฑด ์ข๋ค๋ ๋ง์ด ์๋๋ค. ์ด ์์ ์ฒ๋ผ ์ด๋ ํ ์ ํ๋ค์ ๋ํ '๊ตฐ'์ ๋ฌถ์ด ์์ฑํด์ผ ํ ๋ ์ถ์ ํฉํ ๋ฆฌ๋ก ๊ตฌ์ฑํ๋ ๊ฒ์ด ์ ์ง๋ณด์์ ํ์ฅ์ ์์ด ๋ ์ ๋ฆฌํ๋ค๋ ๊ฒ์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด๋ค.
์ถ์ ํฉํ ๋ฆฌ์ ์ ์ฐํ ํ์ฅ
์๋ฅผ๋ค์ด Linux OS ํ๊ฒฝ์ด ์ถ๊ฐ๋๋ค ํ๋๋ผ๋, ๊ธฐ์กด์ ์ฝ๋ ์์ ์์ด ๋ฆฌ๋ ์ค ์ปดํฌ๋ํธ ๊ตฌํ์ฒด ํด๋์ค์ ๋ฆฌ๋ ์ค ํฉํ ๋ฆฌ ํด๋์ค๋ง ์ ์ ํ๊ฒ ์ถ๊ฐ๋ง ํด์ฃผ๋ฉด ํ์ฅ์ด ์๋ฃ๋๊ฒ ๋๋ค.
๊ธฐ์กด ํฉํ ๋ฆฌ ๋ฉ์๋๋ก ์ค๊ณ ํ์๋๋ ๋ฉ์๋์ ๋ถ๊ธฐ๋ฌธ์ ์ผ์ผํ ๋ฏ์ด ๊ณ ์น๋ ๊ฒ์ ๋นํ๋ฉด ํ์คํ OCP ์์น์ ์์ ์๋ ๋ซํ์๊ณ ํ์ฅ์๋ ์ด๋ ค์๋ค๋ ๋ง์ด ๋ฌด์จ ์๋ฏธ์ธ์ง ์ฒด๊ฐ์ด ์จ๋ค.
์ถ์ ํฉํ ๋ฆฌ์ ๋ฌธ์ ์
๊ทธ๋ฌ๋ ๋ชจ๋ ํ์ฅ์ ๋ํด ์ ์ฐํ๊ฒ ๋์ฒํ ์ ์๋ ๊ฒ์ ์๋๋ค. ์ด๋ฒ์๋ ์๋ก์ด OS ํ๊ฒฝ์ด ์๋ ์๋ก์ด ์ปดํฌ๋ํธ์ธ ํดํ ์ ์ถ๊ฐํ๋ค๊ณ ์๊ฐํด๋ณด์. ๊ทธ๋ฌ๋ฉด ๋ชจ๋ ์๋ธ ํฉํ ๋ฆฌ ํด๋์ค๋ง๋ค ํดํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ createToolTip() ๋ฉ์๋๋ฅผ ์ถ๊ฐ ํด์ผ ๋๋ ์ด๋๋ ์คํ๋ ค ๋ฌธ์ ์ ์ผ๋ก ์์ฉํ๊ฒ ๋๋ค.
์ถ์ ํฉํ ๋ฆฌ ๊ฐ์ฒด ์ฑ๊ธํคํ
๊ธฐ๋ณธ์ ์ผ๋ก ํฉํ ๋ฆฌ ํด๋์ค๋ ํธ์ถ๋๋ฉด ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ๋ง ํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ๋ฅผ ์ํด ๊ฐ ํฉํ ๋ฆฌ ํด๋์ค๋ง๋ค ์ฑ๊ธํค ์ ์ฉ ํ๋ ๊ฒ์ด ์ณ๋ค.
๋ฌผ๋ก ์์ ๊ฐ์ด ๋ฉ์๋ ํธ์ถ์ฉ์ผ๋ก ์ผํ์ฉ์ผ๋ก ์ฐ์ธ ์ธ์คํด์ค๋ JVM์ ๊ฐ๋น์ง ์ปฌ๋ ์ (GC) ์ ์ํด ์๋์ผ๋ก ์ง์์ง์ง๋ง, ์ด๋ฐ ๊ฐ๋น์ง ๊ฐ์ด ๋์ด๋๊ฒ๋๋ฉด ๋์ค์ ๊ฐ์ฒด ์ ๊ฑฐ ๊ณผ์ ์์ Stop-the-world ๊ฐ ์ผ์ด๋๊ฒ ๋๋ค. (ํ๋ก๊ทธ๋จ์ด ๋ ๊ฑธ๋ฆผ)
๋ฐ๋ผ์ ๊ฐ ํฉํ ๋ฆฌ ํด๋์ค๋ค์ ์ฑ๊ธํค(Singleton) ํ ์์ผ ๋ฉ๋ชจ๋ฆฌ ์ ์ผ๋ก ์ต์ ํ๋ฅผ ์ํจ๋ค.
class WindowFactory implements ComponentAbstractFactory {
// ์ฑ๊ธํค ๊ฐ์ฒดํ
private WindowFactory() {
}
private static class SingleInstanceHolder {
private static final WindowFactory INSTANCE = new WindowFactory();
}
public static WindowFactory getInstance() {
return SingleInstanceHolder.INSTANCE;
}
@Override
public Button createButton() {
return new WindowButton();
}
@Override
public CheckBox createCheckBox() {
return new WindowCheckBox();
}
@Override
public TextEdit createTextEdit() {
return new WindowTextEdit();
}
}
class MacFactory implements ComponentAbstractFactory {
// ์ฑ๊ธํค ๊ฐ์ฒดํ
private MacFactory() {
}
private static class SingleInstanceHolder {
private static final MacFactory INSTANCE = new MacFactory();
}
public static MacFactory getInstance() {
return MacFactory.SingleInstanceHolder.INSTANCE;
}
@Override
public Button createButton() {
return new MacButton();
}
@Override
public CheckBox createCheckBox() {
return new MacCheckBox();
}
@Override
public TextEdit createTextEdit() {
return new MacTextEdit();
}
}
์ถ์ ํฉํ ๋ฆฌ + ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด ์กฐํฉ
์ฌ๋๋ค์ด ๋ง์ด๋ค ์ฐฉ๊ฐํ๋ ๋ถ๋ถ์ด ์ถ์ ํฉํ ๋ฆฌ์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ 2์ง ์ ๋คํ์ผ๋ก ์๊ณ ์๋ค๋ ์ ์ด๋ค. ์ด ๋์ ์์ฐํ ๋ณ๊ฐ์ ์ฝ๋ ํจํด์ด๋ค.
ํฉํ ๋ฆฌ ๋ฉ์๋๋ ์ถ์ ๋ฉ์๋๋ฅผ ํตํ ๋ค๋ฅธ ์ ํ ๊ตฌํ๊ณผ ๋๋ถ์ด ๊ฐ์ฒด ์์ฑ์ ๊ดํ ์ ์ฒ๋ฆฌ, ํ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ๋ ๋ก์ง์ด ํต์ฌ์ด๋ฉฐ, ์ถ์ ํฉํ ๋ฆฌ๋ ์ฌ๋ฌ ํ์ ์ ๊ฐ์ฒด ๊ตฐ์ ์์ฑํ ์ ์๋ ๊ฒ์ด ํต์ฌ์ด๋ค. ๋ฐ๋ผ์ ๋์ ์ ์ ํ ์กฐํฉํ์ฌ ์ฌ์ฉํ์ฌ๋ ๋ฌด๊ดํ๋ค. ์๋ ํ์ํ๋ฉด ๋์ ์กฐํฉํ์ฌ ์ฌ์ฉํ์ฌ์ผ ํ๋ค. ์ถ์ ํฉํ ๋ฆฌ์ ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด ๋์ ์กฐํฉํ๊ฒ ๋๋ค๋ฉด, ์ฌ๋ฌ ํ์ ์ ๊ฐ์ฒด ๊ตฐ์ ์์ฑํ๋ฉด์ ๋์์ ํ ํ๋ฆฟ ๋ฉ์๋๋ฅผ ํตํด ์ ์ฒ๋ฆฌ, ํ์ฒ๋ฆฌ ์์ ์ ํด์ฃผ๋ ๊ฒ์ด ๊ฐ๋ฅํด์ง๋ค.
์๋์ ์์ ์ฝ๋๋ OS ๊ตฐ ๋ณ๋ก ์ถ์ ํฉํ ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๋ฉฐ, ๊ฐ ๊ฐ์ฒด ์์ฑ ๋ฉ์๋์ ๋ํด์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ก ๊ตฌ์ฑํ ์์ ์ด๋ค. ํฉํ ๋ฆฌ ๋ฉ์๋์ ํ ํ๋ฆฟ์ ํ๊บผ๋ฒ์ ์ปดํฌ๋ํธ๋ค์ ์์ฑํ๊ณ ์ถ๊ฐ ์ธํ ํ๋ค๋ ์ปจ์ ์ผ๋ก์จ ํ๋์ ๋ฆฌ์คํธ๋ก ๋ฌถ์ด์ ๋ฐํํ๋ค.
๋ง์ผ ๋ฒํผ ๋ฐ๋ก, ์ฒดํฌ๋ฐ์ค ๋ฐ๋ก ํ๊ณ ์ถ๋ค๋ฉด ๋ณ๋์ createButtonOperation() ์ด๋ createCheckBoxOperation() ๋ฉ์๋๋ก ๊ฐ๊ธฐ ๊ตฌํํด์ฃผ๋ฉด ๋๋ค.
interface ComponentAbstractFactoryMethod {
// ์๋ธ ํด๋์ค์์ ๊ตฌํํ ํฉํ ๋ฆฌ ๋ฉ์๋๋ค
Button createButton();
CheckBox createCheckBox();
TextEdit createTextEdit();
// ํฉํ ๋ฆฌ ํ
ํ๋ฆฟ
default List<Component> createOperation() {
Button btn = createButton();
CheckBox chkbox = createCheckBox();
TextEdit txtEdt = createTextEdit();
btn.์ถ๊ฐ์ธํ
();
chkbox.์ถ๊ฐ์ธํ
();
txtEdt.์ถ๊ฐ์ธํ
();
return new ArrayList<Component>(Arrays.asList(btn, chkbox, txtEdt));
}
}
// ์ถ์ ํฉํ ๋ฆฌ
class WindowFactoryMethod implements ComponentAbstractFactoryMethod {
@Override
public Button createButton() {
return new WindowButton();
}
@Override
public CheckBox createCheckBox() {
return new WindowCheckBox();
}
@Override
public TextEdit createTextEdit() {
return new WindowTextEdit();
}
}
// ์ถ์ ํฉํ ๋ฆฌ
class MacFactoryMethod implements ComponentAbstractFactoryMethod {
// ...
}
public static void main(String[] args) {
ComponentAbstractFactoryMethod factory = null;
// ์๋์ฐ ์ปดํฌ๋ํธ ์์ฑ
factory = new WindowFactoryMethod();
List<Component> list = factory.createOperation();
System.out.println(list);
for(Component c: list) {
c.render();
}
}
์ค๋ฌด์์ ์ฐพ์๋ณด๋ ์ถ์ ํฉํ ๋ฆฌ ํจํด
Java
- javax.xml.parsers.DocumentBuilderFactory ์ newInstance()
- javax.xml.transform.TransformerFactory ์ newInstance()
- javax.xml.xpath.XPathFactory ์ newInstance()
DocumentBuilderFactory ์ newInstance()
Java๋ xmlํ์์ ๋ฌธ์๋ฅผ ๊ฐ์ฒดํ ์์ผ ์ดํด๋ณผ ์ ์๋ DocumentBuilder ๊ฐ์ฒด๋ฅผ ์ ๊ณตํ๋๋ฐ ์ด ๊ฐ์ฒด๋ ๋ฐ๋ก DocumentBuilderFactory๋ก๋ถํฐ ์ป์ด์ฌ ์ ์๋ค.
newInstance()๋ฅผ ํตํด ์ป์ด์ค๋ DocumentBuilderFactory ํ์
์ ๊ฐ์ฒด๊ฐ ConcreteFactory์ ํด๋นํ๊ณ ConcreteFactory๊ฐ ์ ๊ณตํ๋ DocumentBuilder๊ฐ ์ถ์ํ๋ ๊ฐ์ฒด(์ ํ)์ ํด๋นํ๊ฒ ๋๋ค.
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
// 1. ๊ณต์ฅ ๊ฐ์ฒด ์์ฑ
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 2. ๊ณต์ฅ ๊ฐ์ฒด๋ฅผ ํตํด ์ถ์ํ๋ ์ ํ ๊ฐ์ฒด ์์ฑ
DocumentBuilder builder = factory.newDocumentBuilder();
// 3. ๊ตฌํ์ฒด ๋ฉ์๋ ์คํ
Document document = builder.parse("src/main/resources/config.xml");
System.out.println(document.getDocumentElement());
}
Spring Framework
FactoryBean
FactoryBean์ ์คํ๋ง์ด ์ ๊ณตํ๋ ์ธํฐํ์ด์ค๋ก, ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณต๋๋ ์คํ๋ง ๊ตฌ๋ฌธ์ผ๋ก๋ ์์ฑ ๋ฐ ๊ด๋ฆฌํ ์ ์๋ ๊ฐ์ฒด๋ฅผ Bean์ผ๋ก ํ์ฉํ ์ ์๊ฒ๋ ์ด๋ํฐ ์ญํ ์ ํ๋ค. ์ฌ๊ธฐ์ ์์ฑ ๋ฐ ๊ด๋ฆฌํ ์ ์๋ ๊ฐ์ฒด๋ ์์ฑ์๊ฐ privateํ ์ฑ๊ธํค ๊ฐ์ฒด ํน์ ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ํตํด ์ป์ด์ค๋ ๊ฐ์ฒด๊ฐ ์ด์ ํด๋นํ๋ค.
์๋ฅผ ๋ค๋ฉด ์๋ Ship ํด๋์ค๋ ์ฑ๊ธํค ์ฒ๋ฆฌ๋ ๊ฐ์ฒด์ด๋ค.
public class Ship {
private static final Ship INSTANCE = new Ship();
private String name = "Singleton_TurtleShip";
private String color = "Green";
private String logo = "\uD83D\uDC22";
private Ship(){}
public static Ship getInstance() {
return INSTANCE;
}
}
๋ง์ฝ ์ฑ๊ธํค ๊ฐ์ฒด๋ฅผ Bean์ผ๋ก ํ์ฉํ๊ณ ์ถ๋ค๋ฉด FactoryBean์ ์ด์ฉํด ๋ฑ๋กํ ์ ์๋ค. FactoryBean์ ๊ตฌํ์ฒด(ShipFactory)๋ฅผ ๋ง๋ค๊ณ ๊ตฌํ์ฒด๋ฅผ Bean์ผ๋ก ๋ฑ๋กํ๋ฉด, ShipFactory์ getObject()์์ ๋ฐํํ๋ ๊ฐ์ฒด๊ฐ ์ต์ข
์ ์ผ๋ก Bean์ผ๋ก ๋ฑ๋ก๋๊ฒ ๋๋ค.
์ฆ, ์ฌ๊ธฐ์ FactoryBean์ ์ถ์ ํฉํ ๋ฆฌ์ AbstractFactory์ ํด๋นํ๊ณ ShipFactory๋ ConcreteFactory์ ํด๋นํ๋ค.
public class ShipFactory implements FactoryBean<Ship> {
@Override
public Ship getObject() throws Exception {
return Ship.getInstance();
}
@Override
public Class<?> getObjectType() {
return Ship.class;
}
}
ํด๋ผ์ด์ธํธ์์ ์คํ ํด๋ณด๋ฉด xml์ ๋ฑ๋ก๋ ์ ๋ณด์ ๋ฐ๋ผ ApplicationContext๋ก๋ถํฐ ๊ฐ์ ธ์ฌ ๋ ShipFactory๊ฐ ์ ๊ณตํ๋ ์ฑ๊ธํค ๊ฐ์ฒด๋ฅผ ์ป์ด์ค๊ฒ ๋๋ค.
<!-- config.xml -->
<bean id="myShip" class="ShipFactory">
</bean>
public static void main(String[] args) throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config.xml");
Ship myShip = applicationContext.getBean("myShip");
System.out.println(myShip);
}
# ์ฐธ๊ณ ์๋ฃ
์ฝ๋ฉ์ผ๋ก ํ์ตํ๋ GoF์ ๋์์ธ ํจํด - ๋ฐฑ๊ธฐ์
https://refactoring.guru/design-patterns/abstract-factory
https://reactiveprogramming.io/blog/en/design-patterns/abstract-factory