[๊ฐ์ฒด์งํฅ์ค๊ณ] GoF(Gang of Four) ๋์์ธ ํจํด(ํ๋กํ ํ์ , ์ถ์ ํฉํ ๋ฆฌ, ์ด๋ํฐ, ๋ธ๋ฆฌ์ง, ๋ณตํฉ์ฒด, ํผ์ฌ๋, ํ๋ก์)
Prototype Pattern(ํ๋กํ ํ์ )
ํ๋กํ ํ์ ์ ์์ฑ ํจํด์ ์ผ์ข ์ผ๋ก ๊ฐ์ฒด์ ๋ณต์ฌ๋ฅผ ์ํ ํจํด์ด๋ค.
๊ธฐ์กด์๋ ๊ฐ์ฒด๋ฅผ ๋ณต์ฌํ๊ธฐ ์ํด ๊ทธ ํ๋กํผํฐ๋ค์ ๋ชจ๋ ๋ณต์ฌํ์ฌ, ์๋กญ๊ฒ ๊ฐ์ฒด๋ฅผ ๊ตฌ์ฑํ์ฌ์ผ ํ๋ค. ์ด๋ฌํ ๋ฐฉ์์ ์ฝ๋๋ก ํ๋ํ๋ ์ง๊ธฐ์ ๊ท์ฐฎ๋ค. ๋ํ ํด๋์ค ๋ด๋ถ์ Private๋ก ์ ์ธ๋ ํ๋กํผํฐ๋ค์ด ์๋ค๋ฉด ์๋ฒฝํ๊ฒ ๋ณต์ฌํด๋ผ ์ ์๋ค.
ํ๋กํ ํ์ ํจํด์ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ณต์ฌ ํ๋ก์ธ์ค๋ฅผ ๊ฐ์ฒด๋ค์๊ฒ ์์ํ๋ค. ์ฆ, ๋ชจ๋ ๊ฐ์ฒด๋ค์ด ๊ณตํต์ ์ผ๋ก ๊ฐ์ง๊ณ ์๋ "clone" ๋ฉ์๋๋ฅผ ๋ง๋๋ ๊ฒ์ด๋ค.
๋ชจ๋ ๊ฐ์ฒด๋ค์ด clone ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ฒ ๋๋ค๋ฉด, ๊ฐ ๊ฐ์ฒด์ private ๋ฉค๋ฒ์ ์ ๊ทผํ ์ ์๊ฒ๋๋ค. ์ด ๋ง์ด ์๋ฏธํ ๊ฒ์ ๊ณง, ์๋ฒฝํ๊ฒ ํด๋น ๊ฐ์ฒด์์ ์๋ก์ด ๊ฐ์ฒด๋ก ๋ณต์ฌ๊ฐ ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ด๋ค.
์ด๋ ๊ฒ ๋ณต์ฌ๋ฅผ ์ง์ํ๋ ๊ฐ์ฒด๋ฅผ ํ๋กํ ํ์ ์ด๋ผ๊ณ ํ๋ค.
ํ๋กํ ํ์ ํจํด์ ๊ตฌ์กฐ
๊ตฌ์กฐ๋ ํฌ๊ฒ ์ด๋ ต์ง ์๋ค. Shape๋ clone()์ด๋ผ๋ ๊ณตํต ๋ฉ์๋๋ฅผ ์ ์ํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ด Shape์ ์์์ ๋ฐ๋ Rectangle๊ณผ Circle์ ์ด clone ๋ฉ์๋๋ฅผ ๋๊ฐ์ด ๊ฐ์ง๋ค. ์ด๋ฅผ ํตํด Rectangle๊ณผ Circle์ ์๊ธฐ ์์ ์ ๊ฐ์ฒด๋ฅผ ๋ณต์ ํ ์ ์๊ฒ ๋๋ ๊ฒ์ด๋ค.
ํ๋กํ ํ์ ์ C++๋ก
Color ํด๋์ค
enum class Color {
kRed,
kGreen,
kBlue,
kWhite,
kBlack,
};
std::string ColorToString(Color color) {
switch (color) {
case Color::kRed:
return "Red";
case Color::kGreen:
return "Green";
case Color::kBlue:
return "Blue";
case Color::kWhite:
return "White";
case Color::kBlack:
return "Black";
default:
return "Unknown";
}
}
Shape ํด๋์ค(ํ๋กํ ํ์ <interface>)
class Shape {
public:
Shape(Color color) : color_(color) {}
virtual Shape* Clone() const = 0;
virtual std::string ToString() const = 0;
protected:
const Color color_;
};
Rectangle ํด๋์ค(ํ๋กํ ํ์ ๊ตฌํ์ฒด1)
class Rectangle : public Shape {
public:
Rectangle(Color color, int width, int height)
: Shape(color), width_(width), height_(height) {}
Shape* Clone() const override {
return new Rectangle(color_, width_, height_);
}
std::string ToString() const override {
return "Color: " + ColorToString(color_) +
", Width: " + std::to_string(width_) +
", Height: " + std::to_string(height_);
}
private:
const int width_;
const int height_;
};
Circle ํด๋์ค(ํ๋กํ ํ์ ๊ตฌํ์ฒด2)
class Circle : public Shape {
public:
Circle(Color color, int radius) : Shape(color), radius_(radius) {}
Shape* Clone() const { return new Circle(color_, radius_);}
std::string ToString() const {
return "Color: " + ColorToString(color_) + ", Radius: " +
std::to_string(radius_);
}
private:
const int radius_;
};
Main ํด๋์ค
int main() {
Shape* shape1 = new Rectangle(Color::kWhite, 3, 2);
Shape* shape2 = shape1 -> Clone();
Shape* shape3 = new Circle(Color::kRed, 5);
Shape* shape4 = shape3 -> Clone();
std::cout << shape1 << " : " << shape1 -> ToString() << std::endl;
std::cout << shape2 << " : " << shape2 -> ToString() << std::endl;
std::cout << shape3 << " : " << shape3 -> ToString() << std::endl;
std::cout << shape4 << " : " << shape4 -> ToString() << std::endl;
}
์คํ ๊ฒฐ๊ณผ
0xfb9b10 : Color: White, Width: 3, Height: 2
0xfb9b28 : Color: White, Width: 3, Height: 2
0xfb9b40 : Color: Red, Radius: 5
0xfb9b58 : Color: Red, Radius: 5
๐ฒ C++์์์ prototype์ ํจ์ ์ค๋ฒ๋ก๋ฉ๊ณผ ํจ์ ์ค๋ฒ๋ผ์ด๋ฉ์ ๊ณผ์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋ค.
๐ฒ Shape์ virtual ... Clone() ์ ํตํด์ ๊ฐ Rectangle, Circle ์ค ํ๋์ Clone()์ด ์คํ๋๋ค.
๐ฒ ์ถ๋ ฅ ๊ฒฐ๊ณผ Clone()์ ํตํด ์๋ก ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ ์์ฑ๋์์ผ๋ฉฐ, ๊ทธ ๋ด์ฉ๋ฌผ์ ๊ฐ๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
Abstract Factory Pattern(์ถ์ ํฉํ ๋ฆฌ)
์ถ์ ํฉํ ๋ฆฌ๋ ๊ด๋ จ ๊ฐ์ฒด๋ค์ ๊ตฌ์ ํด๋์ค๋ค์ ์ง์ ํ์ง ์๋๋ผ๋, ๊ด๋ จ ๊ฐ์ฒด์ ๋ชจ์์ ์ ํํ ์ ์๋ ์์ฑ ํจํด์ด๋ค.
๋ง์ฝ์ ์ฃผ๋ฌธ์(Client) ๋น ํ ๋ฆฌ์์ ์์, ์ํ, ์ปคํผ ํ ์ด๋ธ์ ๊ตฌ๋งคํ๊ณ ์ถ์ ๋, ๊ตณ์ด ๊ตฌ์ฒด์ ์ผ๋ก ๋น ํ ๋ฆฌ์ ์ ์์, ๋น ํ ๋ฆฌ์ ์ ์ํ, ๋น ํ ๋ฆฌ์์ ์ปคํผ ํ ์ด๋ธ์ ์ฃผ๋ฌธํ์ง ์์๋ ๋๋ค.
๊ฒฐ๊ตญ ์ฃผ๋ฌธ์๋ ์ด๋ ํ์ฌ(ํฉํ ๋ฆฌ)์์ ๊ตฌ๋งคํ ๊ฒ์ธ์ง ์ ํด์ผ ํ๋ค. ๋น ํ ๋ฆฌ์์์ผ๋ก ๊ฐ ์ ํ์ ํ๋งคํ๋ ๋น ํ ๋ฆฌ์ ํฉํ ๋ฆฌ, ์๋ฅด๋ฐ์ฝ ์์ผ๋ก ๊ฐ ์ ํ์ ํ๋งคํ๋ ์๋ฅด๋ฐ์ฝ์ ํฉํ ๋ฆฌ, ๋ง์ฐฌ๊ฐ์ง๋ก ํ๋์ ํฉํ ๋ฆฌ๊ฐ ์๋ค๊ณ ํ์. ์ฃผ๋ฌธ์๋ ๋น ํ ๋ฆฌ์ ํฉํ ๋ฆฌ์์์ ์ ํ๋ง์ ์ํ๋ค๋ฉด ๊ตฌ์ฒด ํฉํ ๋ฆฌ๋ก ๋น ํ ๋ฆฌ์ ํฉํ ๋ฆฌ๋ฅผ ์ ํํ๋ฉด ๋๋ค.
์ ์ด์ ๋ค์ ๊ทธ ์๋ฏธ๋ฅผ ์ง์ด๋ณด์. ์ถ์ ํฉํ ๋ฆฌ๋, ๊ด๋ จ ๊ฐ์ฒด(์์, ์ํ, ์ปคํผ ํ ์ด๋ธ)๋ค์ ๊ตฌ์ ํด๋์ค(๋น ํ ๋ฆฌ์์ ์์, ๋น ํ ๋ฆฌ์ ์ ์ํ, ...)๋ฅผ ์ง์ ํ์ง ์๋๋ผ๋, ๊ด๋ จ ๊ฐ์ฒด์ ๋ชจ์(๋น ํ ๋ฆฌ์ ์ ์์, ๋น ํ ๋ฆฌ์ ์....)์ ์ ํํ ์ ์๋ ์์ฑ ํจํด์ด๋ค.
๋ค์๋งํด, ์ฐ๊ด์ฑ ์๋ ์ ํ ๊ตฐ์ด ์ฌ๋ฌ๊ฐ ์์ ๊ฒฝ์ฐ ์ด๋ฅผ ๋ฌถ์ด ์ถ์ํํ๊ณ , ๊ตฌ์ฒด์ ์ธ ์ํฉ์ด ์ฃผ์ด์ง ๋ ํฉํ ๋ฆฌ ๊ฐ์ฒด์์ ์งํฉ์ผ๋ก ๋ฌถ์ ๊ฐ์ฒด๊ตฐ์ ๊ตฌํํ๋ ํจํด์ด๋ผ๋ ๊ฒ์ด๋ค.
์ถ์ ํฉํ ๋ฆฌ ํจํด์ ํน์ง
์ถ์ ํฉํ ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ์๊ธฐ
1๏ธโฃ ์ ํ์ ๊ตฌ์ฒด ํด๋์ค์ ์์กดํ๊ณ ์ถ์ง ์์ ๋(์ฌ๋ฌ ์ ํ๊ตฐ์ด ์์ ๊ฒฝ์ฐ)
2๏ธโฃ ์์คํ ์์์ ํ๋์ ์ ํ ๊ตฐ์ผ๋ก ์ค์ ํด์ผ ํ๋ ๊ฒฝ์ฐ(์๋ฅผ ๋ค์ด ์ ํ ์ ํ ๊ตฐ์ผ๋ก ํต์ผ ํด์ผํ ๋)
3๏ธโฃ ๊ตฌํ ๋ถ๋ถ ๋์ ์ธํฐํ์ด์ค ๋ถ๋ถ๋ง ๋ณด์ฌ์ฃผ๊ณ ์ถ์ ๊ฒฝ์ฐ
์ถ์ ํฉํ ๋ฆฌ์ ์ฅ์
1๏ธโฃ ํด๋ผ์ด์ธํธ ์ฝ๋์์ ๊ฒฐํฉ์ฑ์ ๋ฎ์ถค
2๏ธโฃ ์ ํ์ ์ฝ๊ฒ ๋์ฒด ๊ฐ๋ฅ
์ถ์ ํฉํ ๋ฆฌ์ ๋จ์
1๏ธโฃ ๋ง๋ค์ด์ผ ํ๋ ํด๋์ค๊ฐ ๋ง์์ ธ, ๋ณต์ก๋๊ฐ ์ฆ๊ฐ
2๏ธโฃ ์ถ์ ํด๋์ค ๋ก์ง ์์ฒด๋ฅผ ๋ฐ๊พธ์ด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊น
์ถ์ ํฉํ ๋ฆฌ ํจํด์ ๊ตฌ์กฐ
์ถ์ ํฉํ ๋ฆฌ ํจํด์ ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ํด์๋ ๊ทธ ๊ตฌ์กฐ๋ฅผ ๋ช ํํ ์๊ณ ์์ด์ผ ํ๋ค.
๐ฒ AbstractFactory : ์ถ์ ํฉํ ๋ฆฌ๋ก ์ถ์ ์ ํ๋ค์ ์์ฑํ๊ธฐ ์ํ ์ฌ๋ฌ ๋ฉ์๋๋ค์ ์งํฉ์ ์ ์ธํ๋ค.
๐ฒ ConcreteFactory : ๊ตฌ์ ํฉํ ๋ฆฌ๋ก ์ถ์ ํฉํ ๋ฆฌ์ ์์ฑ ๋ฉ์๋๋ค์ ๊ตฌํํ๋ค.
๐ฒ AbstractProduct : ์ถ์ ์ ํ์ผ๋ก ๊ฐ ํ์ ์ ์ ํ๋ค์ ์ถ์ํํ ์ธํฐํ์ด์ค์ด๋ค.
๐ฒ ConcreteProduct(ProductA, ProductB) : ๊ฐ ํ์ ์ ์ ํ ๊ตฌํ์ฒด๋ค์ด๋ค.
๐ฒ Client : ์ถ์ํ๋ ์ธํฐํ์ด์ค๋ง์ ์ด์ฉํ์ฌ ์ ํ์ ๋ง๋ ๋ค.
๊ฐ ConcreteFactory(๊ตฌ์ ํฉํ ๋ฆฌ)๋ ๊ตฌ์ฒด์ ์ธ ๊ณต์ฅ์ผ๋ก, ์ ํ ๊ตฐ์ ์ ํ์ ๋ฐ๋ผ ๋๋๋ค. ์๋ฅผ ๋ค์ด, ๋น ํ ๋ฆฌ์์ ๊ณต์ฅ, ์๋ฅด๋ฐ์ฝ์ ๊ณต์ฅ, ํ๋์ ๊ณต์ฅ๋ฑ์ด ์ด๋ฌํ ConcreteFactory์ ์ํ๋ค.
ConcreteFactory ๋ฅผ ํตํด์ ConcreteProduct (์ ํ ๊ตฌํ์ฒด)๋ฅผ ๋ง๋ค ์ ์๋ค. ConcreteProduct๋ ๊ทธ ์ธํฐํ์ด์ค๋ก AbstractProduct ๋ฅผ ๋ฐ๋ฅด๋ ๊ฒ ๋ฟ์ด๋ค.
์ถ์ ํฉํ ๋ฆฌ ํจํด์ C++๋ก
์ถ์ ํฉํ ๋ฆฌ(AbstractFactory)
// ์ถ์ ํฉํ ๋ฆฌ
class FurnitureFactory {
public:
virtual Chair* OrderChair() const = 0;
virtual Table* OrderTable() const = 0;
};
๊ตฌ์ ํฉํ ๋ฆฌ(ConcreteFactory)
// ๊ตฌ์ ํฉํ ๋ฆฌ1
class ModernFactory : public FurnitureFactory {
public:
// ๊ตฌํ์ฒด๋ฅผ ์์ฑํ๋ ๋ฉ์๋๋ฅผ ์ง๋. ๋ฐํ ํ์
์ AbstractProduct
Chair* OrderChair() const override {
return new ModernChair();
}
Table* OrderTable() const override {
return new ModernTable();
}
};
// ๊ตฌ์ ํฉํ ๋ฆฌ2
class AntiqueFactory : public FurnitureFactory {
public:
Chair* OrderChair() const override {
return new AntiqueChair();
}
Table* OrderTable() const override {
return new AntiqueTable();
}
};
์ถ์ ์ ํ(AbstractProduct)
// ์ถ์ ์ ํ1
class Chair {
public:
virtual std::string ToString() const = 0;
};
// ์ถ์ ์ ํ2
class Table {
public:
virtual std::string ToString() const = 0;
};
๊ตฌ์ ์ ํ(ConcreteProduct)
// ๊ตฌํ์ฒด 1
class ModernChair : public Chair {
public:
std::string ToString() const override {
return "Modern Chair";
}
};
// ๊ตฌํ์ฒด 2
class ModernTable : public Table {
public:
std::string ToString() const override {
return "Modern Table";
}
};
// ๊ตฌํ์ฒด 3
class AntiqueChair : public Chair {
public:
std::string ToString() const override {
return "Antique Chair";
}
};
// ๊ตฌํ์ฒด 4
class AntiqueTable : public Table {
public:
std::string ToString() const override {
return "Antique Table";
}
};
์คํ ๋ฉ์๋ ๋ฐ main ํจ์
void OrderAndPrint(FurnitureFactory* factory) {
Chair* chair = factory->OrderChair();
Table* table = factory->OrderTable();
std::cout << "Table: " << table->ToString() << ", Chair: " << chair->ToString() << std::endl;
}
int main() {
ModernFactory modern_factory;
AntiqueFactory antique_factory;
OrderAndPrint(&modern_factory);
OrderAndPrint(&antique_factory);
return 0;
}
์คํ ๊ฒฐ๊ณผ
Table: Modern Table, Chair: Modern Chair
Table: Antique Table, Chair: Antique Chair
๐ฒ ์ถ์ ํฉํ ๋ฆฌ์์ ๋ค์ด์ค๋ ๊ตฌ์ฒด ํฉํ ๋ฆฌ์ ํ์ ์ ๋ฐ๋ผ ๊ตฌ์ฒด ํฉํ ๋ฆฌ์ ๋ฉ์๋๊ฐ ์คํ๋๋ค.
๐ฒ ๊ตฌ์ฒด ํฉํ ๋ฆฌ์ ๋ฉ์๋๋ฅผ ์คํ์ํด์ผ๋ก์จ, ๊ฐ ์ ํ๊ตฐ์ ์ผ์นํ๋ ์ ํ(๊ตฌํ์ฒด)๋ฅผ ์์ฑํ ์ ์๋ค.
๐ฒ ๊ตฌ์ฒด ํฉํ ๋ฆฌ์์ ์คํ๋๋ ๋ฉ์๋์์ ๋ฐํ๋๋ ํ์ ์ ๊ฐ ์ ํ์ ์ถ์ ์ ํ(Abstract Product)์ด๋ค.
Structural Design Patterns(๊ตฌ์กฐ ํจํด)
๊ตฌ์กฐ ํจํด์ ํด๋์ค์ ๊ฐ์ฒด๋ฅผ ๋์ฑ ํฐ ๊ตฌ์กฐ๋ก ๋ง๋ค๊ธฐ ์ํด์ ์ฌ์ฉํ๋ค. ๊ตฌ์กฐ ํจํด์ ์ข ๋ฅ๋ ์๋์ ๊ฐ๋ค.
- Adapter
- Bridge
- Composite
- Decorate
- Facade
- Flyweight
- Proxy
- ...
Adapter Patterns(์ด๋ํฐ ํจํด)
์ด๋ํฐ ํจํด์ ์ฝ๊ฒ ์ดํดํด ๋ณด์๋ฉด, ์ ์๊ธฐ๊ธฐ ๋จ์๋ฅผ ํธํํ๊ฒ ํด์ฃผ๋ ์ด๋ํฐ๋ฅผ ์๊ฐํ๋ฉด ๋๋ค. ์ฆ, ์ด๋ํฐ๋ ํด์ธ์ฌํ์ ๊ฐ๋ ์ฌ์ฉํ ์ ์๋ ์ฝ์ผํธ์ ๋์ ์ ์๊ธฐ๊ธฐ๋ฅผ ์ฐ๊ฒฐํด์ฃผ๋ ์ญํ ๊ณผ ๋์ผ ๋งฅ๋ฝ์ด๋ค.
๊ฐ์ฒด์งํฅ์ค๊ณ์ ๊ด์ ์ผ๋ก ์ด๋ฅผ ๋ค์ ํด์ํ์๋ฉด, ํธํ์ฑ ์๋ ์ธํฐํ์ด์ค ๋๋ฌธ์ ๋์ํ์ง ๋ชปํ๋ ํด๋์ค๋ค์ ๋์ํ ์ ์๋๋ก ์ค๊ฐ์ ๋ณํํด์ฃผ๋ ํจํด์ด๋ผ๊ณ ํ ์ ์๋ค.
์ด๋ฌํ ์ด๋ํฐ ํจํด์ ์์์ ํ๋, ํฉ์ฑ์ ํ๋์ ๋ฐ๋ผ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ๋๋๋ค. ์ฐ๋ฆฌ๋ ์ฌ๊ธฐ์ ์ถ์ฒ๋๋ ๋ฐฉ๋ฒ์ธ ๊ฐ์ฒด ์ด๋ํฐ(Object Adapter)์ ๋ํด ์์๋ณผ ๊ฒ์ด๋ค.
์์์ ์ฌ์ฉํ๋ ํด๋์ค ์ด๋ํฐ์ ๊ฒฝ์ฐ, C++ ๊ฐ์ด ๋ค์ค ์์์ ์ง์ํด์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค.
Object Adapter Pattern
๊ฐ์ฒด ์ด๋ํฐ(Object Adapter)์ ํฐ ํน์ง์ผ๋ก๋ ๊ฐ์ฒด ํฉ์ฑ์ ์์น์ ์ฌ์ฉํ๋ค๋ ๊ฒ์ด๋ค. ์ฆ, ํฉ์ฑ์ ํตํด์ Client๋ Adapter๋ฅผ ํตํด ์ํ๋ Service๋ฅผ ์คํํ ์ ์๋ค.
์ฌ๊ธฐ์ Service๋ Adaptee๋ผ๊ณ ๋ ๋ถ๋ฆฌ๋๋ฐ, ์ด ๊ฐ์ฒด๊ฐ Adapter์ ๋ฉค๋ฒ ๋ณ์๋ก์จ ์์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ณต๊ฐ ์ฐจ์ง ๋น์ฉ์ด ์กฐ๊ธ ๋ ๋ ๋ค.
๐ฒ Service(Adaptee) : ํธํ๋์ง ์๋ ์ธ๋ถ ์์คํ , ์จ๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
๐ฒ Client Interface : Adapter๊ฐ ๊ตฌํํ๋ ์ธํฐํ์ด์ค
๐ฒ Adapter : Client์ Service ์ฌ์ด๋ฅผ ์ด์ด์ฃผ๋ ์ญํ ์ ํ๋ค.
- Adaptee๋ฅผ ํด๋์ค ๋ฉค๋ฒ๋ก ์ค์ ํ ํ์, ์์์ ํตํด์ ๋์ํ๊ฒ ํ๋ค.
๐ฒ Client : Client Interface๋ฅผ ํตํด Service๋ฅผ ์ํํ ์ ์๋ค.
Object Adapter Pattern์ C++๋ก
#include <algorithm>
#include <iostream>
#include <sstream>
#include <vector>
class Json {};
class Xml {};
class Yaml {};
class Result {
// Result ํด๋์ค์ ์ ์
// ๊ฒฐ๊ณผ ๋ฐ์ดํฐ ๋ฐ ๊ด๋ จ ๋ฉ์๋๋ฅผ ์ถ๊ฐํด์ผ ํจ
};
class JsonAnalyzer {
public:
Result Analyze(Json json) { /* JSON ๋ถ์ ๋ก์ง์ ๊ตฌํํด์ผ ํจ */ }
};
class XmlAnalyzer {
public:
XmlAnalyzer() : json_analyzer_() {}
Result Analyze(Xml xml) {
return json_analyzer_.Analyze(ToJson(xml));
}
private:
Json ToJson(Xml xml) { /* XML์ JSON์ผ๋ก ๋ณํํ๋ ๋ก์ง์ ๊ตฌํํด์ผ ํจ */ }
JsonAnalyzer json_analyzer_;
};
class YamlAnalyzer {
public:
YamlAnalyzer() : json_analyzer_() {}
Result Analyze(Yaml yaml) {
return json_analyzer_.Analyze(ToJson(yaml));
}
private:
Json ToJson(Yaml yaml) { /* YAML์ JSON์ผ๋ก ๋ณํํ๋ ๋ก์ง์ ๊ตฌํํด์ผ ํจ */ }
JsonAnalyzer json_analyzer_;
};
Xml GetXmlFile() { /* XML ํ์ผ์ ์ฝ์ด์ค๋ ๋ก์ง์ ๊ตฌํํด์ผ ํจ */ }
Yaml GetYamlFile() { /* YAML ํ์ผ์ ์ฝ์ด์ค๋ ๋ก์ง์ ๊ตฌํํด์ผ ํจ */ }
int main() {
Xml xml = GetXmlFile();
Yaml yaml = GetYamlFile();
XmlAnalyzer xml_analyzer;
YamlAnalyzer yaml_analyzer;
Result xml_analysis_result = xml_analyzer.Analyze(xml);
Result yaml_analysis_result = yaml_analyzer.Analyze(yaml);
// ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ก์ง์ ์ถ๊ฐํด์ผ ํจ
}
๊ตฌ์ฒด์ ์ธ ๋ก์ง์ ์๋ตํ๊ณ , ์ด๋ค ๊ตฌ์กฐ๋ก ํจํด์ด ๋์ํ๋ ์ง ์ดํด๋ณด์.
๐ฒ Adaptee(Service) : JsonAnalyzer๋ก, json ํ์ผ๋ง์ ๋ฐ์ Result ๊ฐ์ฒด๋ก ๋ณํํด์ฃผ๋ ์๋น์ค์ด๋ค.
๐ฒ Adaptor : XmlAnalyzer, YamlAnalyzer๋ก, xml๊ณผ yaml ํ์ผ์ ๋ฐ์ json์ผ๋ก ๋ณํํด์ฃผ๋ฉฐ Adaptee(JsonAnlyzer)๋ฅผ ๋ฉค๋ฒ ๋ณ์๋ก ํฌํจํ๊ณ ์๋ค.
๐ฒ Adaptee๋ฅผ ํฉ์ฑํ๋ ๋ถ๋ถ์ private์ด๋ฉฐ, ๋๋จธ์ง ๋ฉ์๋ ์คํ ๋ถ๋ถ์ public์ด๋ค.
Bridge Patterns(๋ธ๋ฆฌ์ง ํจํด)
๋ธ๋ฆฌ์ง ํจํด์ ๊ฐ์ฒด์ ํ์ฅ์ฑ์ ํฅ์์ํค๊ธฐ ์ํ ํจํด์ผ๋ก, ๊ฐ์ฒด์ ๋๋ฌด ๋ง์ ๊ธฐ๋ฅ์ด ํฌํจ๋์ด ์ ์ง ๋ณด์๊ฐ ํ๋ค ๋ ์ฌ์ฉํ ์ ์๋ค.
์ด๋ฅผ ์ํด ๋ธ๋ฆฌ์ง๋ ์์ ๋์ ๊ฐ์ฒด ํฉ์ฑ์ด๋ผ๋ ์๋จ์ ํํ๋ค. ์์์ ์ฌ์ฉํ๋ค๋ฉด, ๊ธฐํ ๊ธ์์ ์ธ ๊ณ์ธต ๊ตฌ์กฐ๊ฐ ํ์ฑ๋ ์๋ ์๊ธฐ ๋๋ฌธ์ด๋ค.
Adapter์์๋ Service์ ๋ํ ํฉ์ฑ์ ํตํด ํธํ์ฑ์ ๋ง์ถฐ์คฌ๋ฏ์ด, ๋ธ๋ฆฌ์ง๋ ๊ฐ์ฒด ํฉ์ฑ์ ํตํด ๊ธฐ๋ฅ์ ํฅ์์ ๋๋ชจํ๋ค.
๊ทธ๋ฆผ์ ๋ณด๋ฉด์๋ ์ ์ ์๋ฏ์ด, ๋ชจ์์ด๋ผ๋ ํด๋์ค ์์ ์์ด๋ผ๋ ๊ฐ์ฒด๋ฅผ ํฌํจ ์ํด์ผ๋ก์จ ํ์ฅ์ ๋์ฑ ์ ๋ฆฌํด์ก๋ค.
๋ธ๋ฆฌ์ง ํจํด์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
๐ฒ ๋ถ๋ชจ ์ถ์ ํด๋์ค(๋ชจ์)์์ ๊ธฐ๋ณธ์ ์ธ ๊ท์น์ด ์ ์๋์ด ์๊ณ , ๊ตฌ์ฒด์ ์ธ ํด๋์ค(๋นจ๊ฐ, ํ๋)๊ฐ ์ถ๊ฐ ๊ท์น์ ์ค์ ํ๊ณ ์ถ์ ๋
๐ฒ ๊ฐ์ฒด์ ๋ํ ์ฐธ์กฐ๊ฐ ์๋ ์ถ์ ํด๋์ค๊ฐ ์๊ณ (๋ชจ์), ๊ตฌ์ฒด์ ์ธ ํด๋์ค์์ ์ ์๋ ์ถ์ ๋ฉ์๋(์)๊ฐ ์กด์ฌํ ๋
์ถ์ํ์ ๊ตฌํ
๋ธ๋ฆฌ์ง ํจํด์ ์ถ์ํ์ ๊ตฌํ์ผ๋ก ์ ์ํ ์ ์๋ค. ์์ ๋งํ๋ฏ์ด, ๋ธ๋ฆฌ์ง ํจํด์ ๊ฐ์ฒด ํฉ์ฑ์ ํตํด์ ๊ตฌํํ๋ค๊ณ ํ๋ค. ์ฆ, ๊ฐ์ฒด ํฉ์ฑ์ด ์ด๋ฃจ์ด์ง๋ ์ถ์ ํด๋์ค๊ฐ ๋ฐ๋ก ์ถ์ํ, ๊ทธ๋ฆฌ๊ณ ํฉ์ฑ ๋นํ๋ ๊ฐ์ฒด๋ฅผ ๊ตฌ์ฒด์ ์ธ ํด๋์ค๋ก ์๊ฐํ ์ ์๋ค.
์ด๋ ๋ฏ, ์ถ์ํ์ ๊ตฌํ ๋ถ๋ถ์ผ๋ก ๋๋๋ ์ด์ ๋ "์ ์ง ๋ณด์" ๋๋ฌธ์ด๋ค. ๋ง์ฝ ์ถ์ํ๋ ๊ตฌํ ์๊ด์์ด ์ ์ฒด ์ฝ๋๋ฅผ ์ดํดํด์ผ ํ๋ ๋ชจ๋๋ก์ ์ฝ๋ ๋ฒ ์ด์ค๋ผ๋ฉด, ๋ณ๊ฒฝ์ด ํ๋ ๋ฐ์ํ ๋๋ง๋ค ๋๋ฌด๋๋ ํ๋ค ๊ฒ์ด๋ค.
ํ์ง๋ง, ์ถ์ํ ๋ถ๋ถ๊ณผ ๊ตฌํ ๋ถ๋ถ์ ๋๋๊ณ ๋ธ๋ฆฌ์ง๋ก ์ด์ด์ค๋ค๋ฉด, ๊ตณ์ด ์ ์ฒด ์ฝ๋์ ๋ํ ์ดํด๊ฐ ์์ด๋ ๋ณ๊ฒฝํ๊ธฐ ์ ๋ฆฌํ ๊ฒ์ด๋ค.
Bridge Patterns(๋ธ๋ฆฌ์ง ํจํด)์ ๊ตฌ์กฐ
๐ฒ Abstraction(์ถ์ํ) : Remote์ ํด๋นํ๋ ๋ถ๋ถ์ผ๋ก, Client๋ ์ถ์ํ๋ฅผ ํตํด ์์ ์ ์ํํ ์ ์๋ค.
- private ๋ฉค๋ฒ๋ก ๊ตฌํ ๋ถ๋ถ์ธ Implementation ์ธํฐํ์ด์ค๋ฅผ ํฌํจํ๋ค.(๊ฐ์ฒด ํฉ์ฑ)
๐ฒ Implementiation(๊ตฌํ) : ๊ตฌ์ฒด์ ์ธ ํด๋์ค์ ๋ํ ๊ณตํต ์ธํฐํ์ด์ค๋ฅผ ์ ์ธํ๋ค.
๐ฒ Concrete Impementations(๊ตฌ์ฒด์ ์ธ ํด๋์ค) : ํ๋ซํผ ๋ณ ๋ง์ถค ์ฝ๋๊ฐ ์ ๊ณต๋๋ค.
๐ฒ Refined Abstraction(์ ์ ํ๋ ์ถ์ํ) : ์ถ์ํ์ ๋ง์ฐฌ๊ฐ์ง๋ก, ๊ตฌํ ์ธํฐํ์ด์ค๋ฅผ ํตํด ์์ ํ๋ค
Bridge Patterns(๋ธ๋ฆฌ์ง ํจํด)์ C++๋ก
#include <algorithm>
#include <iostream>
#include <sstream>
#include <vector>
class Implementation {
public:
virtual ~Implementation() {}
virtual std::string OperationImplementation() const = 0;
};
class ConcreteImplementationA : public Implementation {
public:
std::string OperationImplementation() const override {
return "ConcreteImplementationA: Here's the result on the platform A.\n";
}
};
class ConcreteImplementationB : public Implementation {
public:
std::string OperationImplementation() const override {
return "ConcreteImplementationB: Here's the result on the platform B.\n";
}
};
class Abstraction {
protected:
Implementation* implementation_;
public:
Abstraction(Implementation* implementation) : implementation_(implementation) {
}
virtual ~Abstraction() {
}
virtual std::string Operation() const {
return "Abstraction: Base operation with:\n" +
this->implementation_->OperationImplementation();
}
};
class ExtendedAbstraction : public Abstraction {
public:
ExtendedAbstraction(Implementation* implementation) : Abstraction(implementation) {
}
std::string Operation() const override {
return "ExtendedAbstraction: Extended operation with:\n" +
this->implementation_->OperationImplementation();
}
};
void ClientCode(const Abstraction& abstraction) {
// ...
std::cout << abstraction.Operation();
// ...
}
int main() {
Implementation* implementation = new ConcreteImplementationA;
Abstraction* abstraction = new Abstraction(implementation);
ClientCode(*abstraction);
std::cout << std::endl;
delete implementation;
delete abstraction;
implementation = new ConcreteImplementationB;
abstraction = new ExtendedAbstraction(implementation);
ClientCode(*abstraction);
delete implementation;
delete abstraction;
return 0;
}
๐ฒ Client๋ Abstraction(์ถ์ํ)์ ํตํด์ ์ค์ ๊ตฌํ ๊ฐ์ฒด๋ค๊ณผ ์ํตํ๋ค.
๐ฒ Abstraction์ private ๋ฉค๋ฒ๋ก Implementation(๊ตฌํ ์ธํฐํ์ด์ค)๋ฅผ ๊ฐ์ง๋ค.
๐ฒ ExtendedAbstraction์ Abstraction์ ์์์ ๋ฐ์ ํด๋์ค๋ก Abstraction๊ณผ ๋์ผํ๊ฒ Implementation์ ํตํด ์ํตํ๋ค.
์คํ ๊ฒฐ๊ณผ
Abstraction: Base operation with:
ConcreteImplementationA: Here's the result on the platform A.
ExtendedAbstraction: Extended operation with:
ConcreteImplementationB: Here's the result on the platform B.
Composite Pattern(๋ณตํฉ์ฒด ํจํด)
๋ณตํฉ์ฒด ํจํด(Composite Pattern)์ ๋ณตํฉ ๊ฐ์ฒด(Composite)์ ๋จ์ผ ๊ฐ์ฒด(Leaf)๋ฅผ ๋์ผํ ์ปดํฌ๋ํธ๋ก ์ทจ๊ธํ๊ณ , ๋จ์ผ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋๋ก ํ๋ ๊ตฌ์กฐ ํจํด์ด๋ค.
์๋ฅผ ๋ค์ด, ์์ ๊ฐ์ด ๋ณต์กํ ์ฃผ๋ฌธ์ด ๋ค์ด ์๋ค๊ณ ํ์. ์ด ๊ฐ๊ฒฉ์ ๊ณ์ฐํ๊ธฐ ์ํด ์ผ์ผ์ด ์ ํ ํ๋ํ๋ ๋ง๋ค ๋ํ๊ธฐ๋ฅผ ํด์ค ์๋ ์๋ค. ํ์ง๋ง ์ด๋ฌํ ๋ฐฉ์์ ๋๋ฌด๋๋ ๋นํจ์จ์ ์ด๋ค.
๋ฐ๋ผ์ ๋ณตํฉ์ฒด ํจํด์ ์ฌ๊ท์ ์ผ๋ก ์ ๋ฌด๋ฅผ ์์ํ์ฌ ์ํํ๋ ๋ฐฉ๋ฒ์ ์ ์ํ๋ค. ์ด๋ ์๊ณ ๋ฆฌ์ฆ์ DFS์ ๊ต์ฅํ ์ ์ฌํ๊ฒ ๋์ํ๋ค. DFS๋ ๊ฒฐ๊ตญ ์ฌ๊ท์ ์ผ๋ก ํ๊ณ ๋ค์ด ์ผ๋ จ์ ์ ๋ฌด๋ฅผ ์ํํ๋ ํ์ ๊ธฐ๋ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
๋ณตํฉ์ฒด ํจํด์ ์ด๊ฐ๊ฒฉ์ ๊ณ์ฐํ๋ ๋ฉ์๋๋ฅผ ๊ณตํต ์ธํฐํ์ด์ค๋ฅผ ํตํด์ ์ ํ๋ค๊ณผ ์์๋ค์๊ฒ ๋ถ์ฌํ ์ ์๋ค.
Composite Pattern(๋ณตํฉ์ฒด ํจํด)์ ๊ตฌ์กฐ
๐ฒ Component : Leaf์ Composite๋ฅผ ๋ฌถ๋ ๊ณตํต ์์ ์ธํฐํ์ด์ค์ด๋ค.
๐ฒ Composite : ๋ณตํฉ ๊ฐ์ฒด๋ก, Leaf๋ Composite๋ฅผ ๋ณด๊ดํ๋ ์ญํ ์ ํ๋ค.
- ๋ณด๊ด์ ๋ด๋ถ ๋ฆฌ์คํธ๋ฅผ ํตํด์ ๊ด๋ฆฌํ๋ค.
- add์ remove ๋ฉ์๋๋ฅผ ํตํด์ ๋ด๋ถ ๋ฆฌ์คํธ์ ๋จ์ผ/๋ณตํฉ ๊ฐ์ฒด๋ฅผ ์ถ๊ฐํ๊ณ ์ญ์ ํ๋ค.
- excute()๋ฅผ ํตํด์ ํ์ ๋ณตํฉ ๊ฐ์ฒด๋ฅผ ์ํํ๋ค.
๐ฒ Leaf : ๋จ์ผ ๊ฐ์ฒด์ด๋ค. excute()๋ฅผ ์ํํ๋ฉด, ๋ด์ฉ๋ฌผ๋ง ๋ฐํํ๋ค.
๐ฒ Client : Component๋ฅผ ํตํด์ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ ์ ์๋ค.
Composite Pattern(๋ณตํฉ์ฒด ํจํด)๋ฅผ C++๋ก
Component
class Company {
public:
void Hire(Employee* employee) {
employees_.push_back(employee);
}
std::string GetInfo() {
std::string res = "";
for(Employee* employee : employees_) {
res += employee -> GetInfo() + "\n";
}
return res;
}
private:
std::vector<Employee*> employees_;
};
๐ฒ GetInfo()๋ excute()๋ก, ์ฌ๊ท์ ์ผ๋ก ์ด๋ฅผ ํธ์ถํ๋ค.
๐ฒ Hire()๋ ๋ด๋ถ ๋ฆฌ์คํธ๋ก, ๋จ์ผ/๋ณตํฉ ๊ฐ์ฒด๋ฅผ ์ถ๊ฐํ๋ ๊ธฐ๋ฅ์ ํ๋ค.
Leaf
class Employee {
public:
Employee(std::string name, int age, std::string dept) : name_(name),
age_(age), dept_(dept) {}
virtual std::string GetInfo() {
return "Employee: " + name_ + "(" + std::to_string(age_) + ") @ " + dept_;
}
virtual ~Employee() {}
protected:
std::string name_;
int age_;
std::string dept_;
};
class Developer : public Employee {
public:
Developer(std::string name, int age, std::string dept) : Employee(name, age, dept) {}
std::string GetInfo() {
return "Developer: " + name_ + "(" + std::to_string(age_) + ") @ " + dept_;
}
};
class Researcher : public Employee {
public:
Researcher(std::string name, int age, std::string dept) : Employee(name, age, dept) {}
std::string GetInfo() {
return "Researcher: " + name_ + "(" + std::to_string(age_) + ") @ " + dept_;
}
};
class Leader : public Employee {
public:
Leader(std::string name, int age, std::string dept) : Employee(name, age, dept) {}
std::string GetInfo() {
return "Leader: " + name_ + "(" + std::to_string(age_) + ") @ " + dept_;
}
};
๐ฒ ์ด ์์ ์ ๊ฒฝ์ฐ, Composite์ ์ญํ ์ ํ๋ ๋ถ๋ถ์ Company ๋ฐ์ ์๋ค. ์ฆ, Company๋ Composite์ด์, Component์ด๋ค.
๐ฒ ๋๋จธ์ง ๋ถ๋ถ๋ค์ ์ ๋ถ, Leaf ๋ถ๋ถ์ผ๋ก GetInfo()๋ฅผ ํตํด ๊ทธ ๋ด์ฉ๋ฌผ ๋ง์ ๋ด๋๋๋ค. ์ด๋ virtual์ ํตํ ๋ฉ์๋ ์ค๋ฒ๋ผ์ด๋ฉ์ ํตํด ์ํ๋๋ค.
Facade Pattern(ํผ์ฌ๋ ํจํด)
ํผ์ฌ๋(Facade) ํจํด์ ์ฌ์ฉํ๊ณ ์ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ธ๋ถ API๋ฅผ ๋ด ์ฝ๋์ ๊ฒฐํฉํ๊ณ ์ ํ ๋, ๋น์ฆ๋์ค ๋ก์ง์ ์ดํดํ๊ธฐ ์ฝ๋๋ก ํด๋์ค๋ฅผ ์ฌ์ ๋ฆฌํ๋ ๊ตฌ์กฐํจํด์ด๋ค.
๋ํ ํผ์ฌ๋ ํจํด์ ๋ค๋ฅธ ๋์์ธ ํจํด๊ณผ ๋ฌ๋ฆฌ ์ ํํ๋์ด ์์ง ์์ ํจํด์ด๋ค. ๊ทธ๋์ ํด๋์ค๋ค๊ฐ์ ๊ด๊ณ๊ฐ ํน๋ณํ ์ ํด์ ธ ์๊ฑฐ๋ ํ์ง๋ ์๋ค. ๊ทธ์ ํผ์ฌ๋(Facade) ํด๋์ค๋ฅผ ํตํด์ ๊ธฐ๋ฅ์ด ์ง์ฝํ๋๊ธฐ๋ง ํ๋ฉด ๋๋ค. ๋ณต์กํ ๊ฒ์ ๊ฐ๋จํ๊ฒ ๋ณด์ฌ์ค๋ค๋ ๊ฒ์ด ํผ์ฌ๋ ํจํด์ ๋ชฉ์ ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
ํผ์ฌ๋ ํจํด์ ํน์ง
1๏ธโฃ ์์คํ ์ด ๋๋ฌด ๋ณต์กํ ๋ ์ฌ์ฉํ๋ค.
2๏ธโฃ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฒฐํฉ๋๊ฐ ๋๋ฌด ๋์ ๋ ์ฌ์ฉํ๋ค.
3๏ธโฃ ๋ณต์กํ ์ฝ๋๋ฅผ ๊ฐ์ถ๊ณ , Facade ํด๋์ค๋ง์ ํตํด ์ฝ๋๋ฅผ ์ดํดํ ์ ์๋ค.
4๏ธโฃ ์ฝ๋์ ์์ด ๋ง์์ ธ, ์ ์ง๋ณด์ ๋ฉด์์ ๋น์ฉ์ด ๋ ๋ ๋ค.
Facade Pattern(ํผ์ฌ๋ ํจํด)์ ๊ตฌ์กฐ
๐ฒ VideoConverter๋ Facade ํด๋์ค๋ก์จ, ๋ณต์กํ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ ๋ฆฌํ์ฌ ๋ํ๋ธ๋ค.
๐ฒ Application์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํ ์์กด ์์ด Facade๋ฅผ ํตํด์ ์์ ์ ์ํํ๋ค.
Facade Pattern(ํผ์ฌ๋ ํจํด)์ C++๋ก
#include <algorithm>
#include <iostream>
#include <sstream>
#include <vector>
class Subsystem1 {
public:
std::string Operation1() const { return "Subsystem1: Ready!\n"; }
// ...
std::string OperationN() const { return "Subsystem1: Go!\n"; }
};
class Subsystem2 {
public:
std::string Operation1() const { return "Subsystem2: Get ready!\n"; }
// ...
std::string OperationZ() const { return "Subsystem2: Fire!\n"; }
};
class Facade {
protected:
Subsystem1 *subsystem1_;
Subsystem2 *subsystem2_;
public:
Facade(Subsystem1 *subsystem1 = nullptr, Subsystem2 *subsystem2 = nullptr) {
this->subsystem1_ = subsystem1 ?: new Subsystem1;
this->subsystem2_ = subsystem2 ?: new Subsystem2;
}
~Facade() {
delete subsystem1_;
delete subsystem2_;
}
std::string Operation() {
std::string result = "Facade initializes subsystems:\n";
result += this->subsystem1_->Operation1();
result += this->subsystem2_->Operation1();
result += "Facade orders subsystems to perform the action:\n";
result += this->subsystem1_->OperationN();
result += this->subsystem2_->OperationZ();
return result;
}
};
void ClientCode(Facade *facade) {
// ...
std::cout << facade->Operation();
// ...
}
int main() {
Subsystem1 *subsystem1 = new Subsystem1;
Subsystem2 *subsystem2 = new Subsystem2;
Facade *facade = new Facade(subsystem1, subsystem2);
ClientCode(facade);
delete facade;
return 0;
}
๐ฒ Facade ํด๋์ค๋ ๋ SubSystem(์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ผ๊ณ ์๊ฐํ์)์์ ์ฌ์ฉํ๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋์์ ๊ธฐ์ ํ๋ค.
๐ฒ Client๋ subsystem์ Facade ๊ฐ์ฒด์ ๋ฑ๋ก์ํค๊ณ , ์คํ๋ง ํ๋ค.(๋๋จธ์ง ์ธ๋ถ ๋ก์ง์ Facade ๋ด๋ถ์์ ์คํ๋๋ค.
Facade Pattern(ํผ์ฌ๋ ํจํด)์ Java์์
๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๊ณ ์ถ๋ ฅํ๋๋ฐ ์บ์ ์ ๋ณด๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํด๋ณด์. ๊ทธ๋ ๋ค๋ฉด ์๋์ ๊ฐ์ ๋ก์ง์ผ๋ก ๋ฐ์ดํฐ๊ฐ ์กฐํ๋๋ค.
์กฐํํ ๋ฐ์ดํฐ ์ ๋ณด ๋ณ์ a;
if (๋ฐ์ดํฐ๊ฐ ์บ์์ ์๋ค๋ฉด) {
a = ์บ์์์ ์กฐํ ๋ฐ ๋ฐํ;
} else {
a = DB์์ ๋ฐ์ดํฐ ์กฐํ ๋ฐ ๋ฐํ;
a๋ฅผ ์บ์์ ์ ์ฅ
}
a๋ฅผ ๊ฐ๊ณตํ์ฌ ์ถ๋ ฅ
์ด ๊ณผ์ ์์ ์ฌ์ฉํด์ผ ํ๋ ํด๋์ค๋ Cache ์กฐํ, DBMS ์กฐํ, Cache ์ ๋ ฅ, ์กฐํ ๊ฒฐ๊ณผ ๊ฐ๊ณต, ๊ฐ๊ณต ๊ฒฐ๊ณผ ์ถ๋ ฅ์ด๋ค.
์ด์ ๋ํ ํด๋์ค๋ฅผ ๊ฐ๋จํ๊ฒ ๋ํ๋ด๋ฉด ์๋์ ๊ฐ์ ๊ฒ์ด๋ค.
class Row {
private String name;
private String birthday;
private String email;
public Row(String name, String birthday, String email) {
this.name = name;
this.birthday = birthday;
this.email = email;
}
public String getName() {
return name;
}
public String getBirthday() {
return birthday;
}
public String getEmail() {
return email;
}
}
class DBMS {
private HashMap<String, Row> db = new HashMap<>();
public void put(String name, Row row) {
db.put(name, row);
}
public Row query(String name) {
try {
Thread.sleep(500);
} catch(InterruptedException e) {}
return db.get(name.toLowerCase());
}
}
class Cache {
private HashMap<String, Row> cache = new HashMap<>();
public void put(Row row) {
cache.put(row.getName(), row);
}
public Row get(String name) {
return cache.get(name);
}
}
class Message {
private Row row;
public Message(Row row) {
this.row = row;
}
public String makeName() {
return "Name : \"" + row.getName() + "\"";
}
public String makeBirthday() {
return "Birthday : " + row.getBirthday();
}
public String makeEmail() {
return "Email : " + row.getEmail();
}
}
์ ํด๋์ค ์ฝ๋๋ฅผ main ํจ์์ ํ๋ํ๋ ์ ์ฉํด๋๊ฐ๋ฉฐ ๋ก์ง์ ๊ตฌํํ๋ค๋ฉด ์ด๋ ํด๋ฆฐํ์ง ๋ชปํ ๊ฒ์ด๋ค. ์ ์ง ๋ณด์ํ๊ธฐ ํ๋ค๋ฉฐ ์ฝ๋ ๋ก์ง์ ํด์ํ๊ธฐ๋ ํ๋ค์ด์ง๊ธฐ ๋๋ฌธ์ด๋ค.
์ด์ ๋ฐ๋ผ Facade ํด๋์ค๋ฅผ ๋์ ํ์ฌ "๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๊ณ ์ถ๋ ฅํ๋๋ฐ ์บ์ ์ ๋ณด๋ฅผ ์ฌ์ฉํ๋" ๋ก์ง์ ๋์ ์ํํ๋๋ก ํ๋ค๋ฉด ์ ์ง๋ณด์์ ์ฝ๋ ํด์์ ์์ด ๋งค์ฐ ์ ๋ฆฌํด ์ง ์ ์๋ค.
class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.insert();
// ์บ์ ํ์ฉ DB ์กฐํ ๊ธฐ๋ฅ์ ํ๋ Facade์ run() ๋ฉ์๋
String name = "ํ๊ธธ๋";
facade.run(name);
}
}
Froxy Pattern(ํ๋ก์ ํจํด)
ํ๋ก์ ํจํด์ ์๊ธด ๋ชจ์์ผ๋ก๋ ํผ์ฌ๋ ํจํด๊ณผ ํฐ ์ฐจ์ด๊ฐ ์๋ค. ๋จ, dependency ๊ฐ์๊ฐ ๋ชฉ์ ์ด์๋ Facade์๋ ๋ฌ๋ฆฌ Proxy๋ ์ฑ๋ฅ ํฅ์ ๋ฐ ์ธ๊ฐ๊ฐ ์ฃผ ๋ชฉ์ ์ด๋ค.
์ฆ, ํ๋ก์ ํจํด์ด๋ ์๋ณธ ๊ฐ์ฒด ๋๋ฆฌ๋ก ๋ก์ง์ ์ฒ๋ฆฌํ๋ ํจํด์ธ๋ฐ, ์๋ณธ ๊ฐ์ฒด๋ฅผ ์์ ํ ์ ์๋ ์ํฉ์ผ ๋ ์ฌ์ฉํ๋ค. ์ด๋ฌํ ํ๋ก์ ํจํด์ผ๋ก ๋๋ฆด ์ ์๋ ํจ๊ณผ๋ ์๋์ ๊ฐ๋ค.
1๏ธโฃ ๋ณด์ : ํ๋ก์์์ ํด๋ผ์ด์ธํธ์ ๊ถํ์ ํ์ธํ๊ณ ์๋ณต ๊ฐ์ฒด๋ก์ ์์ฒญ์ ํ ์ ์๋ ์ง ํ์ธํ๋ ์ญํ
2๏ธโฃ ์บ์ฑ : ํ๋ก์๊ฐ ๋ด๋ถ ์บ์๋ฅผ ์ ์งํ์ฌ, ๋ฐ์ดํฐ์ ๋ํ ์บ์๋ฅผ ์ด๋ฏธ ๋ณด์ ํ๊ณ ์์ ๋ ๊ทธ๋๋ก ๋ฐํํ๋ ์ญํ
3๏ธโฃ ๋ฐ์ดํฐ ์ ํจ์ฑ ๊ฒ์ฌ : ์ ๋ ฅ์ ๋ํ ์ ํจ์ฑ ๊ฒ์ฌ ๊ธฐ๋ฅ
4๏ธโฃ ์ง์ฐ ์ด๊ธฐํ : ๋ง์ฝ ๋์ ๊ฐ์ฒด๊ฐ ์์ฑํ ๋ ๋น์ฉ์ด ๋ง์ด ๋ ๋ค๋ฉด, ํ์๋ก ํ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ์ฌ์ฉ ์๊ธฐ์ ์์ฑํ๋ ์ญํ
5๏ธโฃ ๋ก๊น : ์๋ณธ ๊ฐ์ฒด์ ๋ํ ํธ์ถ ์ ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๋ ์ญํ
6๏ธโฃ ์๊ฒฉ ๊ฐ์ฒด : ํ๋ก์๊ฐ ์๊ฒฉ์ ์๋ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์์ ๋ก์ปฌ์ฒ๋ผ ๋ณด์ด๋๋ก ํ๋ ์ญํ
Froxy Pattern(ํ๋ก์ ํจํด)์ ๊ตฌ์กฐ
๐ฒ ์ฌ์ฉ์๋ ServiceInterface๋ฅผ ํตํด์ ๋์ ๊ฐ์ฒด(Service)์ ๋ํ ์์ ์ ์ํํ ์ ์๋ค.
๐ฒ Proxy๋ ๋์ ๊ฐ์ฒด(Service)๋ฅผ ํฉ์ฑํ๋ค.
๐ฒ Service๋ ์๋ณธ ๋์ ๊ฐ์ฒด๋ฅผ ์๋ฏธํ๋ค.
Froxy Pattern(ํ๋ก์ ํจํด)์ C++๋ก
๋ณด์๊ณผ ์บ์ฑ์ ๊ธฐ๋ฅ์ ํ๋ ํ๋ก์ ํจํด์ ๊ฐ๋จํ๊ฒ C++๋ก ๊ตฌํํด๋ณด๊ฒ ๋ค.
์ค๋นํ ํด๋์ค(์บ์ฑ ํด๋์ค, Person, Result ํด๋์ค)
class Result {
public:
Result() { /* ์์ฑ์ ๊ตฌํ */
}
// ๋ค๋ฅธ ๋ฉค๋ฒ ๋ฐ ๋์์ ์ถ๊ฐ๋ก ์ ์ํ ์ ์์ต๋๋ค.
};
class Person {
public:
Person(std::string name) : name_(name) { }/* ์์ฑ์ ๊ตฌํ */
std::string name() const {
return name_;
}
private:
std::string name_;
};
class Cache {
public:
Cache() { /* ์์ฑ์ ๊ตฌํ */
}
bool IsCached(std::string query) {
// ์บ์ ํ์ธ ๋ก์ง ๊ตฌํ
return false;
}
Result GetCachedData(std::string query) {
// ์บ์๋ ๋ฐ์ดํฐ ๋ฐํ ๋ก์ง ๊ตฌํ
return Result();
}
void Update(std::string query, std::experimental::optional<Result> result) {
std::cout << "update cache for person" << std::endl;
// ์บ์ ์
๋ฐ์ดํธ ๋ก์ง ๊ตฌํ
}
};
Service Interface, Service, Proxy
class QueryInterface {
public:
virtual std::experimental::optional<Result> Query(Person accessor, std::string query) = 0;
};
class NetworkAdapter : public QueryInterface {
public:
std::experimental::optional<Result> Query(Person accessor, std::string query) override {
// ๋คํธ์ํฌ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ก์ง ๊ตฌํ
std::cout << "data fetch in NetworkAdapter." << std::endl;
return Result();
}
};
class NetworkProxy : public QueryInterface {
public:
NetworkProxy(Person manager) : network_manager_(manager) {}
std::experimental::optional<Result> Query(Person accessor, std::string query) override {
// ๋ค์ด์จ ๊ฐ์ ๋ํ ์ธ๊ฐ ๊ณผ์
if (network_manager_.name() == accessor.name()) {
// ์บ์ฌ๊ฐ ์๋ค๋ฉด, ๊ทธ๋๋ก ์ค
if (cache_.IsCached(query)) {
return cache_.GetCachedData(query);
// ์บ์ฌ๊ฐ ์๋ค๋ฉด, network_adapter๋ก ๋ถํฐ ๊ฐ์ ธ์ด
} else {
std::experimental::optional<Result> result = network_adapter_.Query(accessor, query); // Query ํจ์์ ์๊ทธ๋์ฒ ๋ณ๊ฒฝ
cache_.Update(query, result);
return result;
}
}
// ์์ ์์ผ๋ฉด null ๊ฐ ๋ฆฌํด
return std::experimental::nullopt;
}
private:
const Person network_manager_;
Cache cache_;
NetworkAdapter network_adapter_;
};
๐ฒ QueryInterface : Service Interface๋ก ํ์ ์์์ผ๋ก Proxy์ Service๋ฅผ ๋๋ค.
๐ฒ NetworkAdapter : Service๋ก ์ค์ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๋ ํด๋์ค์ด๋ค.
๐ฒ NetworkProxy : ์บ์ฑ ๊ธฐ๋ฅ๊ณผ ๋ณด์ ๊ธฐ๋ฅ์ ์ํํ๋ค. NetworkAdapter๋ฅผ ํฉ์ฑํ๋ค.
main ํจ์
int main() {
Person manager("person1"); // Person ๊ฐ์ฒด ์์ฑ
NetworkProxy proxy(manager); // NetworkProxy ๊ฐ์ฒด ์์ฑ
std::experimental::optional<Result> result1 =
proxy.Query(manager, "find name from internet");
std::experimental::optional<Result> result2 =
proxy.Query(manager, "find name from internet");
}
์คํ ๊ฒฐ๊ณผ
data fetch in NetworkAdapter.
update cache for person
data fetch in NetworkAdapter.
update cache for person
์๋ฐ์์๋ Dynamic Proxy, Spring Framework์์๋ Spring AOP ๋ฑ Proxy๋ ์ ๋ง ๋ง์ ๊ณณ์์ ์ฐ์ด๊ณ ์๋ค. ์ด์ ๊ด๋ จ๋ ๋ถ๋ถ์ ํ์ ํฌ์คํ ์์ ์ด๋ค.
References
๋์์ธ ํจํด๋ค
refactoring.guru
[Java][๋์์ธ ํจํด] 8. ๋ธ๋ฆฌ์ง ํจํด (Bridge Pattern)
๋์์ธํจํด [Java][๋์์ธ ํจํด] 8. ๋ธ๋ฆฌ์ง ํจํด ๋ธ๋ฆฌ์ง ํจํด์ ๊ฐ์ฒด์ ํ์ฅ์ฑ์ ํฅ์ํ๊ธฐ ์ํ ํจํด์ผ๋ก, ๊ฐ์ฒด์์ ๋์์ ์ฒ๋ฆฌํ๋ ๊ตฌํ๋ถ์ ํ์ฅ์ ์ํ ์ถ์๋ถ๋ฅผ ๋ถ๋ฆฌํ๋ค. ๋ธ๋ฆฌ์ง ํจํด์ด๋?
hirlawldo.tistory.com
๐ ๋ณตํฉ์ฒด(Composite) ํจํด - ์๋ฒฝ ๋ง์คํฐํ๊ธฐ
Composite Pattern ๋ณตํฉ์ฒด ํจํด(Composite Pattern)์ ๋ณตํฉ ๊ฐ์ฒด(Composite) ์ ๋จ์ผ ๊ฐ์ฒด(Leaf)๋ฅผ ๋์ผํ ์ปดํฌ๋ํธ๋ก ์ทจ๊ธํ์ฌ, ํด๋ผ์ด์ธํธ์๊ฒ ์ด ๋์ ๊ตฌ๋ถํ์ง ์๊ณ ๋์ผํ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋๋ก ํ๋
inpa.tistory.com
์ฝ๋ฉ์ผ๋ก ํ์ตํ๋ GoF์ ๋์์ธ ํจํด - ์ธํ๋ฐ | ๊ฐ์
๋์์ธ ํจํด์ ์๊ณ ์๋ค๋ฉด ์คํ๋ง ๋ฟ ์๋๋ผ ์ฌ๋ฌ ๋ค์ํ ๊ธฐ์ ๋ฐ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ ๋ณด๋ค ์ฝ๊ฒ ํ์ตํ ์ ์์ต๋๋ค. ๋ํ, ๋ณด๋ค ์ ์ฐํ๊ณ ์ฌ์ฌ์ฉ์ฑ์ด ๋ฐ์ด๋ ๊ฐ์ฒด ์งํฅ ์ํํธ์จ์ด๋ฅผ ๊ฐ๋ฐํ
www.inflearn.com
๐ ํผ์ฌ๋(Facade) ํจํด - ์๋ฒฝ ๋ง์คํฐํ๊ธฐ
Facade Pattern ํผ์ฌ๋ ํจํด(Facade Pattern)์ ์ฌ์ฉํ๊ธฐ ๋ณต์กํ ํด๋์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํด ์ฌ์ฉํ๊ธฐ ํธํ๊ฒ ๊ฐํธํ ์ธํฐํ์ด์ค(API)๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํ ๊ตฌ์กฐ ํจํด ์ด๋ค. ์๋ฅผ๋ค์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฐ ํด๋์ค
inpa.tistory.com
๐ ์ด๋ํฐ(Adaptor) ํจํด - ์๋ฒฝ ๋ง์คํฐํ๊ธฐ
Adaptor Pattern ์ด๋ํฐ ํจํด(Adaptor Pattern) ์ด๋ ์ด๋ฆ ๊ทธ๋๋ก ํด๋์ค๋ฅผ ์ด๋ํฐ๋ก์ ์ฌ์ฉ๋๋ ๊ตฌ์กฐ ํจํด์ด๋ค. ์ด๋ํฐ๋ ์ฐ๋ฆฌ ์ฃผ๋ณ์๋ ๋ง์ด ๋ณผ ์ ์๋ ๊ฒ์ผ๋ก์, ๋ํ์ ์ผ๋ก 110V ์ ์ฉ ๊ฐ์ ์ ํ์ 220V
inpa.tistory.com
๐ ํ๋ก์(Proxy) ํจํด - ์๋ฒฝ ๋ง์คํฐํ๊ธฐ
Proxy Pattern ํ๋ก์ ํจํด(Proxy Pattern)์ ๋์ ์๋ณธ ๊ฐ์ฒด๋ฅผ ๋๋ฆฌํ์ฌ ๋์ ์ฒ๋ฆฌํ๊ฒ ํจ์ผ๋ก์จ ๋ก์ง์ ํ๋ฆ์ ์ ์ดํ๋ ํ๋ ํจํด์ด๋ค. ํ๋ก์(Proxy)์ ์ฌ์ ์ ์ธ ์๋ฏธ๋ '๋๋ฆฌ์ธ'์ด๋ผ๋ ๋ป์ด๋ค. ์ฆ, ๋
inpa.tistory.com
๐ ์ถ์ ํฉํ ๋ฆฌ(Abstract Factory) ํจํด - ์๋ฒฝ ๋ง์คํฐํ๊ธฐ
Abstract Factory Pattern ์ถ์ ํฉํ ๋ฆฌ ํจํด์ ์ฐ๊ด์ฑ์ด ์๋ ๊ฐ์ฒด ๊ตฐ์ด ์ฌ๋ฌ๊ฐ ์์ ๊ฒฝ์ฐ ์ด๋ค์ ๋ฌถ์ด ์ถ์ํํ๊ณ , ์ด๋ค ๊ตฌ์ฒด์ ์ธ ์ํฉ์ด ์ฃผ์ด์ง๋ฉด ํฉํ ๋ฆฌ ๊ฐ์ฒด์์ ์งํฉ์ผ๋ก ๋ฌถ์ ๊ฐ์ฒด ๊ตฐ์ ๊ตฌํํ
inpa.tistory.com