โ๏ธ Java Design-Pattern โ จ - Abstract Factory
โ๏ธ Java Design-Pattern โ
จ - Abstract Factory
๐
ใJAVA ์ธ์ด๋ก ๋ฐฐ์ฐ๋ ๋์์ธ ํจํด : ์ฝ๊ฒ ๋ฐฐ์ฐ๋ GoF์ 23๊ฐ์ง ๋์์ธ ํจํดใ
๋ฅผ ์ฝ๊ณ ์ ๋ฆฌํ ๊ธ์ ๋๋ค.
Absctract Factory
ํจํด์ด๋?
- โ์ถ์์ ์ธ ๊ณต์ฅโ์์ โ์ถ์์ ์ธ ๋ถํโ์ ์กฐํฉํ์ฌ โ์ถ์์ ์ธ ์ ํโ์ ๋ง๋๋ ํจํด์ด๋ค.
- ํด๋น ํจํด์์๋ ๊ตฌ์ฒด์ ์ธ ๊ตฌํ๋ณด๋ค ์ธํฐํ์ด์คย
API
์ ์ฃผ๋ชฉํ๋ค. - ๊ทธ๋ฆฌ๊ณ ๊ทธ ์ธํฐํ์ด์ค๋ง ์ฌ์ฉํด์ ๋ถํ์ ์กฐ๋ฆฝํ๊ณ ์ ํ์ ์์ฑํ๋ ๊ฒ์ด๋ค.
Abstract Factory
ย ํจํด์์๋ ํ์ ํด๋์ค ๋จ๊ณ์์ ๊ตฌ์ฒด์ ์ผ๋ก ๊ตฌํํ๋ค.- ๊ตฌ์ฒด์ ์ธ ๊ณต์ฅ์์ ๊ตฌ์ฒด์ ์ธ ๋ถํ์ ์กฐํฉํ์ฌ ๊ตฌ์ฒด์ ์ธ ์ ํ์ ๋ง๋ ๋ค.
์์ ํ๋ก๊ทธ๋จ
- ๋ค์ ํ๋ก๊ทธ๋จ์ ๊ณ์ธต ๊ตฌ์กฐ๋ก ๋ ๋งํฌ ํ์ด์ง๋ฅผย
HTML
ย ํ์ผ๋ก ๋ง๋๋ ๊ฒ์ด๋ค. - ์ถ์์ ์ธ ๊ณต์ฅ, ๋ถํ, ์ ํ์ ํฌํจํ๋ย
factory
ย ํจํค์ง์ ๊ตฌ์ฒด์ ์ธ ๊ณต์ฅ, ๋ถํ, ์ ํ์ ํฌํจํ๋ยlistFactory
ย ํจํค์ง๊ฐ ์๋ค. - ์ง๊ธ๊น์ง๋ย
Main.java
๋ง ์ปดํ์ผํ๋ฉด ํ์ํ ํด๋์ค๊ฐ ๋ชจ๋ ์ปดํ์ผ ๋์๋ค. - ํ์ง๋ง ์ด๋ฒ์๋ย
Main.java
๋ฅผ ์ปดํ์ผํ๋๋ผ๋ยListFactory.java
,ยListLink.java
,ยListTray.java
,ยListPage.java
๋ ์ปดํ์ผ ๋์ง ์๋๋ค. - ์๋๋ฉดย
Main
ย ํด๋์ค๋ยfactory
ย ํจํค์ง๋ง ์ฌ์ฉํ๊ณ ยlistFactory
ย ํจํค์ง๋ ์ง์ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค. - ๊ทธ๋์ ์์ค ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ์ปดํ์ผ ํด์ผ ํ๋ค.
1
javac Main.java listFactory/ListFactory.java
Item
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
package factory;
public abstract class Item {
protected String caption;
public Item(String caption) {
this.caption = caption;
}
public abstract String makeHTML();
}
Link
,ยTray
์ ์์ ์ถ์ ํด๋์ค์ด๋ค.caption
ย ํ๋๋ ํญ๋ชฉ์ ํ์ ์ด๋ฅผ ๋ํ๋ธ๋ค.ยmakeHTML
ย ๋ฉ์๋๋ ์ถ์ ๋ฉ์๋์ด๋ฏ๋ก ํ์ ํด๋์ค์์ ๊ตฌํํด์ผ ํ๋ค.
Link
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
package factory;
public abstract class Link extends Item {
protected String url;
public Link(String caption, String url) {
super(caption);
this.url = url;
}
}
- ํ์ดํผ๋งํฌ๋ฅผ ์ถ์์ ์ผ๋ก ํํํ ํด๋์ค์ด๋ค.
- โ์ถ์์ ์ธ ๋ถํโ์ ํด๋นํ๋ค.
Tray
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package factory;
import java.util.ArrayList;
import java.util.List;
public abstract class Tray extends Item {
protected List<Item> tray = new ArrayList<>();
public Tray(String caption) {
super(caption);
}
public void add(Item item) {
tray.add(item);
}
}
- ๋ณต์์ย
Link
,ยTray
๋ฅผ ๋ชจ์์ ํ ๊ณณ์ ๋ฌถ๋ ํด๋์ค์ด๋ค. - โ์ถ์์ ์ธ ๋ถํโ์ ํด๋นํ๋ค.
Page
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package factory;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
public abstract class Page {
protected String title;
protected String author;
protected List<Item> contect = new ArrayList<>();
public Page(String title, String author) {
this.title = title;
this.author = author;
}
public void add(Item item) {
content.add(item);
}
public void output(String filename) {
try {
Files.writeString(
Path.of(filename),
makeHTML(),
StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING,
StandardOpenOption.WRITE
);
System.out.println(filename + "ํ์ผ์ ์์ฑํ์ต๋๋ค.");
} catch (IOException e) {
e.printStackTrace();
}
}
public abstract String makeHTML();
}
HTML
ย ํ์ด์ง ์ ์ฒด๋ฅผ ์ถ์์ ์ผ๋ก ํํํ ํด๋์ค์ด๋ค.- ์ฆ โ์ถ์์ ์ธ ์ ํโ์ ํด๋นํ๋ค.
Factory
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package factory;
public abstract class Factory {
public static Factory getFactory(String className) {
Factory factory = null;
try {
factory = (Factory) Class
.forName(className)
.getDeclaredConstructor()
.newInstance();
} catch (ClassNotFoundException e) {
System.out.println(className + " ํด๋์ค๊ฐ ๋ฐ๊ฒฌ๋์ง ์์์ต๋๋ค.");
} catch (Exception e) {
e.printStackTrace();
}
return factory;
}
public abstract Link createLink(String caption, String url);
public abstract Tray createTray(String caption);
public abstract Page createPage(String title, String author);
}
- ํ๋ผ๋ฏธํฐ์ย
className
์๋ ๊ตฌ์ฒด์ ์ธ ๊ณต์ฅ์ ํด๋์ค ์ด๋ฆ์ ๋ฌธ์์ด๋ก ์ง์ ํ๋ค. getFactory
ย ๋ฉ์๋ ์์์๋ยClass
ย ํด๋์ค์ยforName
ย ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํด๋น ํด๋์ค๋ฅผ ๋์ ์ผ๋ก ๊ฐ์ ธ์,ยgetDeclaredConstructor
ย ๋ฉ์๋๋ก ์์ฑ์๋ฅผ ์ป๊ณ ,ยnewInstance
ย ๋ฉ์๋๋ก ์ธ์คํด์ค๋ฅผ ์์ฑํ์ฌ ๋ณ์์ ์ ์ฅํ๋ค.- ์ด๋ ๊ฒ ํด๋์ค๋ ์์ฑ์ ๊ฐ์ ์์๋ฅผ ์ปดํ์ผ๋ฌ๊ฐ ๋ค๋ฃจ์ง ์๊ณ ํ๋ก๊ทธ๋จ ์์ ์ด ๋ค๋ฃจ๋ ์ฒ๋ฆฌ๋ฅผ ๋ฆฌํ๋์
ย
reflection
์ด๋ผ๊ณ ํ๋ค. getFactory
ย ๋ฉ์๋์์๋ ๊ตฌ์ฒด์ ์ธ ๊ณต์ฅ์ ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ง๋ง, ๋ฐํ๊ฐ์ ํ์ ์ ์ถ์์ ์ธ ๊ณต์ฅ์ด๋ค.
Main
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import factory.*;
public class Main {
public static void main(String[] args) {
if (args.length() != 2) {
System.out.println("Usage : java Main filename.html class.name.of.ConcreteFactory");
System.out.println("Example 1 : java Main list.html listFactory.ListFactory");
System.out.println("Example 2 : java Main div.html divFactory.DivFactory");
System.exit(0);
}
String fileName = args[0];
String className = args[1];
Factory factory = Factory.getFactory(className);
Link blog1 = factory.createLink("Blog 1", "https://example.com/blog1");
Link blog2 = factory.createLink("Blog 2", "https://example.com/blog2");
Link blog3 = factory.createLink("Blog 3", "https://example.com/blog3");
Tray blogTray = factory.createTray("Blog site");
blogTray.add(blog1);
blogTray.add(blog2);
blogTray.add(blog3);
Link news1 = factory.createLink("News 1", "http://example.com/news1");
Link news2 = factory.createLink("News 2", "http://example.com/news2");
Tray news3 = factory.createLink("News 3");
news3.add(factory.createLink("News 3 (US)", "https://example.com/news3us"));
news3.add(factory.createLink("News 3 (Korea)", "https://example.com/news3kr"));
Tray newsTray = factory.createTray("News Site");
newTray.add(news1);
newTray.add(news2);
newTray.add(news3);
Page page = factory.createPage("Blog and News", "Youngjin.com");
page.add(blogTray);
page.add(newsTray);
page.output(fileName);
}
}
- ์ถ์์ ์ธ ๊ณต์ฅ์ ์ฌ์ฉํด ์ถ์์ ์ธ ๋ถํ์ ์ ์กฐํ๊ณ ์ถ์์ ์ธ ์ ํ์ ์กฐ๋ฆฝํ๋ค. ์ถ์ ํด๋์ค๋ง ๋ชจ์ ๋์ย
factory
ย ํจํค์ง๋งยimport
ํ์ฌ ์ถ์ ํด๋์ค์ ๋ํ ๊ตฌ์ฒด์ ์ธ ๊ตฌํ ํด๋์ค๋ ์ ํ ์์กดํ์ง ์๋๋ค. - ๊ตฌ์ฒด์ ์ธ ๊ณต์ฅ์ ํด๋์ค ์ด๋ฆ์ ๋ค์๊ณผ ๊ฐ์ด ์ปค๋งจ๋ ๋ผ์ธ์์ ์ง์ ํ๋ค.
1
Java Main list.html listFactory.ListFactory
ListFactory
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package listFactory;
import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;
public class ListFactory extends Factory {
@Override
public Link createLink(String caption, String url) {
return new ListLink(caption, url);
}
@Override
public Tray createTray(String caption) {
return new ListTray(caption);
}
@Override
public Page createPage(String title, String author) {
return new ListPage(title, author);
}
}
Factory
ย ํด๋์ค์ ์ถ์ ๋ฉ์๋ยcreateLink
,ยcreateTray
,ยcreatePage
๋ฅผ ๊ตฌํํ๋ค.
ListLink
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package listFactory;
import factory.Link;
public class ListLink extends Link {
public ListLink(String caption, String url) {
super(caption, url);
}
@Override
public String makeHTML() {
return " <li><a href=\"" + url + "\">" + caption + "</a></li>\n";
}
}
Link
ย ์ถ์ ํด๋์ค์ ํ์ ํด๋์ค๋ก,ยmakeHTML
ย ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ค.
ListTray
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package listFactory;
import factory.Tray;
import factory.Item;
public class ListTray extends Tray {
public ListTray(String caption) {
super(caption);
}
@Override
public String makeHTML() {
StringBuilder sb = new StringBuilder();
sb.append("<li>\n");
sb.append(caption);
sb.append("\n<ul>\n");
for (Item item : tray) {
sb.append(item.makeHTML());
}
sb.append("</ul>\n");
sb.append("</li>\n");
return sb.toString();
}
}
- ๊ฐ๊ฐ์ย
Item
์ ๊ฐ๋ณยmakeHTML
ย ๋ฉ์๋๋ฅผ ํตํดยHTML
ย ํ๊ทธ๋ก ๋ง๋ ๋ค. - ์ด ๋ ๋ณ์ย
item
์ ๋ด์ฉ์ดยListLink
์ ์ธ์คํด์ค์ธ์ง,ยListTray
์ ์ธ์คํด์ค์ธ์ง ์ ๊ฒฝ ์ธ ํ์๊ฐ ์๋ค.ย ListLink
,ยListTray
๋ ๋ชจ๋ยItem
์ ํ์ ํด๋์ค์ด๋ฏ๋กยitem
ย ๋ณ์์ ์ธ์คํด์ค๊ฐ ์ด๋ค ํด๋์ค์ยmakeHTML
ย ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผํ ์ง ์๊ณ ์๋ค.
ListPage
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package listFactory;
import factory.Item;
import factory.Page;
public class ListPage extends Page {
public ListPage(String title, String author) {
super(title, author);
}
@Override
public String makeHTML() {
StringBuilder sb = new StringBuilder();
sb.append("<!DOCTYPE html>\n");
sb.append("<html><head><title>");
sb.append(title);
sb.append("</title></head>\n");
sb.append("<body>\n");
sb.append("<h1>");
sb.append(title);
sb.append("</h1>\n");
sb.append("<ul>\n");
for (Item item : content) {
sb.append(item.makeHTML());
}
sb.append("</ul>\n");
sb.append("<hr><address>");
sb.append(author);
sb.append("</address>\n");
sb.append("</body></html>\n");
return sb.toString();
}
}
for
๋ฌธ์์ ์ฌ์ฉ๋๋ยcontent
๋ยPage
ย ํด๋์ค์์ ์์๋ฐ์ ํ๋์ด๋ค.
DivFactory
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package divFactory;
import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;
public class ListFactory extends Factory {
@Override
public Link createLink(String caption, String url) {
return new DivLink(caption, url);
}
@Override
public Tray createTray(String caption) {
return new DivTray(caption);
}
@Override
public Page createPage(String title, String author) {
return new DivPage(title, author);
}
}
divXX
ย ํด๋์ค๋ยdiv
,ยstyle
ย ํ๊ทธ๋ฅผ ์ฌ์ฉํด ๋์์ธํยHTML
ย ๋ฌธ์๋ฅผ ๋ง๋๋ ๊ตฌํ ํด๋์ค์ด๋ค.Factory
ย ํด๋์ค์ ์ถ์ ๋ฉ์๋ยcreateLink
,ยcreateTray
,ยcreatePage
๋ฅผ ๊ตฌํํ๋ค.
DivLink
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package divFactory;
import factory.Link;
public class DivLink extends Link {
public DivLink(String caption, String url) {
super(caption, url);
}
@Override
public String makeHTML() {
return "<div class=\"LINK\"><a href=\"" + url + "\">" + caption + "</a></div>\n";
}
}
Link
ย ์ถ์ ํด๋์ค์ ํ์ ํด๋์ค๋ก,ยmakeHTML
ย ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ค.
DivTray
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package divFactory;
import factory.Tray;
import factory.Item;
public class DivTray extends Tray {
public DivTray(String caption) {
super(caption);
}
@Override
public String makeHTML() {
StringBuilder sb = new StringBuilder();
sb.append("<p><b>");
sb.append(caption);
sb.append("</b></p>\n");
sb.append("<div class=\"TRAY>\">");
for (Item item : tray) {
sb.append(item.makeHTML());
}
sb.append("</div>\n");
return sb.toString();
}
}
DivPage
ย ํด๋์ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package divFactory;
import factory.Item;
import factory.Page;
public class DivPage extends Page {
public DivPage(String title, String author) {
super(title, author);
}
@Override
public String makeHTML() {
StringBuilder sb = new StringBuilder();
sb.append("<!DOCTYPE html>\n");
sb.append("<html><head><title>");
sb.append(title);
sb.append("</title><style>\n");
sb.append("</style></head><body>\n");
sb.append("<h1>");
sb.append(title);
sb.append("</h1>\n");
for (Item item : content) {
sb.append(item.makeHTML());
}
sb.append("<hr><address>");
sb.append(author);
sb.append("</address>\n");
sb.append("</body></html>\n");
return sb.toString();
}
}
for
๋ฌธ์์ ์ฌ์ฉ๋๋ยcontent
๋ยPage
ย ํด๋์ค์์ ์์๋ฐ์ ํ๋์ด๋ค.
Abstract Factory
ย ํจํด์ ๋ฑ์ฅ์ธ๋ฌผ
Link
,ย Tray
,ย Page
ย ํด๋์ค
- ์ถ์์ ์ธ ์ ํย
AbstractProduct
ย ์ญํ ์ ๋งก์ ์ถ์์ ์ธ ๋ถํ์ด๋ ์ ํ์ ์ธํฐํ์ด์คยAPI
๋ฅผ ๊ฒฐ์ ํ๋ค.
Factory
ย ํด๋์ค
- ์ถ์์ ์ธ ๊ณต์ฅย
Abstract Factory
ย ์ญํ ์ ๋งก์ ์ถ์์ ์ธ ์ ํ ์ญํ ์ ์ธ์คํด์ค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ธํฐํ์ด์คยAPI
๋ฅผ ๊ฒฐ์ ํ๋ค.
Main
ย ํด๋์ค
- ์ถ์์ ์ธ ์ ํ์ด๋ ์ถ์์ ์ธ ๊ณต์ฅ ์ญํ ์ ์ธํฐํ์ด์คย
API
๋ง ์ฌ์ฉํด ์์ ํ๋ค. - ๊ตฌ์ฒด์ ์ธ ์ ํ์ด๋ ๊ตฌ์ฒด์ ์ธ ๊ณต์ฅ์ ๋ํด์๋ ๋ชจ๋ฅธ๋ค.
ListLink
ย โฆย ListPage
,ย DivLink
ย โฆย DivPage
ย ํด๋์ค
- ๊ตฌ์ฒด์ ์ธ ์ ํย
ConcreteProduct
ย ์ญํ ์ ๋งก์ ์ถ์์ ์ธ ์ ํ ์ญํ ์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ค.
ListFactory
,ย DivFactory
ย ํด๋์ค
- ๊ตฌ์ฒด์ ์ธ ๊ณต์ฅย
ConcreteFactory
ย ์ญํ ์ ๋งก์ ์ถ์์ ์ธ ๊ณต์ฅ ์ญํ ์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ค.
์ฑ ์์ ์ ์ํ๋ ํํธ
๊ตฌ์ฒด์ ์ธ ๊ณต์ฅ์ ์๋ก ์ถ๊ฐํ๋ ๊ฑด ๊ฐ๋จํ๋ค.
- ์์ ํ๋ก๊ทธ๋จ์ฒ๋ผ ํด์ผํ ์ผ์ ์ถ์ ํด๋์ค๋ฅผ ๊ตฌํํ๋ ํ์ ํด๋์ค๋ฅผ ๋ง๋ค๊ณ ํด๋์ค ๋ด ์ถ์ ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ ์ผ ๋ฟ์ด๋ค.
- ์๋ฌด๋ฆฌ ๊ตฌ์ฒด์ ์ธ ๊ณต์ฅ์ ์ถ๊ฐํ๋๋ผ๋ ์ถ์์ ์ธ ๊ณต์ฅ์ด๋ย
Main
ย ๋ถ๋ถ์ ์์ ํ ํ์๋ ์ ํ ์๋ค.
๋ถํ์ ์๋ก ์ถ๊ฐํ๋ ๊ฑด ์ด๋ ต๋ค.
- ๊ฐ๋ น ์์ ํ๋ก๊ทธ๋จ์ ์ถ์์ ์ธ ๊ณต์ฅ์ย
Picture
๋ผ๋ ๋ถํ์ ์ถ๊ฐํ๋ค๊ณ ํ๋ฉด ์ด๋ฏธ ์กด์ฌํ๋ ๋ชจ๋ ๊ตฌ์ฒด์ ์ธ ๊ณต์ฅ ์ ๋ถ๋ฅผยPicture
์ ๋์ํ๋๋ก ์์ ํด์ผ ํ๋ค.
์ธ์คํด์ค๋ฅผ ๋ง๋๋ ๋ค์ํ ๋ฐฉ๋ฒ
new
ย ์์ฝ์ดclone
ย ๋ฉ์๋newInstance
ย ๋ฉ์๋:ยClass
์ ์ธ์คํด์ค๋ฅผ ๋ฐํ์ผ๋ก ๊ทธยClass
๊ฐ ๋ํ๋ด๋ ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ๋ง๋ค ์ ์๋ค.
This post is licensed under CC BY 4.0 by the author.