Design Pattern
GoF์ ๋์์ธ ํจํด
Gang of Four
Erich Gamma
,Richard Helm
,Ralph Johnson
,John Vlissides
๋ผ๋ ๋ค๋ช ์ ์ ์๋ฅผ ๋ปํจ
์ํํธ์จ์ด ๋์์ธ์์ ์์ฃผ ๋ฐ์ํ๋ ๋ฌธ์ ๋ค์ ๋ํ ํด๊ฒฐ์ฑ ์ ์ ๊ณตํ๋ 23๊ฐ์ง ๋์์ธ ํจํด์ ์กฐํฉ
์์ฑ ํจํด(Creational Patterns)
๊ฐ์ฒด์ ์์ฑ๊ณผ ์ด๊ธฐํ์ ๊ด๋ จ๋ ํจํด
๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐฉ์์ ์ถ์ํ
์ฃผ์ ํจํด:
Singleton
,Factory Method
,Abstract Factory
,Builder
,Prototype
๊ตฌ์กฐ ํจํด(Structural Patterns)
ํด๋์ค๋ ๊ฐ์ฒด๋ฅผ ํฉ์ฑํ์ฌ ๋ ํฐ ๊ตฌ์กฐ๋ก ๋ง๋๋ ํจํด
ํด๋์ค์ ๊ฐ์ฒด๋ฅผ ์กฐํฉํ์ฌ ๋ํฐ ๊ตฌ์กฐ๋ก ๋ง๋ฆ
์ฃผ์ ํจํด:
Adapter
,Bridge
,Composite
,Decorator
,Facade
,Flyweight
,Proxy
ํ๋ ํจํด(Behavioral Paterrns)
๊ฐ์ฒด ๊ฐ์ ํต์ ๊ณผ ์ฑ ์์ ๋ถ์ฐํ๋ ํจํด
์๊ณ ๋ฆฌ์ฆ๊ณผ ๊ฐ์ฒด ๊ฐ์ ์ฑ ์์ ๋ถ๋ฆฌ
์ฃผ์ ํจํด:
Chain of Responsibility
,Command
,Interpreter
,Iterator
,Mediator
,Memento
,Observer
,State
,Strategy
,Template Method
,Visitor
์์ฑ ํจํด
ํฉํ ๋ฆฌ ํจํด
๊ฐ์ฒด ์์ฑ์ ์บก์ํํ๋ ๋์์ธ ํจํด
๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ์ฝ๋๋ฅผ ํด๋ผ์ด์ธํธ ์ฝ๋๋ก๋ถํฐ ๋ถ๋ฆฌํ์ฌ ์ ์ฐ์ฑ์ ์ ๊ณต
๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ณผ์ ์ ์๋ธํด๋์ค์์ ์ฒ๋ฆฌํ๋๋ก ํ๋ ๊ฒ์ด ํน์ง
๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ณ๋ ๋๊ตฌ๋ฅผ ์ ๊ณต
// ๋ํ ์ธํฐํ์ด์ค
interface Shape {
void draw()
}
// ๊ตฌ์ฒด์ ์ธ ๋ํ ํด๋์ค - ์
class Circle implements Shpae {
@Override
public void draw() {
}
}
// ๊ตฌ์ฒด์ ์ธ ๋ํ ํด๋์ค - ์ ์ฌ๊ฐํ
class Square implements Shpae {
@Override
public void draw() {
}
}
// ํฉํ ๋ฆฌ ์ธํฐํ์ด์ค
interface ShapeFactory {
Shape createShape();
}
// ์์ ์์ฑํ๋ ํฉํ ๋ฆฌ
class CircleFactory implements ShapeFactory {
@Override
public Shape createShape() {
return new Circle();
}
}
// ์ ์ฌ๊ฐํ์ ์์ฑํ๋ ํฉํ ๋ฆฌ
class SquareFactory implements ShapeFactory {
@Override
public Shape createShape() {
return new Square();
}
}
// ํด๋ผ์ด์ธํธ ์ฝ๋
public class FactoryPatternExample {
public state void main(String[] args) {
// ์์ ์์ฑํ๋ ํฉํ ๋ฆฌ๋ฅผ ์ด์ฉํด ๋ํ ์์ฑ
ShapeFactory circleFactory = new CircleFactory();
Shape circle = circleFactory.createShape();
circle.draw();
// ์ ์ฌ๊ฐํ์ ์์ฑํ๋ ํฉํ ๋ฆฌ๋ฅผ ์ด์ฉํด ๋ํ ์์ฑ
ShapeFactory squareFactory = new SquareFactory();
Shape square = squareFactory.createShape();
square.draw();
}
}
์ฑ๊ธํค ํจํด
ํ๋์ ์ธ์คํด์ค๋ง์ ๊ฐ๋๋ก ๋ณด์ฅ
public class Singleton {
private static Singleton intstance;
// ์ธ๋ถ์์ ์์ฑํ ์ ์๋๋ก ์์ฑ์ private
private Singleton() {}
// ์ค์ง ์์ฑ์๋ getInstance()๋ฅผ ํตํด ๊ฐ์ ธ๊ฐ ์ ์๋๋ก ๋ฉ์๋ ์ ๊ณต
public static Singleton getInstance() {
if (instace == null) {
instance = new Singleton();
}
return instacne;
}
}
ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด
๊ฐ์ฒด ์์ฑ์ ์บก์ํ
๊ฐ์ฒด ์์ฑ์ ์๋ธ ํด๋์ค์์ ๊ฒฐ์ ํ๋๋ก ํ๋ ๊ฒ
interface Product {
void create();
}
class ConcreteProduct implements Product {
@Override
public void create() {
}
}
abstract class Creator {
public abstract Product factoryMethod();
}
class ConcreteCreator extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProduct();
}
}
๋น๋ ํจํด(Builder Pattern)
๋ณต์กํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋๋ฐ ์ฌ์ฉ๋๋ ํจํด
๊ฐ์ฒด ์์ฑ์ ๋จ๊ณ๋ฅผ ๋ถ๋ฆฌํ์ฌ ๋ณต์ก์ฑ์ ํด๊ฒฐ
๊ฐ์ฒด์ ์์ฑ ๊ณผ์ ์ ๋ค์ํ ๋ฐฉ์์ผ๋ก ์กฐํฉ
class Product {
private String part1;
private String part2;
public void setPart1(String part1) {
this.part1 = part1;
}
public void setPart2(String part1) {
this.part2 = part2;
}
@Override
public String toString() {
return "Product [part1=" + part1 + ", part2=" +part2 + "]";
}
}
// ๋น๋ ์ธํฐํ์ด์ค
interface Builder {
void buildPart1(String part1);
void buildPart2(String part2);
Product getResult();
}
// ๊ตฌ์ฒด์ ์ธ ๋น๋ ํด๋์ค
class ConcreteBuilder implements Builder {
private Product product = new Product();
@Override
public void buildPart1(String part1) {
product.setPart1(part1);
}
@Override
public void buildPart2(String part2) {
product.setPart2(part2);
}
@Override
public Product getResult() {
return project
}
}
// ์์๋ฅผ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ ๋ต ์ํ๋ฅผ ๋ณ๊ฒฝ ex
// ๋๋ ํฐ ํด๋์ค (์์ฑ ์์๋ฅผ ์ ์)
class Director {
public Product construct(Builder builder) {
builder.buildPart1("Part1");
builder.buildPart2("Part2");
return builder.getResult();
}
}
// ํด๋ผ์ด์ธํธ ์ฝ๋'
public class BuilderPatternExample {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director();
Product product = director.construct(builder);
}
}
๊ตฌ์กฐ ํจํด
Facade ํจํด
์ฌ๋ฌ ๊ฐ์ ์๋ธ์์คํ ์ด๋ ๋ณต์กํ ์ธํฐํ์ด์ค๋ฅผ ๋จ์ํ
ํด๋ผ์ด์ธํธ์๊ฒ ๋ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ ํจํด
๋ณต์กํ ์์คํ ์ ๋จ์ํ ์ธํฐํ์ด์ค๋ก ๋ํ
์ฌ๋ฌ ์๋ธ์์คํ ์ ์กฐํฉํด์ ๋ญ๊ฐ ๋์์ ๋ง๋ค๊ธฐ์ ๋ณต์กํด์ง๋ค. ์ด๋ด ๋ Facade ํจํด์ ์ฌ์ฉ
๋ณต์กํ ์ฌ๋ฌ ์๋ธ์์คํ ์ ์ด์ฉํด์ ์คํผ๋ ์ด์ ์ ๋ง๋ค ๋ ํ์ฌ๋ ํจํด์ ์ด๋ค.
// Subsystem classes
class Subsystem1 {
public void operation1() {}
public void operation2() {}
}
class Subsystem2 {
public void operation1() {}
public void operation2() {}
}
// Facade class
class Facade {
private Subsystem1 subsystem1;
private Subsystem2 subsystem2;
private Subsystem3 subsystem3;
public Facade() {
this.subsystem1 = new SubSystem1();
this.subsystem2 = new SubSystem2();
this.subsystem3 = new SubSystem3();
}
// Methods that simplify complex operations
public void operationA() {
System.out.println('Facde Operation A");
subsystem1.operation1();
subsystem2.operation1();
subsystem3.operation1();
}
}
// Exmplae
public class FacadePatternExample {
public static void main(String[] args) {
Facade facade = new Facade();
// Use the Facade to simplify operations
facade.operationA();
facade.operationB();
}
}
Proxy ํจํด
๊ฐ์ฒด์ ์ ๊ทผ์ด๋ ์กฐ์์ ์ค๊ฐ์์ ์ ์ดํ๊ฑฐ๋ ๋ณด์กฐํ ๋ ์ฌ์ฉ
๊ฐ์ฒด์ ๋๋ฆฌ์๋ ๋๋ณ์ ์ญํ ์ ํ๋ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉ
์ค์ ๊ฐ์ฒด์ ๋ํ ์ ๊ทผ์ ์ค๊ฐ์์ ์ ์ดํ๊ฑฐ๋ ์ค๊ฐ์์ ๋ถ๊ฐ์ ์ธ ์์ ์ ์ํํ๋ ํจํด
์ค๊ฐ์ ๋๋ฆฌ์๊ฐ ๋ ํํ
์ค๊ฐ์์ ํ๋ ์ผ์ ์์ง๋ง ์ด๋ค ๋์์ ๋ํด์ ์์ ๋ฐ์ ๊ฐ์ฒด์ ์ ๋ฌ
๋ก๊น ๋ฐ ์๋ ์ธก์ , ์ ๊ทผ ์ ์ด ๋ฑ ๋ถ๊ฐ์ ์ธ ๋ณ๋ ๋์์ ํ ๋ ์ฌ์ฉ
interface Image {
void display();
}
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadImageFromDisk();
}
private void loadImageFromDisk() {}
@Override
public void display() {}
}
// ์ด๋ฏธ์ง์ ํ๋ก์ ํด๋์ค
// ์ค์ง์ ์ธ ๋์์ ๊ตฌํ๋์ง ์์
class ProxyImage implements Image {
private RealImage realImage;
private String filename;
public ProxyImage(String filename) {
this.filename = filename;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
// ํด๋ผ์ด์ธํธ ์ฝ๋
public class ProxyPatternExample {
public static void main(String[] args) {
// ํ๋ก์๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง ๋ก๋ฉ ๋ฐ ํ์
Image image = new ProxyImage("example.jpg");
// ์ด๋ฏธ์ง๊ฐ ์ฒ์์ผ๋ก ํ์๋ ๋ ์ค์ ์ด๋ฏธ์ง๊ฐ ๋ก๋ฉ๋๋ ๊ฒ์ ํ์ธํ ์ ์์
image.display();
// ์ด๋ฏธ์ง๊ฐ ์ด๋ฏธ ๋ก๋ฉ๋ ๊ฒฝ์ฐ์๋ ์ค์ ์ด๋ฏธ์ง๋ฅผ ๋ค์ ๋ก๋ฉํ์ง ์์
image.dispaly();
}
}
ํ๋ ํจํด
์ ๋ต ํจํด(Strategy Pattern)
์๊ณ ๋ฆฌ์ฆ์ด๋ ํ์๋ฅผ ์ ์ํ๊ณ , ๊ฐ๊ฐ์ ์บก์ํ
์๊ณ ๋ฆฌ์ฆ์ ๋ณ๊ฒฝ์ ๋ฐ๋ฅธ ์ํฅ์ ์ต์ํ
๋์ ์ผ๋ก ์๊ณ ๋ฆฌ์ฆ์ ์ ํ
์๊ณ ๋ฆฌ์ฆ์ด๋ ํ์(์ ๋ต)์ ์ฃผ์ ํ์ฌ ๊ต์ฒดํ๊ธฐ ์ฝ๊ฒ ๋ง๋๋ ๊ฒ
// ์ ๋ต ์ธํฐํ์ด์ค
interface SortingStrategy {
void sort(int[] array);
}
// ๊ตฌ์ฒด์ ์ธ ์ ๋ต ํด๋์ค - ๋ฒ๋ธ ์ ๋ ฌ
class BubbleSortStrategy implements SortingStrategy {
@Override
public void sort(int[] array) {
//์ค์ ๋ฒ๋ธ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ ๊ตฌํ
}
}
// ๊ตฌ์ฒด์ ์ธ ์ ๋ต ํด๋์ค - ํต ์ ๋ ฌ
class QuickSortStrategy implements SortingStrategy {
@Override
public void sort(int[] array) {
//์ค์ ํต ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ ๊ตฌํ
}
}
// ์ปจํ
์คํธ ํด๋์ค
class SortContext {
private SortingStrategy sortingStrategy;
public void setSortingStrategy(SortingStrategy sortingStrategy) {
this.sortingStrategy = sortingStrategy;
}
public void performSort(int[] array) {
sortingStrategy.sort(array);
}
}
// ํด๋ผ์ด์ธํธ ์ฝ๋
public class StrategyPatternExample {
public static void main(String[] args) {
int[] arrayToSort = {5, 2, 8, 1, 7};
SortContext sortContext = new SortContext();
// ์ฒซ ๋ฒ์งธ ์ ๋ ฌ: ๋ฒ๋ธ
SortContext.setSortingStrategy(new BubbleSortStrategy());
sortContext.performSort(arrayToSort);
// ๋ ๋ฒ์งธ ์ ๋ ฌ: ํต
SortContext.setSortingStrategy(new QuickSortStrategy());
sortContext.performSort(arrayToSort);
}
}
์ต์ ๋ฒ ํจํด
์ด๋ค ๊ฐ์ฒด์ ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋ ์ข ์ ๊ฐ์ฒด๋ค์ด ์๋์ผ๋ก ์๋ฆผ์ ๋ฐ๋๋ค.
๊ฐ์ฒด๋ค์๊ฒ ์๋ฆฌ๊ธฐ
// Observer interface
interface Observer {
void update(String message);
}
// ConcreteObserver class
class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " received message: " + message);
}
}
// Subject class
class Subject {
private List<Observer> observers = new ArrayList<>();
// Add an observer to the list
public void addObserver(Observer observer) {
observers.add(observer);
}
// Remove an observer from the list
public void removeObserver(Observer observer) {
observers.remove(observer);
}
// Notify all observers with a message
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
// Example usage
public class ObserverPatternExample {
public static void main(String[] args){
// Create subject
Subject subject = new Subject();
// Create observers
Observer observer1 = new ConcreteObserver("Observer 1");
Observer observer2 = new ConcreteObserver("Observer 2");
// Register observers with the subject
subject.notifyObservers("Hello Observers!");
// Unregister observer1
subject.removeObserver(observer1);
// Notify remaining observer with another message
subject.notifiyObservers("Observer 1 has been removed.");
}
}
Last updated