학습목표 l 생성패턴 l 동기, 목적 l 종류 l 팩토리패턴과그적용 l 싱글톤패턴과그적용 l 프로토타입패턴과그적용 l 실습문제 2

Similar documents
JAVA PROGRAMMING 실습 08.다형성

학습목표 l 추상팩토리패턴과그적용 l 빌더패턴과그적용 l 실습문제 2

PowerPoint 프레젠테이션

PowerPoint Presentation

gnu-lee-oop-kor-lec06-3-chap7

q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2

PowerPoint Presentation

Microsoft PowerPoint - 04-UDP Programming.ppt

PowerPoint Presentation

PowerPoint Presentation

<4D F736F F F696E74202D20C1A63038C0E520C5ACB7A1BDBABFCD20B0B4C3BC4928B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

PowerPoint Presentation

Design Issues

05-class.key

PowerPoint Presentation

12-file.key

쉽게 풀어쓴 C 프로그래밍

PowerPoint 프레젠테이션

예제 2) Test.java class A intvar= 10; void method() class B extends A intvar= 20; 1"); void method() 2"); void method1() public class Test 3"); args) A

교육자료

Microsoft PowerPoint - Supplement-03-TCP Programming.ppt [호환 모드]

PowerPoint 프레젠테이션

Microsoft PowerPoint - Lect04.pptx

Microsoft PowerPoint - 03-TCP Programming.ppt

Microsoft PowerPoint - java1-lab5-ImageProcessorTestOOP.pptx

2 단계 : 추상화 class 오리 { class 청둥오리 extends 오리 { class 물오리 extends 오리 { 청둥오리 mallardduck = new 청둥오리 (); 물오리 redheadduck = new 물오리 (); mallardduck.swim();

(8) getpi() 함수는정적함수이므로 main() 에서호출할수있다. (9) class Circle private double radius; static final double PI= ; // PI 이름으로 로초기화된정적상수 public

쉽게 풀어쓴 C 프로그래밍

rmi_박준용_final.PDF

Microsoft PowerPoint - 11_DesignPatterns(2010).ppt [호환 모드]

JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각

PowerPoint 프레젠테이션

작성자 : 김성박\(삼성 SDS 멀티캠퍼스 전임강사\)

자바 프로그래밍

JAVA PROGRAMMING 실습 02. 표준 입출력

JAVA PROGRAMMING 실습 05. 객체의 활용

PowerPoint 프레젠테이션

Spring Boot/JDBC JdbcTemplate/CRUD 예제

쉽게 풀어쓴 C 프로그래밍

PowerPoint Presentation

Cluster management software

4장.문장

ThisJava ..

슬라이드 1

Microsoft PowerPoint 장강의노트.ppt

PowerPoint 프레젠테이션

Microsoft PowerPoint - Java7.pptx

* Factory class for query and DML clause creation * tiwe * */ public class JPAQueryFactory implements JPQLQueryFactory private f

설계란 무엇인가?

01-OOPConcepts(2).PDF

(Microsoft PowerPoint - 11_DesignPatterns\(2008\).ppt [\310\243\310\257 \270\360\265\345])

Microsoft PowerPoint - 2강

untitled

제11장 프로세스와 쓰레드

PowerPoint Presentation

쉽게 풀어쓴 C 프로그래밍

JAVA PROGRAMMING 실습 09. 예외처리

Java

Java ...

Spring Data JPA Many To Many 양방향 관계 예제

C++ Programming

10.0pt1height.7depth.3width±â10.0pt1height.7depth.3widthÃÊ10.0pt1height.7depth.3widthÅë10.0pt1height.7depth.3width°è10.0pt1height.7depth.3widthÇÁ10.0pt1height.7depth.3width·Î10.0pt1height.7depth.3width±×10.0pt1height.7depth.3width·¡10.0pt1height.7depth.3width¹Ö pt1height.7depth.3widthŬ10.0pt1height.7depth.3width·¡10.0pt1height.7depth.3width½º, 10.0pt1height.7depth.3width°´10.0pt1height.7depth.3widthü, 10.0pt1height.7depth.3widthº¯10.0pt1height.7depth.3width¼ö, 10.0pt1height.7depth.3width¸Þ10.0pt1height.7depth.3width¼Ò10.0pt1height.7depth.3widthµå

Microsoft Word - java19-1-midterm-answer.doc

02 C h a p t e r Java

Microsoft PowerPoint - RMI.ppt

class Sale void makelineitem(productspecification* spec, int qty) SalesLineItem* sl = new SalesLineItem(spec, qty); ; 2. 아래의액티비티다이어그램을보고 Java 또는 C ++,

No Slide Title

Network Programming

(Microsoft PowerPoint - java1-lecture11.ppt [\310\243\310\257 \270\360\265\345])

쉽게 풀어쓴 C 프로그래밊

chap10.PDF

C# Programming Guide - Types

5장.key

mytalk

Microsoft PowerPoint 자바-기본문법(Ch2).pptx

PowerPoint Presentation

JAVA PROGRAMMING 실습 07. 상속

K&R2 Reference Manual 번역본

PowerPoint 프레젠테이션

Mobile Service > IAP > Android SDK [ ] IAP SDK TOAST SDK. IAP SDK. Android Studio IDE Android SDK Version (API Level 10). Name Reference V

신림프로그래머_클린코드.key

PowerPoint Presentation

슬라이드 1

Connection 8 22 UniSQLConnection / / 9 3 UniSQL OID SET

Chap12

fundamentalOfCommandPattern_calmglow_pattern_jstorm_1.0_f…

<4D F736F F F696E74202D2036C0CFC2B05FB0B4C3BCC1F6C7E2C7C1B7CEB1D7B7A1B9D62E707074>

Microsoft PowerPoint - 14주차 강의자료

PowerPoint 프레젠테이션

<4D F736F F F696E74202D20C1A63235C0E520B3D7C6AEBFF6C5A920C7C1B7CEB1D7B7A1B9D628B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - C++ 5 .pptx

소프트웨어공학개론 강의 5: 객체지향개념 최은만동국대학교컴퓨터공학과

MVVM 패턴의 이해

JVM 메모리구조

PowerPoint 프레젠테이션

목차 INDEX JSON? - JSON 개요 - JSONObject - JSONArray 서울시공공데이터 API 살펴보기 - 요청인자살펴보기 - Result Code - 출력값 HttpClient - HttpHelper 클래스작성 - JSONParser 클래스작성 공공

PowerPoint Presentation

1. 객체의생성과대입 int 형변수 : 선언과동시에초기화하는방법 (C++) int a = 3; int a(3); // 기본타입역시클래스와같이처리가능 객체의생성 ( 복습 ) class CPoint private : int x, y; public : CPoint(int a

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

09-interface.key

Transcription:

객체지향설계와패턴 Lecture #9: 생성패턴 (1) Eun Man Choi emchoi@dgu.ac.kr

학습목표 l 생성패턴 l 동기, 목적 l 종류 l 팩토리패턴과그적용 l 싱글톤패턴과그적용 l 프로토타입패턴과그적용 l 실습문제 2

생성패턴 l 생성패턴 l 종류 l 객체의생성과정을추상화하여유연성 (flexibility) 을높인다. l 실제객체와객체생성부분을분리함으로써결합도 (coupling) 를낮춘다. l 팩토리패턴 l 싱글톤패턴 l 프로토타입패턴 l 추상팩토리패턴 l 빌더패턴 3

Pattern #1 - 팩토리패턴 생성자만으로는개별객체생성이적합하지않은경우 사용 l 목적 l 결과 l 객체생성을위한인터페이스를정의하는데있다. l 어떤클래스의인스턴스를생성할지에대한결정은서브클래스에서이루어지도록인스턴스의책임을미룸 l 다양한형태의객체를반환하는융통성을갖게됨 4

팩토리패턴을사용하는이유 l 생성자사용할때의문제 Duck duck; if (picnic) { duck = new MallardDuck(); else if (hunting) { duck = new DecoyDuck(); else if (inbathtub) { duck = new RubberDuck(); 새로운타입이추가될때문제가됨 5

사례 #1 - 피자스토어 Pizza orderpizza(string type){ if (type.equals( cheese )) { pizza = new CheesePizza(); else if type.equals( greek )) { pizza = new GreekPizza(); else if type.equals( pepperoni )) { pizza = new PepperoniPizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box() l 만일피자스토어에서주문하는피자종류를바꾸기로결정한다면 orderpizza 메소드는바뀌어야 6

사례 #1- 피자스토어생성자 Pizza orderpizza(string type){ if (type.equals( cheese )) { pizza = new CheesePizza(); else if type.equals( greek )) { pizza = new GreekPizza(); else if type.equals( pepperoni )) { pizza = new PepperoniPizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box() 고정된부분 변동이있을부분 7

사례 #1 객체생성을캡슐화 if (type.equals( cheese )) { pizza = new CheesePizza(); else if type.equals( greek )) { pizza = new GreekPizza(); else if type.equals( pepperoni )) { pizza = new PepperoniPizza(); SimplePizzaFactory 클래스가담당 8 public class SimplePizzaFactory { public Pizza createpizza(string type) { Pizza pizza = null; if (type.equals("cheese")) { pizza = new CheesePizza(); else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); else if (type.equals("clam")) { pizza = new ClamPizza(); else if (type.equals("veggie")) { pizza = new VeggiePizza(); return pizza;

사례 #1 PizzaStore 클래스수정 public class PizzaStore { SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory) { this.factory = factory; public Pizza orderpizza(string type) { Pizza pizza; pizza = factory.createpizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; 9

SimpleFactory 전체사례 SimplePizzaFactory factory = new SimplePizzaFactory(); PizzaStore store = new PizzaStore(factory); Pizza pizza = store.orderpizza("cheese"); PizzaStore orderpizza() SimplePizzaFactory createpizza() CheesePizza Pizza prepare() bake() cut() box() VeggiePizza ClamPizza ClamPizza 10

여러 Factory 생성 NYPizzaFactory PizzaStore ChicagoPizzaFactory NYPizzaFactory nyfactory = new NYPizzaFactory(); PizzaStore nystore = new PizzaStore(nyFactory); Pizza pizza = nystore.orderpizza("cheese"); ChicagoPizzaFactory chicagofactory = new ChicagoPizzaFactory(); PizzaStore chicagostore = new PizzaStore(chicagoFactory); Pizza pizza = chicagostore.orderpizza("cheese"); 11

다른방법 추상메소드 l PizzaStore 를위한프레임워크 public abstract class PizzaStore { abstract Pizza createpizza(string item); public Pizza orderpizza(string type) { Pizza pizza = createpizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; 12

서브클래스를정할수있게 PizzaStore createpizza() orderpizza() NYStylePizzaStore createpizza() ChicagoStylePizzaStore createpizza() l 팩토리메소드는객체생성을다루며이를서브클래스에캡슐화함 l 슈퍼클래스의클라이언트코드에서서브클래스에대하여발생하는객체생성을떼내올 (decoupled) 수있음 13

팩토리메소드패턴 PizzaStore createpizza() orderpizza() Creator Classes Pizza NYStylePizzaStor e createpizza() ChicagoStylePizzaStore createpizza() Product Classes NYStyleCheesePizza NYStyleCheesePizza NYStyleCheesePizza NYStyleCheesePizza ChStyleCheesePizza ChStyleCheesePizza ChStyleCheesePizza ChStyleCheesePizza 14

팩토리메소드패턴정의 l 팩토리메소드패턴은객체를생성하기위한인터페이스를정의한것 l 어떤클래스가인스턴스로될지는서브클래스가결정하게 l 팩토리메소드는서브클래스에게인스턴스화를연기시킨것 15

사례 #2 : 미로찾기 l 예제 : 컴퓨터게임미로찾기만들기 l 단순미로찾기 l 미로 (maze) 는방 (room) 과벽 (wall) 과문 (door) 으로구성 l room은동서남북각방향으로 wall이나 door가연결되어있음. l room과 room간의연결은하나의 door로연결 l maze는복수개의 room으로구성 l 클래스다이어그램 l 클래스 : Maze, Room, Wall, Door, à Room, Wall, Door 를미로의공통구성요소로간주하여 MapSite 로추상화 16

패턴미적용사례 l MapSite 의메소드 l Enter(): Player의위치를변경. l 만일 MapSite가 Room 객체라면 Player가있는방을변경 l 만일 MapSite 가 Door 객체라면 Door가열려져있는경우엔다른 Room으로이동할수있지만, 잠겨있을경우엔이동할수없음. à Door 가열려져있는지여부를표현하기위한속성필요 l Room 의메소드 l 동서남북각방향으로 Wall이나 Door를지정하기위한 Method 필요. à SetSide(), GetSide() l Maze 의메소드 l Room을추가하기위한 Method 필요 à AddRoom() 17

패턴미적용사례 l Maze 를위한클래스다이어그램 18

패턴미적용사례 - 코드 class MapSite { public: virtual void Enter() = 0; ; class Room : public MapSite { public: Room(int = 0); Room(const Room&); virtual Room* Clone() const; void InitializeRoomNo(int); class Wall : public MapSite { public: ; Wall(); Wall(const Wall&); virtual Wall* Clone() const; virtual void Enter(); class Door : public MapSite { public: Door(Room* = 0, Room* = 0); Door(const Room&); virtual Door* Clone() const; MapSite* GetSide(Direction); void Initialize(Room*, Room*); void SetSide(Direction, MapSite*); virtual void Enter(); private: MapSite* _sides[4]; int _roomnumber; ; virtual void Enter(); Room* OtherSideFrom(Room*); private: Room* _room1; Room* _room2; bool _isopen; ; class Maze { public: Maze(); Maze(const Maze&); Room* RoomNo(int); void AddRoom(Room*); virtual Maze* Clone() const; private: //... ; 19

패턴미적용사례 - 코드 Maze* MazeGame::CreateMaze() { Maze* amaze = new Maze; Room* r1 = new Room(1); Room* r2 = new Room(2); Door *thedoor = new Door(r1, r2); amaze->addroom(r1); amaze->addroom(r2); r1->setside(north, new Wall); r1->setside(east, thedoor); r1->setside(south, new Wall); r1->setside(west, new Wall); r2->setside(north, new Wall); r2->setside(east, new Wall); r2->setside(south, new Wall); r2->setside(west, thedoor); l MazeGame::CreateMaze() l Maze 생성 (amaze) l Room 을두개생성 (r1, r2) l Door 을하나생성 (thedoor) l amaze 에 r1, r2 추가 l r1 은동쪽에 thedoor 를연결하고나머지방향에는 Wall 을연결 l r2는서쪽에 thedoor를연결하고나머지방향에는 Wall 을연결 return amaze; 20

패턴미적용사례 - 문제점 l 문제점 : l 미로의구조가하드코딩되어있기때문에미로구조가변경될때마다코드 (MazeGame::CreateMaze()) 를수정하여야한다. l 기존의미로를다음의요소들이추가되는 마법의미로 로바꾸려한다. 주문을외면열리는문 (DoorNeedingSpell) 특별아이템이숨어있는방 (EnchantedRoom) à 어떤코드들이변경되어야하는가? à 쉽게변경할수있는가? 객체들의생성과그과정이하드코딩되어있기때문에변화에대처하기힘들다. Creational Patterns 을이용함으로써이러한문제점을해결할수있다. 21

팩토리패턴의개념 ( 정적모형 ) Client RequiredClass «create object» MyClass createobjectofrequiredclass(): RequiredClass Factory design pattern 22

팩토리패턴의개념 ( 동적모형 ) :Client :MyClass :RequiredClass createobjectofrequiredclass() RequiredClass() 23

팩토리패턴의간단한예제 Client Automobile createautomobile(): Automobile Application of Factory design pattern Hyundai createautomobile() Kia createautomobile() 24 «create object» class Hyundai extends Automobile {... Automobile createautomobile() { return new Hyundai();... «create object»

팩토리패턴의예 : 메일생성시스템 l E-mail 생성시스템 l 다양한고객에맞추어진메일메시지를생성하는시스템 25

사례 #3: 메일시스템 1. 메일생성시스템은고객의이메일주소를요청한다. 2. 사용자는고객의이메일주소를입력한다. 3. 메일생성시스템은고객타입의목록을보여주며, 어떤타입의고객메일메시지인지를묻는다. 4. 사용자는의도한고객타입을입력한다. 5. 메일생성시스템은고객의타입을모니터에다시출력해준다. 6. 메일생성시스템은모든고객에게보내지는부분과사용자에의해요구에맞춰진메일로구성된메일메시지를모니터에출력한다. 7. 메일생성시스템은메시지를보낸다. 26

이메일생성시스템 Application of Factory design pattern Customer getmessage() Frequent Returning Curious Newbie getmessage() getmessage() getmessage() getmessage() Client sendmessage() 27 «setup» MailGenerationApplication getcustomertypefromuser() MailMessage text

클라이언트클래스 class Client { public Client() { super(); public void sendmessage(customer acustomer) { MailMessage mailmessage = acustomer.getmessage(); System.out.println("This message will be sent:"); System.out.println(mailMessage.getText()); abstract class Customer { public MailMessage getmessage() { return new MailMessage( "Losts of material intended for all customers..." ); 28

애플리케이션 import java.io.*; import java.util.*; class MailGenerationApplication { private static Client client = new Client(); public MailGenerationApplication() { super(); public static void main(string[ ] args) { Customer customer = getcustomertypefromuser(); MailGenerationApplication.client.sendMessage(cu stomer); // let the client do its job private static Customer getcustomertypefromuser() { String customertype = "newbie"; // default Hashtable customertypetable = new Hashtable(); // keys strings to Customer types 29 customertypetable.put("frequent", new Frequent()); customertypetable.put("returning", new Returning()); customertypetable.put("curious", new Curious()); customertypetable.put("newbie", new Newbie()); System.out.println( "Please pick a type of customer from one of the following:"); for (Enumeration enumeration = customertypetable.keys(); enumeration.hasmoreelements(); ) { System.out.println(enumeration.nextElement()); try { // pick up user's input BufferedReader bufreader = new BufferedReader(new InputStreamReader(System.in)); customertype = bufreader.readline(); catch (IOException e) { System.out.println(e);

애플리케이션 Customer customerselected = (Customer) customertypetable.get(customertype); if (customerselected!= null) return customerselected; else { // use default if user input bad System.out.println("Sorry: Could not understand your input: newbie customer assumed."); return new Newbie(); // end getcustomertypefromuser() 30

팩토리패턴이적용된코드 class MailMessage { String text = "No text chosen yet"; public MailMessage() { super(); public MailMessage( String atext ) { this(); text = atext; public String gettext() { return text; public void settext( String astring ) { text = astring; class Frequent extends Customer { public Frequent() { super(); public MailMessage getmessage() { String frequentcustomermessage = "... a (possibly long) message for frequent customers..."; String messagetextforallcustomers = ( super.getmessage() ).gettext(); return new MailMessage( "\n" + messagetextforallcustomers + "\n" + frequentcustomermessage ); 31

팩토리패턴사례 : 미로게임 l Sample Code l Slide 7,8 에있는 Maze 소스코드의경우 미로의구성요소 (Room, Door, Wall) 생성이 hard-coding 되어있다. Maze* MazeGame::CreateMaze() { Maze* amaze = new Maze; Room* r1 = new Room(1); Room* r2 = new Room(2); Door *thedoor = new Door(r1, r2); return amaze; Factory Method pattern 을적용한다면? 32

팩토리패턴사례 : 미로게임 class MazeGame { public: Maze* CreateMaze(); override 될 factory method factory method 를이용하여객체생성 ; // factory methods: virtual Maze* MakeMaze() const { return new Maze; virtual Room* MakeRoom(int n) const { return new Room(n); virtual Wall* MakeWall() const { return new Wall; virtual Door* MakeDoor(Room* r1, Room* r2) const { return new Door(r1, r2); Maze* MazeGame::CreateMaze () { Maze* amaze = MakeMaze(); Room* r1 = MakeRoom(1); Room* r2 = MakeRoom(2); Door* thedoor = MakeDoor(r1, r2); amaze->addroom(r1); amaze->addroom(r2); r1->setside(north, MakeWall()); r1->setside(east, thedoor); r1->setside(south, MakeWall()); r1->setside(west, MakeWall()); r2->setside(north, MakeWall()); r2->setside(east, MakeWall()); r2->setside(south, MakeWall()); r2->setside(west, thedoor); return amaze; 33

팩토리패턴사례 : 미로게임 class BombedMazeGame : public MazeGame { public: BombedMazeGame(); virtual Wall* MakeWall() const { return new BombedWall; virtual Room* MakeRoom(int n) const { return new RoomWithABomb(n); ; factory method // Client Code BombedMazeGame game1; EnchantedMazeGame game2; class EnchantedMazeGame : public MazeGame { public: EnchantedMazeGame(); virtual Room* MakeRoom(int n) const { return new EnchantedRoom(n, CastSpell()); virtual Door* MakeDoor(Room* r1, Room* r2) const { return new DoorNeedingSpell(r1, r2); protected: Spell* CastSpell() const; ; game1.createmaze(); game2.createmaze(); 34

Pattern #2 싱글톤패턴 목적어떤클래스, S 의인스턴스를단하나만만들고싶을때. 어플리케이션전체에꼭하나만필요한경우. l 패턴의핵심 l S 의생성자를 private 으로만들고, S 안에 private 정적속성을정의한다. 이를접근하는 public 함수를제공한다. l 싱글톤은오직한개의객체만존재하려는목적이있어더이상만들려는생성자의호출을안전하게막아야한다. 35

싱글톤패턴 클래스다이어그램 Client Singleton Design Pattern MyClass getsingletonofmyclass(): MyClass singletonofmyclass «static» 1 36

싱글톤패턴 MyClass 1. MyClass 클래스안에 MyClass 라는이름의 private 정적변수를선언한다. l private static MyClass singletonofmyclass = new MyClass(); 2. MyClass 의생성자를 private 으로만든다. l private MyClass() { /*. constructor code. */ ; 3. 멤버를접근하는정적 public 메소드를정의한다. public static MyClass getsingletonofmyclass() { return singletonofmyclass; 37

사례 #1 보고서문제 l 연구실의실험결과평가어플리케이션 l 정확히하나의 experiment 객체만이실시간에존재함을보장하여야함 l 어플리케이션에서 experiment 를접근할때다음과같이표시 38

사례 #1 보고서문제 l 클래스다이어그램 Client Experiment theexperiment: Experiment analyze() gettheexperiment(): Experiment reportresults() 1 theexperiment «static» 39

사례 #1 코드 class Client { public Client() { super(); public static void main( String[] args ) { Experiment experiment = Experiment.getTheExperiment(); experiment.analyze(); experiment.reportresults(); class Experiment { private static final Experiment theexperiment = new Experiment(); String result = "Experiment result not yet assigned"; // result of the experiment private static int numtimesreferenced = 0; private Experiment() { super(); public synchronized void analyze() { theexperiment.result = "... The analysis shows that the experiment was a resounding success...."; 40

사례 #1 코드 public static Experiment gettheexperiment() { ++numtimesreferenced; System.out.println ("Noting that the Experiment singleton referenced " + numtimesreferenced + " times so far"); return theexperiment; public void reportresults() { System.out.println(result); 41

사례 #2 미로게임 l Sample Code l Abstract Factory pattern 의 Sample Code 에서 MazeFactory 부분을 Singleton 클래스로작성 그러나, MazeFactory::Instance() 함수에서실제생성되는 Factory 는환경변수 MAZESTYLE 에따라 MazeFactory, BombedMazeFactory, EnchantedMazeFactory 등이생성되도록구현한다. l 변경되는부분 MazeFactory Client Code 42

사례 #2 미로게임 class MazeFactory { public: static MazeFactory* Instance(); // existing interface goes here protected: MazeFactory(); private: static MazeFactory* _instance; ; // Client Code setenv( MAZESTYLE, bombed,1); MazeFactory *factory = MazeFactory::Instance(); MazeGame game; game.createmaze(factory); MazeFactory* MazeFactory::_instance = 0; MazeFactory* MazeFactory::Instance () { if (_instance == 0) { const char* mazestyle = getenv("mazestyle"); if (strcmp(mazestyle, "bombed") == 0) { _instance = new BombedMazeFactory; else if (strcmp(mazestyle, "enchanted") == 0) { _instance = new EnchantedMazeFactory; //... other possible subclasses else _instance = new MazeFactory; return _instance; 43 환경변수값에따라실제 factory 객체를결정

Pattern #3 - 프로토타입패턴 런타임에그타입이결정되는거의동일한객체의집합을만들려고할때적용. l 가정 l 프로토타입이될인스턴스를이미알고있어야함 l 새로운인스턴스가필요할때언제든지이를클론화 l 인스턴스를만드는방법 l New Something() l MyPart anothermypart = MyPartPrototype.clone(); 44

프로토타입패턴 : 동기 A 회사는자사의주력제품인 보고서관리 Class Library 의 upgrade 프로젝트를결정하였으며, 그개발팀의시스템설계자로당신이선발되었다. upgrade 는주로고객 (library 를이용하는개발자 ) 의불만사항을해결하는데초점이맞추어져있다. - 보고서관리 Class Library 의현재상황개발자는실제보고서객체 (ReportA, ReportB, ) 를직접다루지않고모두 Report 객체로간주하여이용한다. 즉, 실제보고서객체는외부에서접근하지못한다. [ 보고서관리 Class Library] Client Code ReportA Report ReportC 45 ReportB ReportD

프로토타입패턴 : 동기 l 고객 ( 개발자 ) 의불만사항 l 특정 Report 객체를넘겨받아이를이용하여작업을수행한다. l 그러나, 넘겨받은 Report 객체와동일한 Report 객체를생성해야되는경우엔어떻게해야되는가? l 예를들면현재 Client Code 에서특정 Report 객체 ( 실제로는 ReportA 객체라고가정 ) 를가지고작업중인데, 이보고서의복사본을생성하기위해서는어떻게해야하는가? (Client Code 는이객체가 ReportA 임을알수없다.) // Client Code CopyReport(Report *rep) { Report *rep2 = new??? What?? ReportA ReportB ReportC. 46

프로토타입패턴 : 동기 l 불만사항해결방안 1 47 // Client Code CopyReport(Report *rep) { Report *rep2; switch ( rep->gettype() ) { case REPORTA: rep2 = new ReportA; break; case REPORTB: rep2 = new ReportB; break; case REPORTC: rep3 = new ReportC; break; // use rep2. [ 문제점 ] 1. Client Code에게구체적 Report 객체로의접근을허용해야한다. 2. Client Code에서모든구체적 Report 객체를알고있어야한다. 3. 새로운구체적 Report 객체가추가될때마다 Client Code 가수정되어야한다. 4. rep2 객체가적합한클래스로생성은되지만, rep의내용을또다시복사해야한다.

프로토타입패턴 : 동기 l 불만사항해결방안 2: l 특정객체를복사해야되는경우, 객체생성과내용복사기능을해당객체에맡긴다. 48 // Client Code CopyReport(Report *rep) { Report *rep2 = rep->clone(); // use rep2 clone 함수는실제구체객체와동일한내용을가지는객체를생성해서반환하는기능제공 1. Client Code 에게구체적 Report 객체로의접근을허용하지않아도된다. 2. Client Code 에서모든구체적 Report 객체를알필요가없다. 3. 새로운구체적 Report 객체가추가되더라도기존 Client Code 가수정될필요는없다. 4. clone 함수내에서 rep 의내용의복사작업을수행한다. 48

프로토타입패턴 : 동기 [ 보고서관리 Class Library] Client Code Report clone() Report *rep2 = rep1->clone(); ReportA ReportC clone() clone() ReportB clone() ReportD clone() return new ReportB(this); return new ReportD(this); 49

프로토타입사례 Furniture color 50 Click on choice of desk: Click on choice of storage: Click on choice of chair: Furniture hardware type colonial

프로토타입사례 51

프로토타입패턴 Client (optional part of interface) Ensemble createensemble() Part1 clone() Part2 clone() MyPart anothermypart = mypartprototype.clone(); MyPart yetanothermypart = MyPartPrototype.clone(); 52

프로토타입패턴 The Prototype Idea Client Ensemble createensemble() mypartprototype 1 MyPart clone(): MyPart // To create a MyPart instance: MyPart p = mypartprototype.clone(); Prototype Design Pattern 53 MyPartStyleA clone() MyPartStyleB clone()

Client Ensemble createensemble() 프로토타입패턴 : 클래스모델 Part1 clone() part1prototype... // To create a Part1 object: Part1 p1 = part1prototype.clone();. 1 1 Part2 clone() part2prototype Part1StyleA clone() Part1StyleB clone() Part1StyleC clone() Part2StyleA clone() Part2StyleB clone() 54 Part1StyleB returnobject = new Part1StyleB();.

프로토타입패턴 : 동적다이어그램 :Ensemble partnprototype :PartN partnprototype :PartNStyleB :PartNStyleB createensemble() clone() PartNStyleB() (virtual function property) 55

프토토타입패턴사례 - 미로게임 l Sample Code l Abstract Factory pattern 의 Sample Code 에서 미로구축에사용되는 product 객체들 (room, wall, door) 을생성하기위하여, factory 를사용하였다. 다른 family 의 product 객체를생성하기위하여각 family 별로 factory 를작성하였다. (EnchantedMazeFactory, BombedMazeFactory) 만일 Factory 를하나만두고, 미리지정된 prototype 객체를이용하여 Room, Wall, Door 객체를생성하려면? 56 Factory 생성시각 product 객체의 prototype 객체를지정 각 product 객체에 Clone() 함수를구현하고, 필요시 Initialize() 함수를구현

class MazePrototypeFactory : public MazeFactory { public: MazePrototypeFactory(Maze*, Wall*, Room*, Door*) { _prototypemaze = m; _prototypewall = w; _prototyperoom = r; _prototypedoor = d; virtual Maze* MakeMaze() const { return _prototypemaze->clone(); virtual Room* MakeRoom(int roomno) const { Room *room = _prototyperoom->clone(); room->initialize(roomno); return room; virtual Wall* MakeWall() const { return _ptototypewall->clone(); virtual Door* MakeDoor(Room*, Room*) const { Door *door = _prototypedoor->clone(); door->initialize(r1,r2); return door; private: Maze* _prototypemaze; Room* _prototyperoom; Wall* _prototypewall; Door* _prototypedoor; ; 57 객체생성을위한 prototype 객체지정 - prototype 객체를이용하여 Maze, Room, Wall, Door 객체생성. - Room & Door 의경우 Initialize 함수를호출하여초기값지정 객체생성에사용될 prototype 객체

class Door : public MapSite { public: Door(); Door(const Door&){ _room1 = other._room1; _room2 = other._room2; virtual void Initialize(Room*, Room*){ _room1 = r1; _room2 = r2; virtual Door* Clone() const{ return new Door(*this); virtual void Enter(); Room* OtherSideFrom(Room*); private: Room* _room1; Room* _room2; ; class Wall : public MapSite { ; class Room: public MapSite { ; 58 clone() 후초기값설정함수 객체복제를위한 clone() 함수 // Client Code factory 에각객체생성을위한 prototype 객체지정 MazeGame game; MazePrototypeFactory simplemazefactory( new Maze, new Wall, new Room, new Door ); Maze* maze = game.createmaze(simplemazefactory);

프토토타입패턴사례 - 미로게임 class BombedWall : public Wall { public: BombedWall(); BombedWall(const BombedWall&): Wall(other) { _bomb = other._bomb; virtual Wall* Clone() const { return new BombedWall(*this); bool HasBomb() { return _bomb; private: bool _bomb; ; class RoomWithABomb : public MapSite { ; // Client Code MazeGame game; MazePrototypeFactory bombedmazefactory( new Maze, new BombedWall, new RoomWithABomb, new Door ); 59 Maze* maze = game.createmaze(bombedmazefactory);

Questions?