본문 바로가기
DesignPattern

[Design Pattern] Proxy Pattern

by 봄석 2019. 10. 8.

[Design Pattern] Proxy Pattern

 

Proxy Pattern이란?

Proxy는 우리말로 대리자, 대변자라는 뜻입니다.

Proxy Pattern이란 프락시에게 어떤 일을 대신시키는 것입니다.

실제 기능을 수행하는 객체 Real Object 대신 가상의 객체 Proxy Object를 사용해 로직의 흐름을 제어하는 디자인 패턴입니다.

 

구체적으로 인터페이스를 사용하고 실행시킬 클래스에 대한 객체가 들어갈 자리에 `대리자`객체를 대신 투입하여

실제 실행시킬 클래스에 대한 객체를 통해 메서드를 호출하고 반환 값을 받는지. 대리자 객체를 통해 메소드를

호출하고 반환값을 받는지 전혀 모르게 처리하는 것입니다.

 

여기서 중요한 것은 , 흐름 제어만 할 뿐 결괏값을 조작하거나 변경시키면 안 된다는 점입니다.

 

Proxy Pattern의 특징

1.  대리자는 실제 서비스와 같은 이름의 메서드를 구현한다. 이때 인터페이스를 사용합니다

2. 대리자는 실제 서비스에 대한 참조 변수를 갖습니다.(함성).

3. 대리자는 실제 서비스의 같은 이름을 가진 메서드를 호출하고 그 값을 클라이언트에게 돌려줍니다.

4. 대리자는 실제 서비스의 메서드 호출 전후에 별도의 로직을 수행할 수도 있습니다.

 

 

No Use Proxy Pattern with Java

프락시 패턴을 안 썻을때 

class Service {
    public String greeting(String str) {
        return "안녕하세요 " + str + "입니다.";
    }
}
public class Client {
    public static void main(String[] args) {
        Service service = new Service();
        System.out.println(service.greeting("bsjo"));
    }
}

 

Proxy Pattern with Java

프록시 패턴을 썻을때 

interface IService {
    public String greeting(String str);
}
class Service implements IService{
    @Override
    public String greeting(String str) {
        return "안녕하세요 " + str + "입니다.";
    }
}
class Proxy implements IService {
    IService iService;
    @Override
    public String greeting(String str) {
        System.out.println("호출에 대한 흐름 제어가 주목적이며, 반환 결과를 그대로 전달한다.");
        iService = new Service();
        return iService.greeting(str);
    }
    
}
public class Client {
    public static void main(String[] args) {
        IService service = new Proxy();
        System.out.println(service.greeting("kkkkk"));
    }
}

 


Proxy Pattern with Kotlin

파일 읽기 시스템

interface File {
    fun read(name: String)
}
class NormalFile : File {
    override fun read(name: String) = println("Reading file: $name")
}
//Proxy:
class SecuredFile(private val normalFile: File) : File {
    var password: String = ""

    override fun read(name: String) {
        if (password == "secret") {
            println("Password is correct: $password")
            normalFile.read(name)
        } else {
            println("Incorrect password. Access denied!")
        }
    }
}

 Proxy(대리자)인 SecuredFile은 

실제 서비스인 File의 참조를 갖고 있고(nomalFile의 참조를 생성자로 받음) , 같은 이름의 메서드(read)를 구현합니다.

그리고 실제 서비스인 NomalFile과 같은 이름의 메서드를 호출하고 그값을 반환합니다.

실제 서비스의 메소드 read를 수행하기 전에 별도의 로직인 password확인을 실행합니다.

 

class ProtectionProxyTest {
    @Test
    fun `Protection Proxy`() {
        val securedFile = SecuredFile(NormalFile())

        with(securedFile) {
            read("readme.md")
            password = "secret"
            read("readme.md")
        }
    }
}

 

//result
Incorrect password. Access denied!
Password is correct: secret
Reading file: readme.md

정리 

위 예제들은 프록시패턴(대리자)를 세웠습니다.

프록시 패턴을 간단하게 정리하면 "제어 흐름을 조정하기 위한 목적으로 중간에 대리자를 두는 패턴"입니다.

 

위의 예를 보면 SOLID의 개방 폐쇄 원칙(OCP)을 활용한 것임을 알 수 있습니다.

또한 인터페이스를 두고 중간에 영향을 받지 않도록 의존 역전 법칙(DIP)을 활용한 예입니다.

 

소스코드 보러가기

https://github.com/qjatjr1108/DesignPattern

 

qjatjr1108/DesignPattern

DesignPattern Sample. Contribute to qjatjr1108/DesignPattern development by creating an account on GitHub.

github.com

 

'DesignPattern' 카테고리의 다른 글

[Design Pattern] Composition Pattern  (2) 2019.10.10
[Design Pattern] Bridge Pattern  (4) 2019.10.10
[Design Pattern] Decorator Pattern  (2) 2019.10.08
[Design Pattern] Facade Pattern  (2) 2019.10.08
[Design Pattern] Adapter Pattern  (4) 2019.10.07

댓글