DesignPattern #구조

곽서현·2022년 11월 15일
0

[코드 참조 velog]
https://velog.io/@ha0kim/Design-Pattern-%EA%B5%AC%EC%A1%B0-%ED%8C%A8%ED%84%B4Structural-Patterns

[ 구조 패턴 : 7개 ]

✅ 어댑터(Adapter) 패턴

📌 개념
인터페이스가 호환되지 않는 클래스들을 함께 이용할 수 있도록, 타 클래스의 인터페이스를 기존 인터페이스에 덧씌운다.

클라이언트에서 어댑터를 사용하는 방법
1. 클라이언트에서 타겟 인터페이스를 사용하여 메소드를 호출함으로써 어댑터에 요청을 한다.
2. 어댑터에서는 어댑티 인터페이스를 사용하여 그 요청을 어댑티에 대한 하나 이상의 메소드 호출로 변환한다.
3. 클라이언트에서는 호출 결과를 받긴 하지만 중간에 어댑터가 껴 있는지는 알지 못한다.

📌 장점

  • 관계가 없는 인터페이스 간 같이 사용 가능
  • 프로그램 검사 용이
  • 기존 코드를 변경하지 않아도 되기 때문에 클래스 재활용성 증가

📌 단점

  • 구성요소를 위해 클래스를 증가시켜야 하기 때문에 복잡도 증가
  • 클래스 Adapter의 경우 상속을 사용하기 때문에 유연하지 못하다.
  • 객체 Adapter의 경우 대부분의 코드를 다시 작성해야 하기 때문에 효율적이지 못하다.

✅ 브리지(Bridge) 패턴

📌 개념
구현부에서 추상층을 분리하여 각자 독립적으로 변형할 수 있게 하는 패턴이다.
추상적 개념(추상클래스, extends)과 구체적 구현(인터페이스, implements)을 서로 다른 두개의 인터페이스로 구현하는 디자인 패턴!
브릿지 패턴은 캡슐화(encapsulation),집합(aggregation)을 사용하고 다른 클래스들로 책임을 분리시키기 위해 상속(inheritance)를 사용한다.

📌 장점

  • 인터페이스와 구현이 분리된다.
  • 서로 독립적으로 확장할 수 있다.
  • 구현 세부사항을 클라이언트에게 은닉하여 캡슐화를 지킬 수 있다.

📌 단점

  • 디자인이 복잡해진다.

📌 활용 상황

  • 런타임에 실제로 사용될 구체적인 구현체가 결정되어야 할 때 유용하다.
  • 구현할 클래스의 기능부 및 구현부가 지속적인 확장 가능성이 있을 때 유용하다.

✅ 합성 패턴(Composite pattern)

📌 개념
객체들의 관계를 트리 구조로 구성하여 전체-부분 계층을 표현하는 패턴으로 여러 개의 객체들로 구성된 복합 객체와 단일 객체를 클라이언트에서 구별없이(같은 타입으로!) 다루게 한다.
또한, 복합 객체(전체)와 단일 객체(leaf)를 같은 타입으로 취급하기 위한 인터페이스로 Component를 선언하는데, left 클래스와 전체에 해당하는 Composite 클래스에 공통 인터페이스를 정의한다.

📌 장점

  • 전체-부분의 관계(Ex. Directory-File)를 갖는 객체들 사이의 관계를 정의할 때 유용하다.
  • 클라이언트는 전체와 부분을 구분하지 않고 동일한 인터페이스를 사용할 수 있다.
  • 객체들이 모두 같은 타입으로 취급되기 때문에 새로운 클래스 추가가 용이하다.

📌 단점

  • 설계를 일반화 시켜 객체간의 구분, 제약이 힘들다.

📌 활용 상황

  • 객체들 간에 계급 및 계층구조가 있고 이를 표현해야할 때
  • 클라이언트가 단일 객체와 집합 객체를 구분하지 않고 동일한 형태로 사용하고자 할 때

✅ 데코레이터 패턴(Decorator Pattern)

📌 개념
객체의 결합을 통해 기능을 동적으로 유연하게 확장할 수 있게 해주는 패턴
객체에 추가적인 요건을 동적으로 첨가하며 기능 확장이 필요할 때 서브 클래스 대신 쓸 수 있는 유일한 대안이 될 수 있다.

즉, 기본 기능(ConcreteComponent)에 추가할 수 있는 기능의 종류가 많은 경우에 각 추가 기능을 Decorator 추상 클래스로 정의한 후 필요한 Decorator 객체(ConcreteDecorator)를 조합함으로써 추가 기능의 조합을 설계 하는 방식이다.

합성패턴과 같이 ConcreteComponent와 Decorator 두 객체를 동등하게 다루기 위한 인터페이스인 Component가 상위에 존재한다.

📌 장점

  • 객체에 동적으로 기능 추가가 간단하게 가능하다.

📌 단점

  • 자잘한 데코레이터 클래스들이 계속 추가되어 클래스가 많아질 수 있다.
  • 객체의 정체를 알기 힘들고 복잡해질 수 있다.

📌 활용 상황
객체가 상황에 따라 다양한 기능이 추가되거나 삭제되어야 할 때

public class ChristmasTreeMain {

    public static void main(String[] args) {
    
        // Christmas tree
        ChristmasTree tree = new DefaultChristmasTree();
        System.out.println(tree.decorate());

        // Christmas tree + Lights
        ChristmasTree treeWithLights = new Lights(
                new DefaultChristmasTree()
        );
        
        System.out.println(treeWithLights.decorate());

        // Christmas tree + Lights + Flowers
        ChristmasTree treeWithLightsAndFlowers = new Flowers(
                new Lights(
                        new DefaultChristmasTree()
                )
        );
        
        System.out.println(treeWithLightsAndFlowers.decorate());
    }
}

🙄 기본 객체인 new DefaultChristmasTree() 에 기능 추가를 new Lights(new DefaultChristmasTree()); 와 같이 동적인 방식으로 하고 있다. 이게 가능한 이유는?

A. Decorator 객체의 생성자로 Component를 받음으로써 Decorator를 이어 붙일 수가 있고 super를 통해 넘어오는 Component 의 operation(decorate()) 을 먼저 수행하기 때문이다.
(이건 크리스마스 트리 관련 코드 볼 것)


✅ 프록시 패턴(Proxy Pattern)

📌 개념
실제 기능을 수행하는 객체(Real Object) 대신 가상의 객체(Proxy Object)를 사용해 로직의 흐름을 제어하는 디자인 패턴이다.
구체적인 업무를 담당하고 있는 클래스에 접근하기 전에, 간단한 사전 작업(전처리, 캐싱) 처리하는 클래스(Proxy)를 두는 구조를 프록시 패턴이라고 한다.
이 패턴은 주요 기능이 요청을 받아 수행하기 전에, 이 요청에 대한 부가적인 전처리들을 수행하는 로직을 세우고 싶을 때 사용한다.

📌 장점

  • 기본 객체의 리소스가 무거운 경우, 프록시 객체에서 간단한 처리를 하거나 기본 객체를 캐싱 처리함으로써 부하를 줄일 수 있다.
  • 기본 객체에 대한 수정 없이, 클라이언트에서의 사용과 기본 객체 사이에 일련의 로직을 프록시 객체를 통해 넣을 수 있다.
  • 프록시는 기본 객체와 요청 사이에 있기 때문에, 일종의 방패(보안)의 역할도 한다.

📌 단점

  • 프록시 객체가 중간에 껴있기 때문에, 간혹 응답이 느려질 수 있다. (캐싱이 안되어있는 초기 사용의 경우)

📌 활용 상황

  • 기본 객체가 리소스 집약적인 경우. 자잘한 작업들은 프록시 객체가 처리하게 한다.
  • 기본 객체에 접근을 제어해야하는 경우. 프록시 객체가 권한에 따라 접근 로직을 다르게 처리하게 한다.

✅ 퍼사드 패턴(Facade Pattern)

📌 개념
Facade (외관)는 "건물의 정면"을 의미하는 단어로 어떤 소프트웨어의 다른 커다란 코드 부분에 대하여 간략화된 인터페이스를 제공해주는 디자인 패턴을 의미한다.
서브 시스템에 있는 인터페이스들에 대한 통합 인터페이스를 제공하여 서브 시스템을 더 쉽게 사용할 수 있도록 만드는 더 높은 수준의 인터페이스.

📌 장점

  • 서브 시스템에 대한 의존성을 한곳으로 모을 수 있다.(캡슐화)

📌 단점

  • 퍼사드 클래스가 서브 시스템에 대한 모든 의존성을 가지게 된다.

플라이웨이트,,안해욥!

0개의 댓글