JavaRush /وبلاگ جاوا /Random-FA /الگوهای طراحی در جاوا
Viacheslav
مرحله

الگوهای طراحی در جاوا

در گروه منتشر شد
الگوها یا الگوهای طراحی بخشی از کار توسعه دهندگان هستند که اغلب نادیده گرفته می شوند و حفظ و تطبیق کد با نیازهای جدید را دشوار می کنند. من به شما پیشنهاد می کنم ببینید چیست و چگونه در JDK استفاده می شود. به طور طبیعی، تمام الگوهای اساسی در یک شکل یا شکل دیگر برای مدت طولانی در اطراف ما بوده اند. بیایید آنها را در این بررسی ببینیم.
الگوهای طراحی در جاوا - 1
محتوا:

قالب ها

یکی از رایج ترین الزامات در مشاغل خالی "آشنایی با الگوها" است. اول از همه، ارزش پاسخ دادن به یک سوال ساده را دارد - "الگوی طراحی چیست؟" الگو از انگلیسی به عنوان "الگو" ترجمه شده است. یعنی این یک الگوی خاصی است که طبق آن ما کاری انجام می دهیم. در برنامه نویسی هم همینطور است. برخی از بهترین شیوه ها و رویکردهای ثابت شده برای حل مشکلات رایج وجود دارد. هر برنامه نویسی یک معمار است. حتی زمانی که فقط چند کلاس یا حتی یک کلاس ایجاد می‌کنید، بستگی به شما دارد که کد تا چه زمانی می‌تواند تحت شرایط متغیر باقی بماند، چقدر راحت است که توسط دیگران استفاده شود. و این جایی است که دانش الگوها کمک خواهد کرد، زیرا ... این به شما این امکان را می دهد که به سرعت درک کنید که چگونه بهترین کد را بدون بازنویسی آن بنویسید. همانطور که می دانید، برنامه نویسان افراد تنبلی هستند و نوشتن سریع چیزی آسان تر از تکرار مجدد آن است) الگوها نیز ممکن است شبیه به الگوریتم ها به نظر برسند. اما آنها یک تفاوت دارند. الگوریتم شامل مراحل خاصی است که اقدامات لازم را توصیف می کند. الگوها فقط رویکرد را توصیف می کنند، اما مراحل اجرا را توصیف نمی کنند. الگوها متفاوت است، زیرا ... حل مشکلات مختلف به طور معمول دسته های زیر متمایز می شوند:
  • مولد

    این الگوها مشکل ایجاد شیء قابل انعطاف را حل می کنند

  • ساختاری

    این الگوها مشکل ایجاد ارتباط موثر بین اشیاء را حل می کند

  • رفتاری

    این الگوها مشکل تعامل موثر بین اشیاء را حل می کند

برای در نظر گرفتن مثال‌ها، پیشنهاد می‌کنم از کامپایلر کد آنلاین repl.it استفاده کنید.
الگوهای طراحی در جاوا - 2

الگوهای خلاقیت

بیایید از ابتدای چرخه زندگی اشیاء - با ایجاد اشیاء - شروع کنیم. قالب‌های تولیدی به ایجاد راحت‌تر اشیاء کمک می‌کنند و در این فرآیند انعطاف‌پذیری ایجاد می‌کنند. یکی از معروف ترین آنها " سازنده " است. این الگو به شما اجازه می دهد تا اشیاء پیچیده را مرحله به مرحله ایجاد کنید. در جاوا معروف ترین مثال این است StringBuilder:
class Main {
  public static void main(String[] args) {
    StringBuilder builder = new StringBuilder();
    builder.append("Hello");
    builder.append(',');
    builder.append("World!");
    System.out.println(builder.toString());
  }
}
یکی دیگر از روش های شناخته شده برای ایجاد یک شی، انتقال ایجاد به یک روش جداگانه است. این روش، همانطور که بود، به یک کارخانه اشیاء تبدیل می شود. به همین دلیل است که این الگو را " روش کارخانه " می نامند. به عنوان مثال، در جاوا، اثر آن در کلاس قابل مشاهده است java.util.Calendar. کلاس خود Calendarانتزاعی است و برای ایجاد آن از متد استفاده می شود getInstance:
import java.util.*;
class Main {
  public static void main(String[] args) {
    Calendar calendar = Calendar.getInstance();
    System.out.println(calendar.getTime());
    System.out.println(calendar.getClass().getCanonicalName());
  }
}
این اغلب به این دلیل است که منطق پشت ایجاد شی می تواند پیچیده باشد. به عنوان مثال، در مورد بالا، ما به کلاس پایه دسترسی پیدا می کنیم Calendarو یک کلاس ایجاد می شود GregorianCalendar. اگر به سازنده نگاه کنیم، می بینیم که پیاده سازی های مختلفی بسته به شرایط ایجاد می شود Calendar. اما گاهی اوقات یک روش کارخانه کافی نیست. گاهی اوقات شما نیاز دارید که اشیاء مختلفی ایجاد کنید تا در کنار هم قرار گیرند. یک الگوی دیگر به ما در این امر کمک می کند - " کارخانه انتزاعی ". و سپس ما باید کارخانه های مختلف را در یک مکان ایجاد کنیم. در عین حال، مزیت این است که جزئیات پیاده سازی برای ما مهم نیست، یعنی. مهم نیست که کدام کارخانه خاص را دریافت کنیم. نکته اصلی این است که پیاده سازی های مناسب را ایجاد می کند. مثال فوق العاده:
الگوهای طراحی در جاوا - 3
یعنی بسته به محیط (سیستم عامل) کارخانه خاصی را دریافت خواهیم کرد که عناصر سازگار را ایجاد می کند. به عنوان جایگزینی برای رویکرد ایجاد از طریق شخص دیگری، می‌توانیم از الگوی « نمونه اولیه » استفاده کنیم. ماهیت آن ساده است - اشیاء جدید در تصویر و شباهت اشیاء موجود ایجاد می شوند، یعنی. با توجه به نمونه اولیه آنها. در جاوا، همه با این الگو مواجه شده اند - این استفاده از یک رابط است java.lang.Cloneable:
class Main {
  public static void main(String[] args) {
    class CloneObject implements Cloneable {
      @Override
      protected Object clone() throws CloneNotSupportedException {
        return new CloneObject();
      }
    }
    CloneObject obj = new CloneObject();
    try {
      CloneObject pattern = (CloneObject) obj.clone();
    } catch (CloneNotSupportedException e) {
      //Do something
    }
  }
}
همانطور که می بینید، تماس گیرنده نمی داند چگونه clone. یعنی ایجاد یک شی بر اساس نمونه اولیه بر عهده خود شی است. این به این دلیل مفید است که کاربر را به اجرای شی الگو متصل نمی کند. خوب، آخرین مورد در این لیست الگوی "Singleton" است. هدف آن ساده است - ارائه یک نمونه واحد از یک شی برای کل برنامه. این الگو جالب است زیرا اغلب مشکلات چند رشته ای را نشان می دهد. برای نگاه عمیق تر، این مقالات را بررسی کنید:
الگوهای طراحی در جاوا - 4

الگوهای ساختاری

با ایجاد اشیاء روشن تر شد. اکنون زمان بررسی الگوهای ساختاری است. هدف آنها ایجاد سلسله مراتب طبقاتی با پشتیبانی آسان و روابط آنهاست. یکی از اولین و شناخته شده الگوهای " معاون " (پروکسی) است. پروکسی دارای رابط یکسانی با شی واقعی است، بنابراین برای کلاینت فرقی نمی‌کند که از طریق پراکسی یا مستقیم کار کند. ساده ترین مثال java.lang.reflect.Proxy است :
import java.util.*;
import java.lang.reflect.*;
class Main {
  public static void main(String[] arguments) {
    final Map<String, String> original = new HashMap<>();
    InvocationHandler proxy = (obj, method, args) -> {
      System.out.println("Invoked: " + method.getName());
      return method.invoke(original, args);
    };
    Map<String, String> proxyInstance = (Map) Proxy.newProxyInstance(
        original.getClass().getClassLoader(),
        original.getClass().getInterfaces(),
        proxy);
    proxyInstance.put("key", "value");
    System.out.println(proxyInstance.get("key"));
  }
}
همانطور که می بینید، در مثالی که ما اصلی داریم - این همان چیزی است HashMapکه رابط را پیاده سازی می کند Map. در مرحله بعد یک پروکسی ایجاد می کنیم که جایگزین پروکسی اصلی HashMapبرای بخش مشتری می شود، که و putمتدها را فراخوانی می کند getو منطق خود را در طول تماس اضافه می کند. همانطور که می بینیم، تعامل در الگو از طریق رابط ها رخ می دهد. اما گاهی اوقات یک جایگزین کافی نیست. و سپس می توان از الگوی " دکوراتور " استفاده کرد. به دکوراتور لفاف یا لفاف نیز گفته می شود. پروکسی و دکوراتور بسیار شبیه هم هستند، اما اگر به مثال نگاه کنید، تفاوت را خواهید دید:
import java.util.*;
class Main {
  public static void main(String[] arguments) {
    List<String> list = new ArrayList<>();
    List<String> decorated = Collections.checkedList(list, String.class);
    decorated.add("2");
    list.add("3");
    System.out.println(decorated);
  }
}
برخلاف پروکسی، دکوراتور خود را دور چیزی می‌پیچد که به عنوان ورودی ارسال می‌شود. یک پروکسی هم می‌تواند آنچه را که باید پراکسی شود بپذیرد و هم می‌تواند عمر شیء پراکسی را مدیریت کند (مثلاً یک شیء پراکسی ایجاد کنید). الگوی جالب دیگری وجود دارد - " آداپتور ". شبیه دکوراتور است - دکوراتور یک شی را به عنوان ورودی می گیرد و یک لفاف بر روی این شی برمی گرداند. تفاوت این است که هدف تغییر عملکرد نیست، بلکه تطبیق یک رابط با رابط دیگر است. جاوا یک مثال بسیار واضح برای این دارد:
import java.util.*;
class Main {
  public static void main(String[] arguments) {
    String[] array = {"One", "Two", "Three"};
    List<String> strings = Arrays.asList(array);
    strings.set(0, "1");
    System.out.println(Arrays.toString(array));
  }
}
در ورودی یک آرایه داریم. بعد، یک آداپتور ایجاد می کنیم که آرایه را به رابط می آورد List. هنگام کار با آن، در واقع با یک آرایه کار می کنیم. بنابراین، افزودن عناصر کارساز نخواهد بود، زیرا ... آرایه اصلی را نمی توان تغییر داد. و در این صورت به دست خواهیم آورد UnsupportedOperationException. رویکرد جالب بعدی برای توسعه ساختار کلاس الگوی ترکیبی است . جالب است که مجموعه خاصی از عناصر با استفاده از یک رابط در یک سلسله مراتب درخت مانند مرتب شده اند. با فراخوانی یک متد بر روی یک عنصر والد، ما یک فراخوانی به این متد در تمام عناصر فرزند ضروری دریافت می کنیم. نمونه بارز این الگو UI است (خواه java.awt یا JSF):
import java.awt.*;
class Main {
  public static void main(String[] arguments) {
    Container container = new Container();
    Component component = new java.awt.Component(){};
    System.out.println(component.getComponentOrientation().isLeftToRight());
    container.add(component);
    container.applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
    System.out.println(component.getComponentOrientation().isLeftToRight());
  }
}
همانطور که می بینیم، ما یک جزء به ظرف اضافه کرده ایم. و سپس از ظرف خواستیم جهت گیری جدید اجزا را اعمال کند. و کانتینر با دانستن اینکه از چه اجزایی تشکیل شده است، اجرای این دستور را به تمام اجزای فرزند محول کرد. الگوی جالب دیگر الگوی " پل " است. به این دلیل نامیده می شود که یک ارتباط یا پل بین دو سلسله مراتب کلاس مختلف را توصیف می کند. یکی از این سلسله مراتب ها انتزاع و دیگری اجرا در نظر گرفته می شود. این مورد برجسته است زیرا خود انتزاع اقداماتی را انجام نمی دهد، اما این اجرا را به پیاده سازی واگذار می کند. این الگو اغلب زمانی استفاده می شود که کلاس های "کنترل" و چندین نوع کلاس "پلتفرم" (به عنوان مثال، ویندوز، لینوکس و غیره) وجود داشته باشد. با این رویکرد، یکی از این سلسله مراتب (انتزاع) ارجاع به اشیاء سلسله مراتب دیگر (پیاده سازی) را دریافت می کند و کار اصلی را به آنها محول می کند. از آنجایی که همه پیاده سازی ها از یک رابط مشترک پیروی می کنند، می توان آنها را در انتزاع تعویض کرد. در جاوا، یک مثال واضح از این است java.awt:
الگوهای طراحی در جاوا - 5
برای اطلاعات بیشتر به مقاله " الگوها در جاوا AWT " مراجعه کنید. در بین الگوهای ساختاری، می خواهم به الگوی " نما " نیز توجه کنم. ماهیت آن پنهان کردن پیچیدگی استفاده از کتابخانه ها/چارچوب های پشت این API در پشت یک رابط کاربری مناسب و مختصر است. به عنوان مثال، می توانید از JSF یا EntityManager از JPA به عنوان مثال استفاده کنید. همچنین الگوی دیگری به نام " Flyweight " وجود دارد . ماهیت آن این است که اگر اشیاء مختلف حالت یکسانی داشته باشند، می توان آن را تعمیم داد و نه در هر شی، بلکه در یک مکان ذخیره کرد. و سپس هر شیء قادر خواهد بود به یک بخش مشترک ارجاع دهد، که هزینه های حافظه برای ذخیره سازی را کاهش می دهد. این الگو اغلب شامل پیش ذخیره سازی یا نگهداری مجموعه ای از اشیا است. جالب اینجاست که ما نیز از همان ابتدا این الگو را می شناسیم:
الگوهای طراحی در جاوا - 6
با همین قیاس، مجموعه ای از رشته ها را می توان در اینجا گنجاند. شما می توانید مقاله ای با این موضوع بخوانید: " الگوی طراحی وزن مگس ".
الگوهای طراحی در جاوا - 7

الگوهای رفتاری

بنابراین، ما متوجه شدیم که چگونه می توان اشیاء را ایجاد کرد و چگونه می توان ارتباطات بین کلاس ها را سازماندهی کرد. جالب ترین چیزی که باقی می ماند ایجاد انعطاف پذیری در تغییر رفتار اجسام است. و الگوهای رفتاری در این امر به ما کمک خواهند کرد. یکی از الگوهای متداول، الگوی « استراتژی » است. اینجاست که مطالعه الگوها در کتاب " ابتدا سر. الگوهای طراحی " آغاز می شود. با استفاده از الگوی «استراتژی»، می‌توانیم در داخل یک شی ذخیره کنیم که چگونه عمل را انجام خواهیم داد، یعنی. شی داخل یک استراتژی ذخیره می کند که می تواند در طول اجرای کد تغییر کند. این الگویی است که ما اغلب هنگام استفاده از مقایسه کننده استفاده می کنیم:
import java.util.*;
class Main {
  public static void main(String[] args) {
    List<String> data = Arrays.asList("Moscow", "Paris", "NYC");
    Comparator<String> comparator = Comparator.comparingInt(String::length);
    Set dataSet = new TreeSet(comparator);
    dataSet.addAll(data);
    System.out.println("Dataset : " + dataSet);
  }
}
قبل از ما - TreeSet. این رفتار TreeSetحفظ نظم عناصر را دارد، یعنی. آنها را مرتب می کند (زیرا یک SortedSet است). این رفتار یک استراتژی پیش‌فرض دارد که در JavaDoc می‌بینیم: مرتب‌سازی در «ترتیب طبیعی» (برای رشته‌ها، این ترتیب واژگانی است). اگر از سازنده بدون پارامتر استفاده کنید این اتفاق می افتد. اما اگر بخواهیم استراتژی را تغییر دهیم، می توانیم عبور کنیم Comparator. در این مثال، می‌توانیم مجموعه خود را به‌عنوان ایجاد کنیم new TreeSet(comparator)، و سپس ترتیب ذخیره‌سازی عناصر (استراتژی ذخیره‌سازی) به چیزی که در مقایسه‌کننده مشخص شده است تغییر می‌کند. جالب اینجاست که تقریباً همان الگوی به نام " دولت " وجود دارد. الگوی "State" می گوید که اگر رفتاری در شی اصلی داشته باشیم که به وضعیت این شی بستگی دارد، می توانیم خود حالت را به عنوان یک شی توصیف کنیم و شی حالت را تغییر دهیم. و تماس‌ها را از شی اصلی به حالت تفویض کنید. الگوی دیگری که از مطالعه اصول اولیه زبان جاوا برای ما شناخته شده است، الگوی " Command " است. این الگوی طراحی نشان می دهد که دستورات مختلف را می توان به عنوان کلاس های مختلف نشان داد. این الگو بسیار شبیه به الگوی Strategy است. اما در الگوی Strategy، ما در حال تعریف مجدد نحوه انجام یک عمل خاص بودیم (مثلاً مرتب سازی در TreeSet). در الگوی "Command"، ما دوباره تعریف می کنیم که چه عملی انجام می شود. هنگام استفاده از thread دستور الگو هر روز با ما همراه است:
import java.util.*;
class Main {
  public static void main(String[] args) {
    Runnable command = () -> {
      System.out.println("Command action");
    };
    Thread th = new Thread(command);
    th.start();
  }
}
همانطور که می بینید، دستور یک عمل یا دستور را تعریف می کند که در یک رشته جدید اجرا می شود. همچنین ارزش در نظر گرفتن الگوی "زنجیره مسئولیت " را دارد . این الگو نیز بسیار ساده است. این الگو می گوید که اگر چیزی نیاز به پردازش دارد، می توانید کنترل کننده ها را در یک زنجیره جمع آوری کنید. به عنوان مثال، این الگو اغلب در سرورهای وب استفاده می شود. در ورودی، سرور درخواستی از کاربر دارد. سپس این درخواست از طریق زنجیره پردازش عبور می کند. این زنجیره از کنترل‌کننده‌ها شامل فیلترها (به عنوان مثال، عدم پذیرش درخواست‌ها از لیست سیاه آدرس‌های IP)، کنترل‌کننده‌های احراز هویت (فقط به کاربران مجاز اجازه می‌دهد)، کنترل‌کننده هدر درخواست، کنترل‌کننده ذخیره‌سازی و غیره است. اما یک مثال ساده تر و قابل فهم تر در جاوا وجود دارد java.util.logging:
import java.util.logging.*;
class Main {
  public static void main(String[] args) {
    Logger logger = Logger.getLogger(Main.class.getName());
    ConsoleHandler consoleHandler = new ConsoleHandler(){
		@Override
            public void publish(LogRecord record) {
                System.out.println("LogRecord обработан");
            }
        };
    logger.addHandler(consoleHandler);
    logger.info("test");
  }
}
همانطور که می بینید، Handlers به ​​لیست کنترل کننده های لاگر اضافه شده است. هنگامی که یک لاگر پیامی را برای پردازش دریافت می کند، هر پیامی از این قبیل از زنجیره ای از کنترل کننده ها (از logger.getHandlers) برای آن لاگر عبور می کند. الگوی دیگری که هر روز می بینیم " Iterator " است. ماهیت آن جدا کردن مجموعه ای از اشیا (یعنی کلاسی که یک ساختار داده را نشان می دهد. به عنوان مثال، List) و پیمایش این مجموعه است.
import java.util.*;
class Main {
  public static void main(String[] args) {
    List<String> data = Arrays.asList("Moscow", "Paris", "NYC");
    Iterator<String> iterator = data.iterator();
    while (iterator.hasNext()) {
      System.out.println(iterator.next());
    }
  }
}
همانطور که می بینید، تکرار کننده بخشی از مجموعه نیست، بلکه توسط یک کلاس جداگانه نمایش داده می شود که مجموعه را طی می کند. کاربر تکرار کننده ممکن است حتی نداند که روی چه مجموعه ای تکرار می کند، یعنی. او از چه مجموعه ای بازدید می کند؟ الگوی بازدیدکننده نیز ارزش در نظر گرفتن دارد . الگوی بازدیدکننده بسیار شبیه به الگوی تکرارکننده است. این الگو به شما کمک می کند ساختار اشیاء را دور بزنید و اعمالی را روی این اشیا انجام دهید. آنها بیشتر در مفهوم متفاوت هستند. تکرار کننده مجموعه را طی می کند تا مشتری که از تکرار کننده استفاده می کند اهمیتی نداشته باشد که مجموعه در داخل چیست، فقط عناصر موجود در دنباله مهم هستند. منظور از بازدیدکننده این است که سلسله مراتب یا ساختار خاصی از اشیایی که ما بازدید می کنیم وجود دارد. به عنوان مثال، می توانیم از پردازش دایرکتوری جداگانه و پردازش فایل جداگانه استفاده کنیم. جاوا پیاده سازی خارج از جعبه این الگو را به شکل زیر دارد java.nio.file.FileVisitor:
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.*;
class Main {
  public static void main(String[] args) {
    SimpleFileVisitor visitor = new SimpleFileVisitor() {
      @Override
      public FileVisitResult visitFile(Object file, BasicFileAttributes attrs) throws IOException {
        System.out.println("File:" + file.toString());
        return FileVisitResult.CONTINUE;
      }
    };
    Path pathSource = Paths.get(System.getProperty("java.io.tmpdir"));
    try {
      Files.walkFileTree(pathSource, visitor);
    } catch (AccessDeniedException e) {
      // skip
    } catch (IOException e) {
      // Do something
    }
  }
}
گاهی اوقات نیاز است که برخی از اشیاء به تغییرات در اشیاء دیگر واکنش نشان دهند و سپس الگوی Observer به ما کمک می کند . راحت‌ترین راه، ارائه مکانیزم اشتراکی است که به برخی از اشیا اجازه می‌دهد تا رویدادهایی را که در اشیاء دیگر رخ می‌دهند، نظارت کرده و به آنها پاسخ دهند. این الگو اغلب در شنوندگان و ناظران مختلفی که به رویدادهای مختلف واکنش نشان می دهند استفاده می شود. به عنوان یک مثال ساده، می‌توانیم اجرای این الگو را از نسخه اول JDK به یاد بیاوریم:
import java.util.*;
class Main {
  public static void main(String[] args) {
    Observer observer = (obj, arg) -> {
      System.out.println("Arg: " + arg);
    };
    Observable target = new Observable(){
      @Override
      public void notifyObservers(Object arg) {
        setChanged();
        super.notifyObservers(arg);
      }
    };
    target.addObserver(observer);
    target.notifyObservers("Hello, World!");
  }
}
الگوی رفتاری مفید دیگری وجود دارد - " میانجی ". مفید است زیرا در سیستم های پیچیده کمک می کند تا ارتباط بین اشیاء مختلف را از بین ببریم و تمام تعاملات بین اشیاء را به یک شی، که یک واسطه است، واگذار کنیم. یکی از بارزترین کاربردهای این الگو Spring MVC است که از این الگو استفاده می کند. در اینجا می توانید اطلاعات بیشتری در مورد این موضوع بخوانید: " بهار: الگوی واسطه ". اغلب می توانید همین را در مثال ها ببینید java.util.Timer:
import java.util.*;
class Main {
  public static void main(String[] args) {
    Timer mediator = new Timer("Mediator");
    TimerTask command = new TimerTask() {
      @Override
      public void run() {
        System.out.println("Command pattern");
        mediator.cancel();
      }
    };
    mediator.schedule(command, 1000);
  }
}
مثال بیشتر شبیه یک الگوی فرمان است. و جوهر الگوی «میانجی» در اجرای Timer«الف» نهفته است. در داخل تایمر یک صف کار وجود دارد TaskQueue، یک موضوع وجود دارد TimerThread. ما به عنوان مشتریان این کلاس، با آنها تعامل نداریم، بلکه با Timerشی تعامل داریم، که در پاسخ به فراخوانی ما به متدهای خود، به متدهای سایر اشیاء که واسطه آنهاست دسترسی پیدا می کند. از نظر خارجی ممکن است بسیار شبیه به "نما" به نظر برسد. اما تفاوت این است که وقتی از نما استفاده می شود، اجزا از وجود نما خبر ندارند و با یکدیگر صحبت می کنند. و هنگامی که از "Mediator" استفاده می شود، اجزاء واسطه را می شناسند و از آن استفاده می کنند، اما مستقیماً با یکدیگر تماس ندارند. شایان ذکر است که الگوی " روش الگو " را در نظر بگیرید، این الگو از نام آن مشخص است. نکته اصلی این است که کد به گونه ای نوشته شده است که به کاربران کد (توسعه دهندگان) الگوریتمی ارائه می شود که مراحل آن مجاز به تعریف مجدد است. این به کاربران کد اجازه می دهد تا کل الگوریتم را ننویسند، بلکه فقط به نحوه صحیح اجرای یک یا آن مرحله از این الگوریتم فکر کنند. به عنوان مثال، جاوا یک کلاس انتزاعی دارد AbstractListکه رفتار یک تکرارکننده را با List. با این حال، تکرار کننده خود از روش های برگ مانند:،، استفاده getمی setکند remove. رفتار این روش ها توسط توسعه دهنده فرزندان تعیین می شود AbstractList. بنابراین، تکرار کننده در AbstractList- الگویی برای الگوریتم برای تکرار در یک صفحه است. و توسعه دهندگان پیاده سازی های خاص AbstractListرفتار این تکرار را با تعریف رفتار مراحل خاص تغییر می دهند. آخرین مورد از الگوهایی که ما تحلیل می‌کنیم، الگوی « عکس فوری » (Momento) است. ماهیت آن حفظ حالت خاصی از یک شی با توانایی بازگرداندن این حالت است. قابل تشخیص ترین مثال از JDK سریال سازی شی است. java.io.Serializable. بیایید به یک مثال نگاه کنیم:
import java.io.*;
import java.util.*;
class Main {
  public static void main(String[] args) throws IOException {
    ArrayList<String> list = new ArrayList<>();
    list.add("test");
    // Save State
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    try (ObjectOutputStream out = new ObjectOutputStream(stream)) {
      out.writeObject(list);
    }
    // Load state
    byte[] bytes = stream.toByteArray();
    InputStream inputStream = new ByteArrayInputStream(bytes);
    try (ObjectInputStream in = new ObjectInputStream(inputStream)) {
      List<String> listNew = (List<String>) in.readObject();
      System.out.println(listNew.get(0));
    } catch (ClassNotFoundException e) {
      // Do something. Can't find class fpr saved state
    }
  }
}
الگوهای طراحی در جاوا - 8

نتیجه

همانطور که از بررسی دیدیم، الگوهای بسیار متنوعی وجود دارد. هر کدام مشکل خود را حل می کند. و آگاهی از این الگوها می تواند به شما کمک کند تا به موقع نحوه نوشتن سیستم خود را طوری بنویسید که انعطاف پذیر، قابل نگهداری و مقاوم در برابر تغییرات باشد. و در نهایت، چند لینک برای غواصی عمیق تر: #ویاچسلاو
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION