[읽기전에]
UML 다이어그램 : UML클래스 다이어그램 기본상식 http://hongjinhyeon.tistory.com/25
포스팅되는 디자인 패턴의 예는 스타크래프트를 기본으로 하였습니다 : 디자인 패턴을 시작하며 http://hongjinhyeon.tistory.com/24
<기본 정의 >
1. Abstract Factory Pattern 정의
- 구체적인 클래스를 명시하지 않고도 연관되어 있거나 의존적인 객체 패밀리 생성을 위한 인터페이스 제공.
(Provide an interface for creating families of related or dependent objects without specifying their concrete classes.)
- 예를 들어서, 곰 세마리 가족(아빠,엄마,아기) 에 대한 대화형 어플리케이션을 개발한다고 했을때에 그 어플리케이션에서
두가지 종류의 곰(골든베어가족과 브라운베어가족)을 사용자가 선택해서 이야기를 진행하는 기능이 있다면 사용자의 선택
에 따라서 자동으로 하나의 종류의 아빠 엄마 아기가 생성되어야 한다. 그때 골든베어를 선택하면 자동으로 GoldenDadBear,
GoldenMomBear, GoldenBabyBear 를 생성해주고 반대로 브라운을 선택하면 BrownDadBear, BrownMomBear, BrownBabyBear
을 생성해주어야 한다.
- 즉, 비슷한 기능을 하지만 종류가 다른 클래스들을 생성하는 인터페이스 제공한다.
2.UML Diagram
3. 사용 용도 및 장점
-Factory Method Pattern의 장점을 거의 동일하게 가진다.
①객체의 생성을 한군데에서 관리를 할수가 있다. (ConcreteCreator 부분에서만 생성코드를 넣는다. )
②동일한 인터페이스 구현으로 새로운 객체가 추가되더라도 소스의 수정의 거의 없다. ( 생성 부분의 수정과 신규 클래스의 추가 정도 )
③객체를 여러군데에서 생성을 각자하면 동일한 생성을 보장 못하지만, 한군데에서 관리하게 되면 동일한 생성을 보장한다.
-연관된 객체들을 생성을 할때 실수로 다른종류의 클래스가 생성이 되는것을 방지한다.
-어플리케이션에서 GUI타입이 여러종류일때, 선택에 따라서 동일한 모양의 GUI타입으로 설정이 된다.
4. 소스
001.
using
System;
002.
003.
namespace
DoFactory.GangOfFour.Abstract.Structural
004.
{
005.
/// <summary>
006.
/// MainApp startup class for Structural
007.
/// Abstract Factory Design Pattern.
008.
/// </summary>
009.
class
MainApp
010.
{
011.
/// <summary>
012.
/// Entry point into console application.
013.
/// </summary>
014.
public
static
void
Main()
015.
{
016.
// Abstract factory #1
017.
AbstractFactory factory1 =
new
ConcreteFactory1();
018.
Client client1 =
new
Client(factory1);
019.
client1.Run();
020.
021.
// Abstract factory #2
022.
AbstractFactory factory2 =
new
ConcreteFactory2();
023.
Client client2 =
new
Client(factory2);
024.
client2.Run();
025.
026.
// Wait for user input
027.
Console.ReadKey();
028.
}
029.
}
030.
031.
/// <summary>
032.
/// The 'AbstractFactory' abstract class
033.
/// </summary>
034.
abstract
class
AbstractFactory
035.
{
036.
public
abstract
AbstractProductA CreateProductA();
037.
public
abstract
AbstractProductB CreateProductB();
038.
}
039.
040.
041.
/// <summary>
042.
/// The 'ConcreteFactory1' class
043.
/// </summary>
044.
class
ConcreteFactory1 : AbstractFactory
045.
{
046.
public
override
AbstractProductA CreateProductA()
047.
{
048.
return
new
ProductA1();
049.
}
050.
public
override
AbstractProductB CreateProductB()
051.
{
052.
return
new
ProductB1();
053.
}
054.
}
055.
056.
/// <summary>
057.
/// The 'ConcreteFactory2' class
058.
/// </summary>
059.
class
ConcreteFactory2 : AbstractFactory
060.
{
061.
public
override
AbstractProductA CreateProductA()
062.
{
063.
return
new
ProductA2();
064.
}
065.
public
override
AbstractProductB CreateProductB()
066.
{
067.
return
new
ProductB2();
068.
}
069.
}
070.
071.
/// <summary>
072.
/// The 'AbstractProductA' abstract class
073.
/// </summary>
074.
abstract
class
AbstractProductA
075.
{
076.
}
077.
078.
/// <summary>
079.
/// The 'AbstractProductB' abstract class
080.
/// </summary>
081.
abstract
class
AbstractProductB
082.
{
083.
public
abstract
void
Interact(AbstractProductA a);
084.
}
085.
086.
087.
/// <summary>
088.
/// The 'ProductA1' class
089.
/// </summary>
090.
class
ProductA1 : AbstractProductA
091.
{
092.
}
093.
094.
/// <summary>
095.
/// The 'ProductB1' class
096.
/// </summary>
097.
class
ProductB1 : AbstractProductB
098.
{
099.
public
override
void
Interact(AbstractProductA a)
100.
{
101.
Console.WriteLine(
this
.GetType().Name +
102.
" interacts with "
+ a.GetType().Name);
103.
}
104.
}
105.
106.
/// <summary>
107.
/// The 'ProductA2' class
108.
/// </summary>
109.
class
ProductA2 : AbstractProductA
110.
{
111.
}
112.
113.
/// <summary>
114.
/// The 'ProductB2' class
115.
/// </summary>
116.
class
ProductB2 : AbstractProductB
117.
{
118.
public
override
void
Interact(AbstractProductA a)
119.
{
120.
Console.WriteLine(
this
.GetType().Name +
121.
" interacts with "
+ a.GetType().Name);
122.
}
123.
}
124.
125.
/// <summary>
126.
/// The 'Client' class. Interaction environment for the products.
127.
/// </summary>
128.
class
Client
129.
{
130.
private
AbstractProductA _abstractProductA;
131.
private
AbstractProductB _abstractProductB;
132.
133.
// Constructor
134.
public
Client(AbstractFactory factory)
135.
{
136.
_abstractProductB = factory.CreateProductB();
137.
_abstractProductA = factory.CreateProductA();
138.
}
139.
140.
public
void
Run()
141.
{
142.
_abstractProductB.Interact(_abstractProductA);
143.
}
144.
}
145.
}
-Client 클래스의 생성자에서 AbstractFactory 객체를 받아서 실제 AbstractProductA, AbstractProductB 를 생성한다.
5.실행결과
ProductB1 interacts with ProductA1
ProductB2 interacts with ProductA2
<실제 적용>
1. UML Diagram
2. 사용 용도 및 장점
-사용자가 선택한 종족(테란, 프로토스, 저그 )에 따라서 생성할 수 있는 빌딩들을 설정할 수 있다.
-보통 종족마다 비슷한 종류의 기능을 하는 건물들이 70~80프로는 비슷하다. 이때 추상팩토리 패턴을 이용해서 구현이 가능하다.
-GUI 설정(지도위에 테두리, 마우스 포인터 등등)도 AbstractProduct로 하나더 생성해서 추가하면 된다.
-추상팩토리를 이용하면 테란이 인구확장으로 파일런을 생성하는 경우는 없앨수 있다.
3. 소스
001.
using
System;
002.
using
System.Collections.Generic;
003.
using
System.Linq;
004.
using
System.Text;
005.
006.
namespace
AbstractFactory
007.
{
008.
class
Program
009.
{
010.
static
void
Main(
string
[] args)
011.
{
012.
Race _race1 =
new
Terran();
013.
Game _game1 =
new
Game(_race1);
014.
_game1.Show();
015.
016.
Race _race2 =
new
Protoss();
017.
Game _game2 =
new
Game(_race2);
018.
_game2.Show();
019.
020.
Console.ReadKey();
021.
}
022.
023.
#region 추상 팩토리 설정
024.
025.
abstract
class
Race
026.
{
027.
public
abstract
MaincenterBuilding CreateMaincenterBuilding();
028.
public
abstract
PopulationBuilding CreatePopulationBuilding();
029.
}
030.
031.
032.
class
Terran : Race
033.
{
034.
public
override
MaincenterBuilding CreateMaincenterBuilding()
035.
{
036.
return
new
CommandCenter();
037.
}
038.
public
override
PopulationBuilding CreatePopulationBuilding()
039.
{
040.
return
new
SupplyDepot();
041.
}
042.
043.
}
044.
045.
class
Protoss : Race
046.
{
047.
public
override
MaincenterBuilding CreateMaincenterBuilding()
048.
{
049.
return
new
Nexus();
050.
}
051.
public
override
PopulationBuilding CreatePopulationBuilding()
052.
{
053.
return
new
Pylon();
054.
}
055.
}
056.
057.
#endregion
058.
059.
#region 추상 Product 클래스 생성
060.
061.
abstract
class
MaincenterBuilding
062.
{
063.
}
064.
065.
abstract
class
PopulationBuilding
066.
{
067.
public
abstract
void
Interact(MaincenterBuilding a);
068.
}
069.
070.
#endregion
071.
072.
#region Product 클래스 생성
073.
074.
class
CommandCenter : MaincenterBuilding
075.
{
076.
}
077.
078.
class
SupplyDepot : PopulationBuilding
079.
{
080.
public
override
void
Interact(MaincenterBuilding a)
081.
{
082.
Console.WriteLine(
this
.GetType().Name +
083.
" interacts with "
+ a.GetType().Name);
084.
}
085.
}
086.
087.
class
Nexus : MaincenterBuilding
088.
{
089.
}
090.
091.
class
Pylon : PopulationBuilding
092.
{
093.
public
override
void
Interact(MaincenterBuilding a)
094.
{
095.
Console.WriteLine(
this
.GetType().Name +
096.
" interacts with "
+ a.GetType().Name);
097.
}
098.
}
099.
100.
#endregion
101.
102.
103.
class
Game
104.
{
105.
private
MaincenterBuilding _maincenterBuilding;
106.
private
PopulationBuilding _populationBuilding;
107.
108.
109.
public
Game(Race _race)
110.
{
111.
_maincenterBuilding = _race.CreateMaincenterBuilding();
112.
_populationBuilding = _race.CreatePopulationBuilding();
113.
}
114.
115.
public
void
Show()
116.
{
117.
_populationBuilding.Interact(_maincenterBuilding);
118.
}
119.
}
120.
121.
}
122.
}
4. 결과
5. 피드백
-Factory Method 패턴과 비슷하지만 그것과는 다르게 연관된 클래스들을(family) 생성한다.
-위의 다이어그램에서 저그가 추가될 시에는 클래스 3개가 추가되고 Game에서 해당 저그를 생성해서 사용해주면 된다.
[참조]
-Professional VB.NET 디자인 패턴
-http://www.dofactory.com
'프로젝트 설계 > 디자인 패턴' 카테고리의 다른 글
5. Decorator Pattern ( 데코레이터 / 장식자 패턴 C# ) (1) | 2012.08.29 |
---|---|
4. Adapter Pattern ( 어댑터 / 적응자 패턴 C# ) (2) | 2012.08.28 |
2. Factory Method Pattern ( 팩토리 매소드 패턴 C# ) (14) | 2012.08.22 |
1. Singleton Pattern(싱글턴 패턴 C#) (17) | 2011.12.15 |
GOF 23개 디자인 패턴 분석 (2) | 2011.12.14 |