JavaRush /Java blogi /Random-UZ /Java-da dizayn naqshlari
Viacheslav
Daraja

Java-da dizayn naqshlari

Guruhda nashr etilgan
Naqshlar yoki dizayn naqshlari ishlab chiquvchi ishining ko'pincha e'tibordan chetda qoladigan qismi bo'lib, kodni saqlash va yangi talablarga moslashishni qiyinlashtiradi. Men sizga bu nima ekanligini va JDKda qanday ishlatilishini ko'rib chiqishni taklif qilaman. Tabiiyki, u yoki bu shakldagi barcha asosiy naqshlar bizni uzoq vaqt davomida o'rab olgan. Keling, ularni ushbu sharhda ko'rib chiqaylik.
Java-da dizayn naqshlari - 1
Tarkib:

Shablonlar

Bo'sh ish o'rinlaridagi eng keng tarqalgan talablardan biri bu "Naqshlarni bilish". Avvalo, oddiy savolga javob berishga arziydi - "Dizayn namunasi nima?" Pattern ingliz tilidan "shablon" deb tarjima qilingan. Ya'ni, bu ma'lum bir naqsh bo'lib, unga ko'ra biz biror narsa qilamiz. Dasturlashda ham xuddi shunday. Umumiy muammolarni hal qilish uchun ba'zi o'rnatilgan eng yaxshi amaliyotlar va yondashuvlar mavjud. Har bir dasturchi arxitektordir. Hatto bir nechta sinflarni yoki hatto bittasini yaratganingizda ham, o'zgaruvchan talablar ostida kod qancha vaqt saqlanib qolishi, boshqalar tomonidan foydalanish qanchalik qulayligi sizga bog'liq. Bu erda shablonlarni bilish yordam beradi, chunki... Bu sizga kodni qayta yozmasdan qanday qilib eng yaxshi yozishni tezda tushunish imkonini beradi. Ma'lumki, dasturchilar dangasa odamlardir va uni bir necha marta takrorlashdan ko'ra darhol yaxshi yozish osonroq) Naqshlar ham algoritmlarga o'xshab ko'rinishi mumkin. Lekin ularning farqi bor. Algoritm kerakli harakatlarni tavsiflovchi aniq bosqichlardan iborat. Naqshlar faqat yondashuvni tavsiflaydi, lekin amalga oshirish bosqichlarini tasvirlamaydi. Naqshlar har xil, chunki... turli muammolarni hal qilish. Odatda quyidagi toifalar ajratiladi:
  • Generativ

    Ushbu naqshlar ob'ekt yaratishni moslashuvchan qilish muammosini hal qiladi

  • Strukturaviy

    Ushbu naqshlar ob'ektlar orasidagi aloqalarni samarali o'rnatish muammosini hal qiladi

  • Xulq-atvor

    Ushbu naqshlar ob'ektlar orasidagi samarali o'zaro ta'sir muammosini hal qiladi

Misollarni ko'rib chiqish uchun repl.it onlayn kod kompilyatoridan foydalanishni taklif qilaman.
Java-da dizayn naqshlari - 2

Yaratilish naqshlari

Keling, ob'ektlarning hayot aylanishining boshidan - ob'ektlarni yaratishdan boshlaylik. Generativ shablonlar ob'ektlarni yanada qulayroq yaratishga yordam beradi va bu jarayonda moslashuvchanlikni ta'minlaydi. Eng mashhurlaridan biri " Quruvchi ". Ushbu naqsh murakkab ob'ektlarni bosqichma-bosqich yaratishga imkon beradi. Java-da eng mashhur misol 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());
  }
}
Ob'ektni yaratishning yana bir mashhur usuli - bu yaratishni alohida usulga o'tkazish. Bu usul, xuddi ob'ekt zavodiga aylanadi. Shuning uchun naqsh " Zavod usuli" deb nomlanadi. Masalan, Java-da uning ta'sirini sinfda ko'rish mumkin java.util.Calendar. Sinfning o'zi Calendarmavhum va uni yaratish uchun quyidagi usul qo'llaniladi 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());
  }
}
Buning sababi ko'pincha ob'ektni yaratish mantiqi murakkab bo'lishi mumkin. Masalan, yuqoridagi holatda biz asosiy sinfga kiramiz Calendarva sinf yaratiladi GregorianCalendar. Agar biz konstruktorga qarasak, sharoitga qarab turli xil ilovalar yaratilganligini ko'rishimiz mumkin Calendar. Ammo ba'zida bitta zavod usuli etarli emas. Ba'zan siz bir-biriga mos keladigan turli xil ob'ektlarni yaratishingiz kerak. Bunda bizga yana bir shablon yordam beradi - “ Abstrakt zavod ”. Va keyin biz bir joyda turli zavodlar yaratishimiz kerak. Shu bilan birga, afzallik shundaki, amalga oshirish tafsilotlari biz uchun muhim emas, ya'ni. qaysi aniq zavodni olishimiz muhim emas. Asosiysi, u to'g'ri amalga oshirishni yaratadi. Super misol:
Java-da dizayn naqshlari - 3
Ya'ni, atrof-muhitga (operatsion tizim) qarab, biz mos elementlarni yaratadigan ma'lum bir zavodni olamiz. Boshqa birov orqali yaratish yondashuviga muqobil sifatida biz " Prototip " naqshidan foydalanishimiz mumkin. Uning mohiyati oddiy - yangi ob'ektlar allaqachon mavjud ob'ektlarning tasviri va o'xshashligida yaratiladi, ya'ni. ularning prototipiga ko'ra. Java-da hamma bu naqshga duch keldi - bu interfeysdan foydalanish 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
    }
  }
}
Ko'rib turganingizdek, qo'ng'iroq qiluvchi qanday qilib clone. Ya'ni, prototip asosida ob'ekt yaratish ob'ektning o'zi uchun javobgardir. Bu foydali, chunki u foydalanuvchini shablon ob'ektini amalga oshirishga bog'lamaydi. Xo'sh, ushbu ro'yxatdagi eng oxirgisi "Singleton" naqshidir. Uning maqsadi oddiy - butun dastur uchun ob'ektning bitta nusxasini taqdim etish. Ushbu naqsh qiziqarli, chunki u ko'pincha ko'p qirrali muammolarni ko'rsatadi. Batafsilroq ma'lumot olish uchun ushbu maqolalarni ko'rib chiqing:
Java-da dizayn naqshlari - 4

Strukturaviy naqshlar

Ob'ektlarning yaratilishi bilan aniqroq bo'ldi. Endi strukturaviy naqshlarni ko'rib chiqish vaqti keldi. Ularning maqsadi oson qo'llab-quvvatlanadigan sinf ierarxiyasini va ularning munosabatlarini qurishdir. Birinchi va taniqli naqshlardan biri bu " Deputat " (proksi). Proksi-server haqiqiy ob'ekt bilan bir xil interfeysga ega, shuning uchun mijozning proksi-server orqali yoki to'g'ridan-to'g'ri ishlashi hech qanday farq qilmaydi. Eng oddiy misol 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"));
  }
}
Ko'rib turganingizdek, misolda bizda original bor - bu HashMapinterfeysni amalga oshiradigan Map. HashMapKeyinchalik , mijoz qismi uchun asl proksi-serverni yaratamiz , u putva usullarini chaqiradi getva qo'ng'iroq paytida o'z mantiqimizni qo'shadi. Ko'rib turganimizdek, naqshdagi o'zaro ta'sir interfeyslar orqali sodir bo'ladi. Ammo ba'zida uning o'rnini bosadigan narsa etarli emas. Va keyin " Dekorator " naqshidan foydalanish mumkin. Dekorator, shuningdek, o'rash yoki o'rash deyiladi. Proksi va dekorativ juda o'xshash, ammo misolga qarasangiz, farqni ko'rasiz:
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);
  }
}
Proksi-serverdan farqli o'laroq, dekorator kirish sifatida uzatiladigan narsa atrofiga o'raladi. Proksi-server proksi-server kerak bo'lgan narsani qabul qilishi va proksilangan ob'ektning ishlash muddatini boshqarishi mumkin (masalan, proksilangan ob'ekt yaratish). Yana bir qiziqarli naqsh mavjud - " Adapter ". Bu dekoratorga o'xshaydi - dekorator kirish sifatida bitta ob'ektni oladi va bu ob'ektning ustiga o'ramni qaytaradi. Farqi shundaki, maqsad funksionallikni o'zgartirish emas, balki bir interfeysni boshqasiga moslashtirishdir. Java-da bunga juda aniq misol bor:
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));
  }
}
Kirishda bizda massiv bor. Keyinchalik, massivni interfeysga olib keladigan adapter yaratamiz List. U bilan ishlashda biz aslida massiv bilan ishlaymiz. Shuning uchun elementlarni qo'shish ishlamaydi, chunki ... Asl massivni o'zgartirib bo'lmaydi. Va bu holda biz olamiz UnsupportedOperationException. Sinf tuzilishini rivojlantirishning navbatdagi qiziqarli yondashuvi kompozitsion naqshdir . Qizig'i shundaki, bitta interfeysdan foydalangan holda ma'lum elementlar to'plami ma'lum bir daraxtga o'xshash ierarxiyada joylashtirilgan. Asosiy elementdagi usulni chaqirish orqali biz barcha zarur bo'lgan yordamchi elementlarda ushbu usulga qo'ng'iroq qilamiz. Ushbu naqshning asosiy namunasi UI (java.awt yoki JSF bo'lsin):
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());
  }
}
Ko'rib turganimizdek, biz konteynerga komponent qo'shdik. Va keyin biz konteynerdan komponentlarning yangi yo'nalishini qo'llashni so'radik. Va konteyner qanday komponentlardan iboratligini bilib, ushbu buyruqni bajarishni barcha yordamchi komponentlarga topshirdi. Yana bir qiziqarli naqsh " Ko'prik " naqshidir. Bu ikki xil sinf ierarxiyasi o'rtasidagi bog'lanish yoki ko'prikni tasvirlagani uchun shunday nomlanadi. Ushbu ierarxiyalardan biri abstraksiya, ikkinchisi esa amalga oshirish hisoblanadi. Bu ta'kidlangan, chunki abstraktsiyaning o'zi amallarni bajarmaydi, lekin bu bajarishni amalga oshirishga topshiradi. Ushbu naqsh ko'pincha "nazorat" sinflari va bir necha turdagi "platforma" sinflari (masalan, Windows, Linux va boshqalar) mavjud bo'lganda qo'llaniladi. Ushbu yondashuv bilan ushbu ierarxiyalardan biri (abstraksiya) boshqa ierarxiya (amalga oshirish) ob'ektlariga havola oladi va ularga asosiy ishni topshiradi. Barcha ilovalar umumiy interfeysga amal qilganligi sababli ularni abstraksiya doirasida almashtirish mumkin. Java-da bunga aniq misol java.awt:
Java-da dizayn naqshlari - 5
Qo'shimcha ma'lumot uchun " Java AWT-dagi naqshlar " maqolasiga qarang . Strukturaviy naqshlar orasida men " Fasad " naqshini ham ta'kidlashni istardim . Uning mohiyati qulay va ixcham interfeys orqasida ushbu API orqasida kutubxonalar/ramkalardan foydalanishning murakkabligini yashirishdir. Masalan, JPA-dan JSF yoki EntityManager-dan foydalanishingiz mumkin. Bundan tashqari, " Flyweight " deb nomlangan yana bir naqsh mavjud . Uning mohiyati shundaki, agar turli ob'ektlar bir xil holatga ega bo'lsa, u holda uni umumlashtirish va har bir ob'ektda emas, balki bir joyda saqlash mumkin. Va keyin har bir ob'ekt umumiy qismga murojaat qilish imkoniyatiga ega bo'ladi, bu esa saqlash uchun xotira xarajatlarini kamaytiradi. Ushbu naqsh ko'pincha oldindan keshlash yoki ob'ektlar hovuzini saqlashni o'z ichiga oladi. Qizig'i shundaki, biz bu naqshni ham boshidan bilamiz:
Java-da dizayn naqshlari - 6
Xuddi shu o'xshashlik bo'yicha, bu erda qatorlar hovuzini kiritish mumkin. Ushbu mavzu bo'yicha maqolani o'qishingiz mumkin: " Flyweight Design Pattern ".
Java-da dizayn naqshlari - 7

Xulq-atvor namunalari

Shunday qilib, biz ob'ektlarni qanday yaratish mumkinligini va sinflar o'rtasidagi aloqalarni qanday tashkil qilish mumkinligini aniqladik. Qolgan eng qiziqarli narsa - ob'ektlarning xatti-harakatlarini o'zgartirishda moslashuvchanlikni ta'minlash. Bunda bizga xulq-atvor namunalari yordam beradi. Eng tez-tez tilga olingan naqshlardan biri bu " Strategiya " naqshidir. Bu erda " Birinchi bosh. Dizayn naqshlari " kitobidagi naqshlarni o'rganish boshlanadi. "Strategiya" naqshidan foydalanib, biz ob'ekt ichida harakatni qanday bajarishimizni saqlashimiz mumkin, ya'ni. ichidagi ob'ekt kodni bajarish paytida o'zgartirilishi mumkin bo'lgan strategiyani saqlaydi. Bu taqqoslash vositasidan foydalanganda biz tez-tez ishlatadigan namunadir:
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);
  }
}
Bizdan oldin - TreeSet. TreeSetU elementlarning tartibini saqlash xatti-harakatiga ega , ya'ni. ularni saralaydi (chunki u SortedSet). Ushbu xatti-harakatlarning standart strategiyasi mavjud, biz uni JavaDoc da ko'ramiz: "tabiiy tartibda" saralash (satrlar uchun bu leksikografik tartib). Bu parametrsiz konstruktordan foydalansangiz sodir bo'ladi. Ammo strategiyani o'zgartirmoqchi bo'lsak, o'tishimiz mumkin Comparator. Ushbu misolda biz o'z to'plamimizni sifatida yaratishimiz mumkin new TreeSet(comparator), keyin elementlarni saqlash tartibi (saqlash strategiyasi) taqqoslagichda ko'rsatilganiga o'zgaradi. Qizig'i shundaki, " Davlat " deb nomlangan deyarli bir xil naqsh mavjud . “Davlat” naqshida aytilishicha, agar biz asosiy ob'ektda ushbu ob'ektning holatiga bog'liq bo'lgan ba'zi xatti-harakatlarga ega bo'lsak, u holda biz holatning o'zini ob'ekt sifatida tasvirlashimiz va holat ob'ektini o'zgartirishimiz mumkin. Va asosiy ob'ektdan qo'ng'iroqlarni davlatga topshiring. Java tilining asoslarini o'rganishda bizga ma'lum bo'lgan yana bir naqsh " Buyruq " naqshidir. Ushbu dizayn namunasi turli xil buyruqlar turli sinflar sifatida taqdim etilishi mumkinligini ko'rsatadi. Ushbu naqsh Strategiya naqshiga juda o'xshaydi. Ammo Strategiya namunasida biz muayyan harakat qanday bajarilishini qayta belgilagan edik (masalan, TreeSet. "Buyruq" naqshida biz qanday harakat bajarilishini qayta belgilaymiz. Biz iplardan foydalanganda har kuni naqsh buyrug'i biz bilan birga bo'ladi:
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();
  }
}
Ko'rib turganingizdek, buyruq yangi ish zarrachasida bajariladigan amal yoki buyruqni belgilaydi. Shuningdek, " Mas'uliyat zanjiri" naqshini ko'rib chiqishga arziydi . Ushbu naqsh ham juda oddiy. Ushbu naqsh, agar biror narsani qayta ishlash kerak bo'lsa, unda siz ishlov beruvchilarni zanjirda to'plashingiz mumkinligini aytadi. Misol uchun, bu naqsh ko'pincha veb-serverlarda qo'llaniladi. Kirishda server foydalanuvchidan ba'zi so'rovlarga ega. Keyin bu so'rov qayta ishlash zanjiri orqali o'tadi. Ushbu ishlovchilar zanjiri filtrlarni (masalan, IP manzillarning qora ro'yxatidan so'rovlarni qabul qilmaslik), autentifikatsiya ishlov beruvchilarini (faqat avtorizatsiya qilingan foydalanuvchilarga ruxsat berish), so'rov sarlavhasini qayta ishlashni, keshlash ishlovchisini va boshqalarni o'z ichiga oladi. Ammo Java-da oddiyroq va tushunarli misol bor 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");
  }
}
Ko'rib turganingizdek, ishlov beruvchilar logger ishlov beruvchilar ro'yxatiga qo'shilgan. logger.getHandlersRo'yxatga oluvchi qayta ishlash uchun xabar olganida, har bir bunday xabar ushbu logger uchun ishlov beruvchilar zanjiri (dan) orqali o'tadi . Biz har kuni ko'radigan yana bir naqsh bu " Iterator ". ListUning mohiyati ob'ektlar to'plamini (ya'ni, ma'lumotlar tuzilmasini ifodalovchi sinf. Masalan, ) va ushbu to'plamning o'tishini ajratishdir .
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());
    }
  }
}
Ko'rib turganingizdek, iterator to'plamning bir qismi emas, balki to'plamni kesib o'tuvchi alohida sinf bilan ifodalanadi. Iterator foydalanuvchisi u qaysi to'plamni takrorlayotganini ham bilmasligi mumkin, ya'ni. u qaysi kollektsiyaga tashrif buyuradi? Tashrifchi namunasi ham e'tiborga loyiqdir . Tashrifchi namunasi iterator naqshiga juda o'xshaydi. Ushbu naqsh ob'ektlar tuzilishini chetlab o'tishga va ushbu ob'ektlar ustida amallarni bajarishga yordam beradi. Ular kontseptsiyada ancha farq qiladi. Iterator to'plam bo'ylab o'tadi, shunda iteratordan foydalanayotgan mijoz to'plam ichida nima ekanligiga ahamiyat bermaydi, faqat ketma-ketlikdagi elementlar muhim. Mehmon degani, biz tashrif buyuradigan ob'ektlarning ma'lum bir ierarxiyasi yoki tuzilishi mavjudligini anglatadi. Masalan, alohida kataloglarni qayta ishlash va alohida fayllarni qayta ishlashdan foydalanishimiz mumkin. Java-da ushbu naqshni quyidagi shaklda amalga oshirish mavjud 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
    }
  }
}
Ba'zida ba'zi ob'ektlar boshqa ob'ektlardagi o'zgarishlarga reaksiyaga kirishishi kerak, keyin esa "Kuzatuvchi" naqsh bizga yordam beradi . Eng qulay usul - ba'zi ob'ektlarga boshqa ob'ektlarda sodir bo'layotgan hodisalarni kuzatish va ularga javob berish imkonini beruvchi obuna mexanizmini taqdim etishdir. Ushbu naqsh ko'pincha turli hodisalarga munosabat bildiradigan turli tinglovchilar va kuzatuvchilarda qo'llaniladi. Oddiy misol sifatida, JDK ning birinchi versiyasidan ushbu naqshning amalga oshirilishini eslashimiz mumkin:
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!");
  }
}
Yana bir foydali xulq-atvor namunasi mavjud - " Mediator ". Bu foydali, chunki murakkab tizimlarda u turli ob'ektlar orasidagi aloqani olib tashlashga yordam beradi va ob'ektlar orasidagi barcha o'zaro ta'sirlarni vositachi bo'lgan ba'zi bir ob'ektga topshirishga yordam beradi. Ushbu naqshning eng ajoyib ilovalaridan biri bu naqshdan foydalanadigan Spring MVC. Bu haqda ko'proq ma'lumotni bu erda o'qishingiz mumkin: " Bahor: vositachi namunasi ". Ko'pincha xuddi shunday misollarda ko'rishingiz mumkin 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);
  }
}
Misol ko'proq buyruq naqshiga o'xshaydi. Va "O'rta vositachi" naqshining mohiyati "a" ni amalga oshirishda yashiringan Timer. Taymer ichida vazifa navbati TaskQueue, ip bor TimerThread. Biz, ushbu sinfning mijozlari sifatida, ular bilan o'zaro aloqada emasmiz, balki Timeruning usullariga chaqiruvimizga javoban, vositachi bo'lgan boshqa ob'ektlarning usullariga kiradigan ob'ekt bilan o'zaro aloqadamiz. Tashqi tomondan, u "Fasad" ga juda o'xshash bo'lishi mumkin. Ammo farq shundaki, Fasad ishlatilganda, komponentlar jabhaning mavjudligini bilishmaydi va bir-biri bilan gaplashadilar. Va "Mediator" dan foydalanilganda, komponentlar vositachini bilishadi va foydalanadilar, lekin bir-biri bilan bevosita aloqa qilmaydi. “ Shablon usuli ” naqshini ko'rib chiqishga arziydi Naqsh uning nomidan aniq. Xulosa shuki, kod shunday yozilganki, koddan foydalanuvchilarga (ishlab chiquvchilarga) qandaydir algoritm shablonlari taqdim etiladi, uning qadamlarini qayta belgilashga ruxsat beriladi. Bu kod foydalanuvchilariga butun algoritmni yozish emas, balki faqat ushbu algoritmning u yoki bu bosqichini qanday qilib to'g'ri bajarish haqida o'ylash imkonini beradi. Misol uchun, Java-da AbstractListiteratorning xatti-harakatlarini belgilaydigan mavhum sinf mavjud List. Biroq, iteratorning o'zi quyidagi kabi barg usullaridan foydalanadi: get, set, remove. Ushbu usullarning xatti-harakati avlodlarning ishlab chiquvchisi tomonidan belgilanadi AbstractList. Shunday qilib, iterator AbstractList- bu varaq ustida takrorlash algoritmi uchun shablondir. Muayyan ilovalarni ishlab chiquvchilar esa, AbstractListaniq qadamlarning xatti-harakatlarini belgilash orqali ushbu iteratsiyaning xatti-harakatlarini o'zgartiradilar. Biz tahlil qiladigan naqshlarning oxirgisi " Snapshot " (Momento) naqshidir. Uning mohiyati ob'ektning ma'lum bir holatini ushbu holatni tiklash qobiliyati bilan saqlab qolishdir. JDK dan eng taniqli misol ob'ektni ketma-ketlashtirishdir, ya'ni. java.io.Serializable. Keling, bir misolni ko'rib chiqaylik:
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
    }
  }
}
Java-da dizayn naqshlari - 8

Xulosa

Ko'rib chiqqanimizdek, juda ko'p turli xil naqshlar mavjud. Ularning har biri o'z muammosini hal qiladi. Va bu naqshlarni bilish tizimingizni moslashuvchan, barqaror va o'zgarishlarga chidamli bo'lishi uchun qanday yozishni o'z vaqtida tushunishga yordam beradi. Va nihoyat, chuqurroq sho'ng'in uchun ba'zi havolalar: #Viacheslav
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION