070626_D.P
팩토리와 컴포짓 패턴(탐색기) 데코레이션 패턴
# 데코레이터 패턴 -크림과 우유 주문-
- Beverage(음료) 클래스와 그속의 descriotion 그리고 그것을 가져오는 getDescription()와 cost()를 만든다.
- 밑에 4개의 상속받는 클래스들 HouseBlend / DarkRoast / Decaf / Espresso 클래스를 만들고 각각의 cost()를 재정의 한다.
- 하지만 얹는 토핑과 크림, 모카등의 추가로 가격이 바뀐다.
- 때문에 다른 방법을 찾는다. - Beverage 클래스의descrption속에 재료를 넣어버리면 되는것. hasMilk() , hasWhip() 등의 재료 get함수와 set함수도 만들어 부모 클래스에 넣어준다.
- 여기까지의 문제점.
- 첨가물의 가격이 바뀔 때 마다 기존 코드를 수정해야 한다.(OpenClosePre.. 원리를 위배함)
- 첨가물의 종류가 추가 되면 새로운 함수를 추가해야 하고, cost() 함수도 추가해야 한다.
- 첨가물이 들어가면 안되는 Tea 서브 클래스에서도 has whip과 같은 함수를 상속 받게 된다.
- 손님이 더블 모카를 주문하면 어떻게 해야 하나?
- =>해결) 데코레이터 패턴을 사용.
- 컴퍼넌트 클래스에 상속받는 콘크리트(구현) 컴퍼넌트와 데코레이터 클래스를 만들고, 데코레이터 클래스에 상속받는 콘크리트 데코레이터 A와 콘크리트 데코레이터 B 클래스를 만든다.
- 데코레이터 패턴에서는 객체에 추가적인 요건을 동적으로 첨가한다. 데코레에터는 서브 클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다.
- 각 데코레이터 패턴안에는 component 객체가 들어있다. 즉, 데코레이터에는 구성요소에 대한 레퍼런스가 들어 있는 인스턴스 변수이다.
- Beverage 객체아래 concreat 객체들(Espressom Decaf...등등)과 CondimentDecorator(getDescrotion()포함)객체를 만들고, Beverage를 감싸안는 포인터를 가지는 콘크리트 condimentDecorator 자식 함수들(milk,soy,whip...등등)을 만든다.
- CondimentDecorator객체는 디폴트로 함수 선언이 가능하다. 자식에서 재정의 되었기 때문이다.
- 변화에는 닫혀있고 확장에는 열려있는 코드이다.
#팩토리 패턴 -피자 주문-
- 피자를 주문하면 추상의 피자를 만들고(new) 피자를 준비해서, 만들고, 자르고, 박스에 넣는 함수를 가진다. 다형성을 이용해서 피자의 종류를 고르게 할 수 도 있다.
- 하지만..... 유연성을 감안하여 추상클래스로 만들면 좋지만 추상클래스는 인스턴스로 만들 수 없다. 실제 인스턴스 화 시킬땐 분기를 이용, 다형성을 이용하게 한다.
- 또한 변화하는 것은 밖으로 빼서 캡슐화 하는 것이 유리하다. 팩토리라는 클래스를 만들어 클래스를 생성하는 클래스로 만드는 것이다.
- 간단한 팩토리.
- 피자 추상 클래스피자를 만들고 피자의 상속을 받는 여러가지 피자를 만든다.
- 팩토리 메쏘드! - 분점을 자식으로 상속해서 쓰자.
- 프레임 워크. 부모가 실행순서를 정의해놓고 자식이 재정의해서 쓰되 순서를 바꿔쓰지 못하게 하는 것.
- 객체의 생성을 자식 팩토리에게 위임한다. 팩토리 메쏘드.
[과제] _ (금요일까지) pizzaaf를 주석 잔뜩 달아서 그림도 그려보고 C++로 만들어서 돌아가게 제출해라 [Homework]_pizzaaf_0706신진수.cpp
- #include <iostream>
#include <string>
using namespace std; - struct Beverage
{
string description;
Beverage( string desc="Unknown Beverage" ) : description(desc) {}
virtual string getDescription()
{
return description;
}
virtual double cost()=0;
}; - class Espresso : public Beverage
{
public:
Espresso()
{
description = "Espresso";
}
double cost()
{
return 1.99;
}
};
class DarkRoast : public Beverage {
public:
DarkRoast()
{
description = "Dark Roast Coffee";
}
double cost()
{
return .99;
}
};- class Decaf :public Beverage
{
public:
Decaf()
{
description = "Decaf Coffee";
}
double cost()
{
return 1.05;
}
}; - class HouseBlend : public Beverage
{
public:
HouseBlend()
{
description = "House Blend Coffee";
}
double cost()
{
return .89;
}
}; - class CondimentDecorator : public Beverage
{
public:
virtual string getDescription()=0;
}; - class Milk : public CondimentDecorator
{
Beverage *beverage; - public:
Milk(Beverage *beverage)
{
this->beverage = beverage;
} - string getDescription()
{
return beverage->getDescription() + ", Milk";
} - double cost()
{
return .10 + beverage->cost();
}
}; - class Mocha : public CondimentDecorator
{
Beverage *beverage;
public:
Mocha(Beverage *beverage)
{
this->beverage = beverage;
}
string getDescription()
{
return beverage->getDescription() + ", Mocha";
}
double cost()
{
return .20 + beverage->cost();
}
}; - class Soy : public CondimentDecorator
{
Beverage *beverage; - public:
Soy(Beverage *beverage)
{
this->beverage = beverage;
} - string getDescription()
{
return beverage->getDescription() + ", Soy";
} - double cost()
{
return .15 + beverage->cost();
}
}; - class Whip : public CondimentDecorator {
Beverage *beverage;
public:
Whip(Beverage *beverage)
{
this->beverage = beverage;
}
string getDescription()
{
return beverage->getDescription() + ", Whip";
}
double cost()
{
return .10 + beverage->cost();
}
}; - class Honey : public CondimentDecorator {
Beverage *beverage;
public:
Honey(Beverage *beverage)
{
this->beverage = beverage;
}
string getDescription()
{
return beverage->getDescription() + ", Honey";
}
double cost()
{
return .50 + beverage->cost();
}
}; - int main()
{
Beverage *beverage = new Espresso;
cout << beverage->getDescription() + " $" << beverage->cost() << endl; - Beverage *beverage2 = new DarkRoast;
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
beverage2 = new Honey(beverage2);
cout << beverage2->getDescription() + " $" << beverage2->cost() << endl; - Beverage *beverage3 = new HouseBlend;
beverage3 = new Soy(beverage3);
beverage3 = new Mocha(beverage3);
beverage3 = new Whip(beverage3);
beverage3 = new Honey(beverage3);
cout << beverage3->getDescription() + " $" << beverage3->cost() << endl;
return 0;
}
- /*
Pizza *orderPizza()
{
Pizza *pizza = new Pizza(); // 유연성을 감안하여 추상클래스로 만들면 좋지만
// 추상클래스는 인스턴스로 만들수 없다. - pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box(); - return pizza;
}
*/
/*
Pizza *orderPizza(string type)
{
Pizza *pizza;- if( type == "cheeze" )
pizza = new CheezePizza;
// else if( type == "greek" )
// pizza = new GreekPizza;
else if( type == "pepperoni" )
pizza = new PepperoniPizza;
else if( type == "clam" )
pizza = new ClamPizza;
else if( type == "veggie" )
pizza = new VeggiePizza; - pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box(); - return pizza;
}
*/
#if 0
#include <iostream>
#include <string>
#include <vector>
using namespace std; - struct Pizza
{
string name;
string dough;
string sauce;
vector<string> toppings; - string getName()
{
return name;
} - void prepare() {
cout << name + " Preparing" << endl;
} - void bake() {
cout << name + " Baking " << endl;
} - void cut() {
cout << name + " Cutting " << endl;
} - void box() {
cout << name + " Boxing " << endl;
} - string toString() {
string display;
display += "---- " + name + " ----\n";
display += dough + "\n";
display += sauce + "\n";
for (unsigned int i = 0; i < toppings.size(); i++)
display += toppings[i] + "\n";
return display;
}
}; - class CheesePizza : public Pizza {
public:
CheesePizza()
{
name = "Cheese Pizza";
dough = "Regular Crust";
sauce = "Marinara Pizza Sauce";
toppings.push_back("Fresh Mozzarella");
toppings.push_back("Parmesan");
}
}; - class ClamPizza : public Pizza {
public:
ClamPizza() {
name = "Clam Pizza";
dough = "Thin crust";
sauce = "White garlic sauce";
toppings.push_back("Clams");
toppings.push_back("Grated parmesan cheese");
}
}; - class VeggiePizza : public Pizza {
public:
VeggiePizza() {
name = "Veggie Pizza";
dough = "Crust";
sauce = "Marinara sauce";
toppings.push_back("Shredded mozzarella");
toppings.push_back("Grated parmesan");
toppings.push_back("Diced onion");
toppings.push_back("Sliced mushrooms");
toppings.push_back("Sliced red pepper");
toppings.push_back("Sliced black olives");
}
}; - class PepperoniPizza : public Pizza {
public:
PepperoniPizza() {
name = "Pepperoni Pizza";
dough = "Crust";
sauce = "Marinara sauce";
toppings.push_back("Sliced Pepperoni");
toppings.push_back("Sliced Onion");
toppings.push_back("Grated parmesan cheese");
}
}; - class SimplePizzaFactory
{
public:
Pizza * createPizza( string type )
{
Pizza *pizza = 0;
if( type == "cheese" )
pizza = new CheesePizza;
else if( type == "pepperoni" )
pizza = new PepperoniPizza;
else if( type == "clam" )
pizza = new ClamPizza;
else if( type == "veggie" )
pizza = new VeggiePizza; - return pizza;
}
}; - class PizzaStore
{
SimplePizzaFactory *factory; - public:
PizzaStore( SimplePizzaFactory *fac ) : factory(fac) {} - Pizza *orderPizza(string type)
{
Pizza *pizza = factory->createPizza( type ); - pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box(); - return pizza;
}
}; - int main()
{
SimplePizzaFactory *factory = new SimplePizzaFactory;
PizzaStore *store = new PizzaStore(factory); - Pizza *pizza = store->orderPizza("cheese");
cout << "We ordered a " + pizza->getName() + "\n"; - pizza = store->orderPizza("veggie");
cout << "We ordered a " + pizza->getName() + "\n"; - return 0;
}
#endif
#if 1
#include <iostream>
#include <string>
#include <vector>
using namespace std;- struct Pizza
{
string name;
string dough;
string sauce;
vector<string> toppings; - string getName()
{
return name;
} - void prepare() {
cout << name + " Preparing" << endl;
} - void bake() {
cout << name + " Baking " << endl;
} - void cut() {
cout << name + " Cutting " << endl;
} - void box() {
cout << name + " Boxing " << endl;
} - string toString() {
string display;
display += "---- " + name + " ----\n";
display += dough + "\n";
display += sauce + "\n";
for (unsigned int i = 0; i < toppings.size(); i++)
display += toppings[i] + "\n";
return display;
}
}; - class ChicagoStyleCheesePizza : public Pizza {
- public:
ChicagoStyleCheesePizza() {
name = "Chicago Style Deep Dish Cheese Pizza";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomatofffffffffffffffffffffffff Sauce";
toppings.push_back("Shredded Mozzarella Cheese");
}
void cut() {
cout << "Cutting the pizza into square slices" << endl ;
}
}; - class NYStyleCheesePizza : public Pizza {
- public:
NYStyleCheesePizza() {
name = "NY Style Sauce and Cheese Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
toppings.push_back("Grated Reggiano Cheese");
}
};
class PizzaStore
{
public:
Pizza *orderPizza(string type)
{
Pizza *pizza = createPizza( type );- pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box(); - return pizza;
} - virtual Pizza * createPizza(string) = 0;
}; - class NYPizzaStore : public PizzaStore {
Pizza *createPizza(string item) {
if (item == "cheese")
return new NYStyleCheesePizza;
/*
else if (item == "veggie")
return new NYStyleVeggiePizza;
else if (item == "clam")
return new NYStyleClamPizza;
else if (item == "pepperoni")
return new NYStylePepperoniPizza;
else return 0;
*/
}
};
class ChicagoPizzaStore : public PizzaStore {
Pizza *createPizza(string item)
{
if (item == "cheese" )
return new ChicagoStyleCheesePizza;
/*
else if (item == "veggie")
return new ChicagoStyleVeggiePizza;
else if (item == "clam")
return new ChicagoStyleClamPizza;
else if (item == "pepperoni")
return new ChicagoStylePepperoniPizza;
else return 0;
*/
}
};
int main()
{
PizzaStore *nyStore = new NYPizzaStore;
PizzaStore *chicagoStore = new ChicagoPizzaStore;- Pizza *pizza = nyStore->orderPizza("cheese");
cout << "Ethan ordered a " + pizza->getName() << endl; - pizza = chicagoStore->orderPizza("cheese");
cout << "Joel ordered a " + pizza->getName() << endl; - return 0;
}
#endif
History
Last edited on 01/01/2008 23:15 by jinsu56
Comments (0)