الگو Adaptor الگوی adapter یک الگوی ساختاری است که برای سازگار کردن موجودیت های مختلف با هم به کار میرود.
داده ها در دنیای دیجیتال به فرمتهای مختلف ذخیره و پردازش میشوند. این تفاوت در لایهها و فرمتهای مختلف نمایان و آشکار است. نمونه واضح و پرکاربرد آن فرمتهای مختلفی مانند json و xml و باینری… است که در پروتکلهای ارتباطی متفاوت مورد استفاده قرار میگیرد و گاها برای ایجاد ارتباط و امکان خوانده شدن این دادهها نیازمند یک روش و الگوی قابل گسترش هستیم.
الگوی adapter در اینجا مورد استفاده قرار میگیرد. نحوه پیاده سازی این الگو در زبان گو به اینصورت است که ابتدا یک struct مادر به همراه متد یا متدهای مورد نیاز ما که مابین موجودیتهای متفاوت مشترک است تعریف میشود. همزمان برای هر فرمت داده یک struct جهت سازگار کردن دادهها ساخته می شود. متدهای این strcut توسط یک interface فراخوانی شده است. در اینجا کافی است که این interface را به عنوان ورودی متدهای struct مادر درنظر بگیریم. اینکار باعث ایجاد ارتباط میان struct ها و موجودیت های مختلف خواهد شد.
در زیر مثالی از پیاده سازی این الگو انجام گرفته است. در این مثال دو دستگاه پرینتر متفاوت وظیفه چاپ بر روی کاغذ با یک ابعاد خاص و مشخص (A4) را دارند در صورتی که هیچکدام بصورت اختصاصی این ابعاد را پشتیبانی نمیکنند بنابراین ما با پیاده سازی الگوی adapter این امکان را ایجاد میکنیم که این تفاوت ابعاد در داخل هر موجودیت مدیریت شود و فقط متد چاپ در ابعاد A4 فراخوانی شود.
package main
type IPrint interface{
PrintA4()
}
type Printer struct {}
func (p Printer) Print(printer IPrint) {
printer.PrintA4()
}
// HP Printer
type HpPrinter struct {}
func (h HpPrinter) PrintWithHP() {
println("print with HP printer")
}
type HpAdapter struct {
printer *HpPrinter
}
func (ha HpAdapter) PrintA4() {
println("adapting to A4 size for HP printer")
//some adapting functions
ha.printer.PrintWithHP()
}
// Canon Printer
type CanonPrinter struct {}
func (c CanonPrinter) PrintWithCanon() {
println("print with Canon printer")
}
type CanonAdapter struct{
printer *CanonPrinter
}
func (ca CanonAdapter) PrintA4() {
println("adapting to A4 size for Canon printer")
//some adapting functions
ca.printer.PrintWithCanon()
}
func main() {
hpPrinter := &HpPrinter{}
hpAdapter := HpAdapter{
printer: hpPrinter,
}
canonPrinter := &CanonPrinter{}
canonAdapter := CanonAdapter{
printer: canonPrinter,
}
printer := Printer{}
printer.Print(hpAdapter)
printer.Print(canonAdapter)
}
adapting to A4 size for HP printer
print with HP printer
adapting to A4 size for Canon printer
print with Canon printer
۱− در مثال بالا ما برای هر پرینتر یک struct به عنوان adapter ایجاد کرده ایم (خطوط 21 و 39) ۲− این struct ها متدی به نام PrintA4 را تعریف میکنند که وظیفه تغییر داده ها به فرمت مشترک مورد نظر را دارند (خطوط 25 و 43) ۳− این متد در یک اینترفیس به نام IPrint نیز فراخوانی میشود (خط 5) ۴− در این مرحله یک struct به نام Printer ایجاد میکنیم (خط 8) ۵− در مرحله آخر متد اصلی که وظیفه Print کردن کاغذ برای هر پیرنتری را دارد تعریف میکنیم. نکته مهم ورودی این متد است که همان interface تعریف شده در مرحله 3 می باشد. ۶− مرحله آخر تغریف هر پرینتر و printerAdapter در خطوط 52 تا 61 است و درنهایت فراخوانی متد تعریف شده در مرحله 5 برای هر پرینتر در خطوط 64 و 65.