תבנית עיצוב אדפטר ב-Java

התבנית של ממיר (Adapter) היא אחת מתבניות העיצוב המבניות והיא משמשת כך ששני ממשקים לא קשורים יכולים לעבוד יחד. העצם שמקשר ביניהם נקרא ממיר.

תבנית עיצוב של ממיר

אחד מדוגמאות החיים המוצלחות של השימוש בתבנית ממיר היא מטען הטלפון הנייד. סוללת הטלפון הנייד דורשת 3 וולט לטעינה, אך השקע הרגיל יוצא בעיקרו עם 120 וולט (בארצות הברית) או 240 וולט (בהודו). לכן, מטען הטלפון הנייד פועל כממיר בין תקע הטעינה של הטלפון הנייד ובין שקע החשמל בקיר. ננסה ליישם ממיר מרובה באמצעות תבנית הממיר במדריך זה. אז נתחיל עם שני מחלקות – Volt (למדידת וולטים) ו-Socket (יוצר וולטים קבועים של 120 וולט).

package com.journaldev.design.adapter;

public class Volt {

	private int volts;
	
	public Volt(int v){
		this.volts=v;
	}

	public int getVolts() {
		return volts;
	}

	public void setVolts(int volts) {
		this.volts = volts;
	}
	
}
package com.journaldev.design.adapter;

public class Socket {

	public Volt getVolt(){
		return new Volt(120);
	}
}

כעת אנו רוצים לבנות ממיר שיכול ליצור 3 וולט, 12 וולט וברירת מחדל של 120 וולט. אז ניצור ממשק ממיר עם השיטות הללו.

package com.journaldev.design.adapter;

public interface SocketAdapter {

	public Volt get120Volt();
		
	public Volt get12Volt();
	
	public Volt get3Volt();
}

תבנית ממיר דו-כיוונית

בעת ביצוע דפוס מתאם, ישנם שני גישות – מתאם קבוצתי ומתאם אובייקט. עם זאת, שתי הגישות הללו מספקות את אותו התוצאה.

  1. מתאם קבוצתי – גרסה זו משתמשת בההתרשמות מהורשה של Java ומרחיבה את ממשק המקור, במקרה שלנו מחלקת Socket.
  2. מתאם אובייקט – גרסה זו משתמשת בהרכבה ב-Java והמתאם מכיל את אובייקט המקור.

דפוס עיצוב המתאם – מתאם קבוצתי

הנה המימוש של גרסת מתאם קבוצתי שלנו.

package com.journaldev.design.adapter;

//שימוש בהורשה לדפוס המתאם
public class SocketClassAdapterImpl extends Socket implements SocketAdapter{

	@Override
	public Volt get120Volt() {
		return getVolt();
	}

	@Override
	public Volt get12Volt() {
		Volt v= getVolt();
		return convertVolt(v,10);
	}

	@Override
	public Volt get3Volt() {
		Volt v= getVolt();
		return convertVolt(v,40);
	}
	
	private Volt convertVolt(Volt v, int i) {
		return new Volt(v.getVolts()/i);
	}

}

דפוס עיצוב המתאם – מימוש מתאם אובייקט

הנה המימוש של גרסת מתאם אובייקט שלנו.

package com.journaldev.design.adapter;

public class SocketObjectAdapterImpl implements SocketAdapter{

	//שימוש בהרכבה לדפוס המתאם
	private Socket sock = new Socket();
	
	@Override
	public Volt get120Volt() {
		return sock.getVolt();
	}

	@Override
	public Volt get12Volt() {
		Volt v= sock.getVolt();
		return convertVolt(v,10);
	}

	@Override
	public Volt get3Volt() {
		Volt v= sock.getVolt();
		return convertVolt(v,40);
	}
	
	private Volt convertVolt(Volt v, int i) {
		return new Volt(v.getVolts()/i);
	}
}

שים לב שמימושי המתאםים שנמצאים בשני המימושים דומים בגדול והם מיישמים את ממשק ה־SocketAdapter. ממשק המתאם יכול גם הוא להיות מחלקה מופשטת. הנה תוכנית בדיקה לצורך צריבת יישום של דפוס עיצוב המתאם שלנו.

package com.journaldev.design.test;

import com.journaldev.design.adapter.SocketAdapter;
import com.journaldev.design.adapter.SocketClassAdapterImpl;
import com.journaldev.design.adapter.SocketObjectAdapterImpl;
import com.journaldev.design.adapter.Volt;

public class AdapterPatternTest {

	public static void main(String[] args) {
		
		testClassAdapter();
		testObjectAdapter();
	}

	private static void testObjectAdapter() {
		SocketAdapter sockAdapter = new SocketObjectAdapterImpl();
		Volt v3 = getVolt(sockAdapter,3);
		Volt v12 = getVolt(sockAdapter,12);
		Volt v120 = getVolt(sockAdapter,120);
		System.out.println("v3 volts using Object Adapter="+v3.getVolts());
		System.out.println("v12 volts using Object Adapter="+v12.getVolts());
		System.out.println("v120 volts using Object Adapter="+v120.getVolts());
	}

	private static void testClassAdapter() {
		SocketAdapter sockAdapter = new SocketClassAdapterImpl();
		Volt v3 = getVolt(sockAdapter,3);
		Volt v12 = getVolt(sockAdapter,12);
		Volt v120 = getVolt(sockAdapter,120);
		System.out.println("v3 volts using Class Adapter="+v3.getVolts());
		System.out.println("v12 volts using Class Adapter="+v12.getVolts());
		System.out.println("v120 volts using Class Adapter="+v120.getVolts());
	}
	
	private static Volt getVolt(SocketAdapter sockAdapter, int i) {
		switch (i){
		case 3: return sockAdapter.get3Volt();
		case 12: return sockAdapter.get12Volt();
		case 120: return sockAdapter.get120Volt();
		default: return sockAdapter.get120Volt();
		}
	}
}

כאשר אנו מפעילים את תוכנית הבדיקה שלמעלה, אנו מקבלים את הפלט הבא.

v3 volts using Class Adapter=3
v12 volts using Class Adapter=12
v120 volts using Class Adapter=120
v3 volts using Object Adapter=3
v12 volts using Object Adapter=12
v120 volts using Object Adapter=120

תרשים המחלקות של דפוס העיצוב "מתאם"

דוגמה לשימוש בדפוס עיצוב המתאם ב־JDK

כמה מדוגמאות לשימוש בדפוס עיצוב המתאם שניתן למצוא בקלות במחלקות ה־JDK הן;

  • java.util.Arrays#asList()
  • java.io.InputStreamReader(InputStream) (מחזירה Reader)
  • java.io.OutputStreamWriter(OutputStream) (מחזירה Writer)

זהו כל הכול לגבי דפוס עיצוב המתאם ב־Java.

Source:
https://www.digitalocean.com/community/tutorials/adapter-design-pattern-java