![Contoh Proxy Design Pattern](http://images.ctfassets.net/7wjlcr9d5ii8/7mxDYbiEsE11CFpGbxmsrv/01a019ae9b536ac9aadc428674ba3f35/1200px-Proxy_concept_en.jpg?w=1200&h=900&fl=progressive&q=75&fm=jpg)
Design pattern ini seringnya digunakan ketika membuat framework. Beberapa framewrok menggunakan Proxy behind the scene untuk memanipulasi behavior objek. Seperti saat melakukan Autowired pada Spring atau Mock pada Mockito. Framework biasanya menggunakan library dari JDK atau library pihak ketiga seperti CGLIB untuk membuat proxy. Tapi dalam tulisan kali ini gw hanya memberikan contoh menggunakan Proxy sederhana sebagai pembelajaran. Untuk menggunakan library seperti CGLIB mungkin akan gw bahas pada kesempatan lain.
Proxy Design Pattern adalah Structural Design Pattern yang berguna sebagai pengganti objek asli dan memiliki kontrol akses terhadap objek asli tersebut seperti melakukan sesuatu sebelum atau sesudah eksekusi objek asli.
Proxy Design Pattern
Use Case
Terdapat sebuah class UserDetailUseCase dari modul luar untuk melakukan print User. Kita tidak memiliki akses untuk melakukan modifikasi terhadap class tersebut.
Contoh code
Class User
public class User{
private final int id;
private final String name;
public User(int id, String name){
this.id = id;
this.name = name;
}
public int getId(){
return id;
}
public String getName(){
return name;
}
}
Interface UserDetail
public interface UserDetail{
void printUserDetail(User user) throws Exception;
}
Class UserDetailUseCase
public class UserDetailUseCase implements UserDetail{
@Override
public void printUserDetail(User user) throws Exception{
System.out.println("user.getName() = " + user.getName());
System.out.println("user.getId() = " + user.getId());
}
}
Contoh penggunaan
public static void main(String[] args) throws Exception{
UserDetail userDetail = new UserDetailUseCase();
userDetail.printUserDetail(new User(11, "ferry"));
}
Masalah
Misalkan selanjutnya kita ingin menambahkan validasi User sebelum eksekusi print. Seperti yang sudah dijelaskan di atas, kita tidak mempunyai akses terhadap class UserDetailUseCase tersebut. Jadi kita tidak bisa melakukan modifikasiš¤.
Solusi
Solusi untuk kasus di atas adalah kita membuat class Proxy agar bisa dimodifikasi. Sekarang kita praktekkan Proxy Design Patternš.
Class UserDetailProxy
public static class UserDetailProxy extends UserDetailUseCase{
private static UserDetailUseCase userDetailUseCase = null;
@Override
public void printUserDetail(User user) throws Exception{
if(userDetailUseCase == null){
userDetailUseCase = new UserDetailUseCase();
}
if(user == null){
throw new Exception("user can't be null");
}
if(user.getId() < 1){
throw new Exception("id can't be less than 1");
}
if(user.getName() == null){
throw new Exception("name can't be null");
}
userDetailUseCase.printUserDetail(user);
}
}
Contoh Penggunaan
public static void main(String[] args) throws Exception{
UserDetail userDetail = new UserDetailProxy();
userDetail.printUserDetail(new User(11, "ferry"));
}
Dengan class Proxy sekarang kita bisa memodifikasi behavior UserDetailUseCase tanpa harus melakukan modifikasi langsung. Kita juga bisa melakukan caching objek di dalam class proxy agar objek asli dari UserDetailUseCase hanya dibuat satu kali saat pertama kali diakses saja.
Kapan menggunakan Proxy Design Pattern?
Proxy Design Pattern biasanya digunakan pada framework/library. Contohnya Mockito, saat melakukan mock, mockito ga punya akses langsung pada class yang kita punya untuk mocking objek. Oleh karena itu Mockito membuat Proxy class agar behavior dari objek asli bisa dimodifikasi tanpa harus mengubah langsung pada objek asli tersebut.
Verdict
Proxy Design Pattern membuat subclass dari objek asli agar objek asli bisa dimodifikasi secara tidak langsung. Contoh yang paling umum adalah pada framework. Framework dapat melakukan modifikasi pada objek asli yang kita punya lewat Proxy. Framework melakukannya lewat library seperti CGLIB atau JDK Dynamic Proxy. Kebetulan contoh di atas kita melakukannya manual, secara sederhana agar dapat dipahami dengan mudah untuk pemula. Jadi agak berbeda dengan implementasi yang dilakukan oleh framework. Mungkin di lain kesempatan gw bakal bikin contoh menggunakan CGLIB. Secara struktur, Proxy memang memiliki kemiripan dengan Decorator Design Pattern. Bedanya, User memiliki kontrol penuh terhadap objek asli pada Decorator. Sedangkan pada Proxy, kontrol penuh terhadap objek asli dilakukan di dalam komponen Proxy.