Design Pattern

임준철·2021년 4월 11일
0

SoftwareEnginerring

목록 보기
1/1

디자인 패턴 (Design Patterns)

  • 디자인 패턴이 어떤 것인지와 대표적으로 사용하는 패턴에 대한 사용법 정도만 정리했다.

디자인 패턴이란

  • 자주 발생하는 문제를 쉽게 해결하기 위해 제시된 재사용 가능한 해결책
    • Don't reinvent the Wheel (바퀴를 다시 발명하지 마라)
  • 이미 해결된 방식은 해결된 방식대로 해결하고, 새롭게 맞딱드린 문제를 해결하자
  • 소프트웨어 설계 문제를 쉽게 해결할 수 있도록 패턴화된 설계 방식
  • 팀원들과의 소통을 위해 디자인 패턴 학습이 필요하다.
    • 팀원들이 싱글톤 패턴으로 해결 해주세요 할 때 이 패턴에 대해서 알고 있어야 하겠지?

디자인 패턴의 구조

  • 문맥(Context)
    • 패턴이 적용될 수 있는 문제 상황을 기술
  • 문제(Problem)
    • 패턴이 적용되어 해결되어야 하는 여러 설계 이슈를 기술
  • 해결(Solution)
    • 문제를 해결하는 설계 구성 요소와 구성 요소 사이의 관계를 기술

디자인 패턴의 종류

  • Gang of four 패턴
    • 생성 패턴 (Creational patterns)
      • 객체의 생성 방식에 관련된 패턴
      • Abstract Factory, Factory Method, Singleton ...
    • 구조 패턴 (Structural patterns)
      • 클래스/객체를 조합한 구조를 가지는 패턴
      • Composite, Decorator ...
    • 동작 패턴 (Behavioral patterns)
      • 클래스/객체 사이의 동작 분배에 관련된 패턴
      • Observer, State, Strategy, Template Method, Command ...
  • 동시성 패턴 (Concurrency patterns)
    • Scheduling, Monitor, Lock ...
  • 아키텍처 패턴 (Architecture patterns)
    • Model-View-Controller, Model-View-Presenter, Model-View-ViewModel ...
  • 기타 패턴
    • Dependency injection, Lazy loading, Mock object ...

대표적인 디자인 패턴

싱글톤 패턴

  • 단 하나의 객체만 존재할 수 있는 클래스를 구현하는 패턴
class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

팩토리 패턴

  • 구상 클래스 객체를 전담하여 생성하는 클래스를 구현하는 패턴
  • 팩토리 메소드 패턴 (ref)

interface Shape {
    void draw();
}

class Rectangle implements Shape {
  @Override
  public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
    }
}

class Square implements Shape {
  @Override
  public void draw() {
      System.out.println("Inside Square::draw() method.");
  }
}

class Circle implements Shape {
  @Override
  public void draw() {
      System.out.println("Inside Circle::draw() method.");
  }
}

class ShapeFactory {


Shape getShape(String shapeType){
    if(shapeType == null){
      return null;
    }		
    if(shapeType.equalsIgnoreCase("CIRCLE")){
      return new Circle();
      
    } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
      return new Rectangle();
      
    } else if(shapeType.equalsIgnoreCase("SQUARE")){
      return new Square();
    }
    
    return null;
  }
}
class FactoryPatternDemo {
  public static void main(String[] args) {
    ShapeFactory shapeFactory = new ShapeFactory();

    Shape shape1 = shapeFactory.getShape("CIRCLE");
    shape1.draw();

    Shape shape2 = shapeFactory.getShape("RECTANGLE");

    shape2.draw();

    Shape shape3 = shapeFactory.getShape("SQUARE");

    shape3.draw();
  }
}

추상 팩토리 패턴

public interface Shape {
  void draw();
}

class RoundedRectangle implements Shape {
  @Override
  public void draw() {
      System.out.println("Inside RoundedRectangle::draw() method.");
  }
}

class RoundedSquare implements Shape {
  @Override
  public void draw() {
      System.out.println("Inside RoundedSquare::draw() method.");
  }
}

class Rectangle implements Shape {
  @Override
  public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
  }
}

abstract class AbstractFactory {
  abstract Shape getShape(String shapeType) ;
}

class ShapeFactory extends AbstractFactory {
  @Override
  public Shape getShape(String shapeType){    
      if(shapeType.equalsIgnoreCase("RECTANGLE")){
        return new Rectangle();         
      }else if(shapeType.equalsIgnoreCase("SQUARE")){
        return new Square();
      }	 
      return null;
  }
}

class RoundedShapeFactory extends AbstractFactory {
  @Override
  public Shape getShape(String shapeType){    
      if(shapeType.equalsIgnoreCase("RECTANGLE")){
        return new RoundedRectangle();         
      }else if(shapeType.equalsIgnoreCase("SQUARE")){
        return new RoundedSquare();
      }	 
      return null;
  }
}

class FactoryProducer {
  public static AbstractFactory getFactory(boolean rounded){   
      if(rounded){
        return new RoundedShapeFactory();         
      }else{
        return new ShapeFactory();
      }
  }
}

class AbstractFactoryPatternDemo {
  public static void main(String[] args) {
      AbstractFactory shapeFactory = FactoryProducer.getFactory(false);

      Shape shape1 = shapeFactory.getShape("RECTANGLE");
      shape1.draw();
      Shape shape2 = shapeFactory.getShape("SQUARE");
      shape2.draw();

      AbstractFactory shapeFactory1 = FactoryProducer.getFactory(true);

      Shape shape3 = shapeFactory1.getShape("RECTANGLE");
      shape3.draw();
      Shape shape4 = shapeFactory1.getShape("SQUARE");
      shape4.draw();
  }
}

데코레이터 패턴

  • 생성자를 이용해 객체에 일정한 기능을 추가하는 패턴

interface Shape {
  void draw();
}

class Rectangle implements Shape {

  @Override
  public void draw() {
      System.out.println("Shape: Rectangle");
  }
}

class Circle implements Shape {

  @Override
  public void draw() {
      System.out.println("Shape: Circle");
  }
}

abstract class ShapeDecorator implements Shape {
  protected Shape decoratedShape;

  public ShapeDecorator(Shape decoratedShape){
      this.decoratedShape = decoratedShape;
  }

  public void draw(){
      decoratedShape.draw();
  }	
}

class RedShapeDecorator extends ShapeDecorator {

  public RedShapeDecorator(Shape decoratedShape) {
      super(decoratedShape);		
  }

  @Override
  public void draw() {
      decoratedShape.draw();	       
      setRedBorder(decoratedShape);
  }

  private void setRedBorder(Shape decoratedShape){
      System.out.println("Border Color: Red");
  }
}

class DecoratorPatternDemo {
  public static void main(String[] args) {

      Shape circle = new Circle();

      Shape redCircle = new RedShapeDecorator(new Circle());

      Shape redRectangle = new RedShapeDecorator(new Rectangle());
      System.out.println("Circle with normal border");
      circle.draw();

      System.out.println("\nCircle of red border");
      redCircle.draw();

      System.out.println("\nRectangle of red border");
      redRectangle.draw();
  }
}

옵저버 패턴

  • Observable 객체의 변화를 Observer에서 알 수 있도록 하는 패턴

class Subject {
  private List<Observer> observers = new ArrayList<Observer>();
  private int state;

  public int getState() {
      return state;
  }

  public void setState(int state) {
      this.state = state;
      notifyAllObservers();
  }

  public void attach(Observer observer){
      observers.add(observer);		
  }

  public void notifyAllObservers(){
      for (Observer observer : observers) {
        observer.update();
      }
  } 	
}

abstract class Observer {
  protected Subject subject;
  public abstract void update();
}

class BinaryObserver extends Observer{

  public BinaryObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
  }

  @Override
  public void update() {
      System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) ); 
  }
}

class OctalObserver extends Observer{

  public OctalObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
  }

  @Override
  public void update() {
    System.out.println( "Octal String: " + Integer.toOctalString( subject.getState() ) ); 
  }
}

class HexaObserver extends Observer{

  public HexaObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
  }

  @Override
  public void update() {
      System.out.println( "Hex String: " + Integer.toHexString( subject.getState() ).toUpperCase() ); 
  }
}

class ObserverPatternDemo {
  public static void main(String[] args) {
      Subject subject = new Subject();

      new HexaObserver(subject);
      new OctalObserver(subject);
      new BinaryObserver(subject);

      System.out.println("First state change: 15");	
      subject.setState(15);
      System.out.println("Second state change: 10");	
      subject.setState(10);
  }
}
profile
지금, 새로운 문을 열자! 문 저편에 무엇이 있을지 두렵더라도!!

0개의 댓글