JavaRush /Blog Java /Random-MS /Corak Reka Bentuk di Jawa

Corak Reka Bentuk di Jawa

Diterbitkan dalam kumpulan
Corak atau corak reka bentuk adalah bahagian yang sering diabaikan dalam tugas pembangun, menjadikan kod sukar untuk dikekalkan dan disesuaikan dengan keperluan baharu. Saya cadangkan anda melihat apa itu dan bagaimana ia digunakan dalam JDK. Sememangnya, semua corak asas dalam satu bentuk atau yang lain telah berada di sekeliling kita untuk masa yang lama. Mari lihat mereka dalam ulasan ini.
Corak Reka Bentuk dalam Java - 1
Kandungan:

templat

Salah satu keperluan yang paling biasa dalam kekosongan ialah "Pengetahuan tentang corak." Pertama sekali, anda patut menjawab soalan mudah - "Apakah itu Corak Reka Bentuk?" Corak diterjemahkan daripada bahasa Inggeris sebagai "template". Iaitu, ini adalah corak tertentu mengikut mana kita melakukan sesuatu. Perkara yang sama berlaku dalam pengaturcaraan. Terdapat beberapa amalan terbaik dan pendekatan yang ditetapkan untuk menyelesaikan masalah biasa. Setiap pengaturcara adalah seorang arkitek. Walaupun anda membuat hanya beberapa kelas atau bahkan satu, ia bergantung kepada anda berapa lama kod itu boleh bertahan di bawah keperluan yang berubah-ubah, betapa mudahnya ia digunakan oleh orang lain. Dan di sinilah pengetahuan tentang templat akan membantu, kerana... Ini akan membolehkan anda memahami dengan cepat cara terbaik untuk menulis kod tanpa menulisnya semula. Seperti yang anda ketahui, pengaturcara adalah orang yang malas dan lebih mudah untuk menulis sesuatu dengan segera daripada membuat semula beberapa kali) Corak juga mungkin kelihatan serupa dengan algoritma. Tetapi mereka mempunyai perbezaan. Algoritma terdiri daripada langkah-langkah khusus yang menerangkan tindakan yang diperlukan. Corak hanya menerangkan pendekatan, tetapi tidak menerangkan langkah pelaksanaan. Coraknya berbeza, kerana... menyelesaikan masalah yang berbeza. Biasanya kategori berikut dibezakan:
  • Generatif

    Corak ini menyelesaikan masalah menjadikan penciptaan objek fleksibel

  • berstruktur

    Corak ini menyelesaikan masalah membina hubungan antara objek dengan berkesan

  • Tingkah laku

    Corak ini menyelesaikan masalah interaksi berkesan antara objek

Untuk mempertimbangkan contoh, saya cadangkan menggunakan pengkompil kod dalam talian repl.it.
Corak Reka Bentuk dalam Java - 2

Corak ciptaan

Mari kita mulakan dari permulaan kitaran hidup objek - dengan penciptaan objek. Templat generatif membantu mencipta objek dengan lebih mudah dan memberikan fleksibiliti dalam proses ini. Salah satu yang paling terkenal ialah " Builder ". Corak ini membolehkan anda membuat objek kompleks langkah demi langkah. Di Jawa, contoh yang paling terkenal ialah 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());
  }
}
Satu lagi pendekatan yang terkenal untuk mencipta objek ialah memindahkan ciptaan ke kaedah yang berasingan. Kaedah ini menjadi, seolah-olah, kilang objek. Itulah sebabnya corak itu dipanggil " Kaedah Kilang ". Di Jawa, sebagai contoh, kesannya boleh dilihat dalam kelas java.util.Calendar. Kelas itu sendiri Calendaradalah abstrak, dan untuk menciptanya kaedah digunakan 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());
  }
}
Ini selalunya kerana logik di sebalik penciptaan objek boleh menjadi rumit. Sebagai contoh, dalam kes di atas, kita mengakses kelas asas Calendar, dan kelas dicipta GregorianCalendar. Jika kita melihat pembina, kita dapat melihat bahawa pelaksanaan yang berbeza dicipta bergantung pada syarat Calendar. Tetapi kadang-kadang satu kaedah kilang tidak mencukupi. Kadangkala anda perlu mencipta objek yang berbeza supaya ia sesuai bersama. Templat lain akan membantu kami dengan ini - " Kilang abstrak ". Dan kemudian kita perlu membuat kilang yang berbeza di satu tempat. Pada masa yang sama, kelebihannya ialah butiran pelaksanaan tidak penting bagi kami, i.e. tidak kira kilang tertentu yang kita dapat. Perkara utama ialah ia mewujudkan pelaksanaan yang betul. Contoh hebat:
Corak Reka Bentuk dalam Java - 3
Iaitu, bergantung kepada persekitaran (sistem operasi), kita akan mendapat kilang tertentu yang akan mencipta elemen yang serasi. Sebagai alternatif kepada pendekatan mencipta melalui orang lain, kita boleh menggunakan corak " Prototaip ". Intipatinya adalah mudah - objek baru dicipta dalam imej dan rupa objek sedia ada, i.e. mengikut prototaip mereka. Semua orang telah menemui corak ini dalam Java - ini adalah penggunaan antara muka 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
    }
  }
}
Seperti yang anda lihat, pemanggil tidak tahu bagaimana clone. Iaitu, mencipta objek berdasarkan prototaip adalah tanggungjawab objek itu sendiri. Ini berguna kerana ia tidak mengikat pengguna dengan pelaksanaan objek templat. Nah, yang terakhir dalam senarai ini ialah corak "Singleton". Tujuannya mudah - untuk menyediakan satu contoh objek untuk keseluruhan aplikasi. Corak ini menarik kerana ia sering menunjukkan masalah multithreading. Untuk pandangan yang lebih mendalam, lihat artikel ini:
Corak Reka Bentuk dalam Java - 4

Corak struktur

Dengan penciptaan objek ia menjadi lebih jelas. Sekarang adalah masa untuk melihat corak struktur. Matlamat mereka adalah untuk membina hierarki kelas yang mudah disokong dan perhubungan mereka. Salah satu corak yang pertama dan terkenal ialah " Timbalan " (Proksi). Proksi mempunyai antara muka yang sama dengan objek sebenar, jadi tiada bezanya untuk klien bekerja melalui proksi atau secara langsung. Contoh paling mudah ialah 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"));
  }
}
Seperti yang anda lihat, dalam contoh kami mempunyai asal - ini adalah yang HashMapmelaksanakan antara muka Map. Kami seterusnya mencipta proksi yang menggantikan yang asal HashMapuntuk bahagian klien, yang memanggil putdan kaedah get, menambah logik kami sendiri semasa panggilan. Seperti yang kita lihat, interaksi dalam corak berlaku melalui antara muka. Tetapi kadangkala pengganti tidak mencukupi. Dan kemudian corak " Penghias " boleh digunakan. Penghias juga dipanggil pembalut atau pembalut. Proksi dan penghias sangat serupa, tetapi jika anda melihat contoh, anda akan melihat perbezaannya:
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);
  }
}
Tidak seperti proksi, penghias membungkus dirinya dengan sesuatu yang dihantar sebagai input. Proksi boleh menerima kedua-dua perkara yang perlu diproksi dan mengurus hayat objek yang diproksi itu sendiri (contohnya, mencipta objek yang diproksi). Terdapat satu lagi corak yang menarik - " Penyesuai ". Ia serupa dengan penghias - penghias mengambil satu objek sebagai input dan mengembalikan pembungkus ke atas objek ini. Perbezaannya ialah matlamatnya bukan untuk menukar fungsi, tetapi untuk menyesuaikan satu antara muka dengan yang lain. Java mempunyai contoh yang sangat jelas tentang ini:
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));
  }
}
Pada input kita mempunyai array. Seterusnya, kami mencipta penyesuai yang membawa tatasusunan ke antara muka List. Apabila bekerja dengannya, kami sebenarnya bekerja dengan tatasusunan. Oleh itu, menambah elemen tidak akan berfungsi, kerana... Tatasusunan asal tidak boleh diubah. Dan dalam kes ini kita akan mendapat UnsupportedOperationException. Pendekatan menarik seterusnya untuk membangunkan struktur kelas ialah corak Komposit . Adalah menarik kerana satu set elemen tertentu menggunakan satu antara muka disusun dalam hierarki seperti pokok tertentu. Dengan memanggil kaedah pada elemen induk, kami mendapat panggilan ke kaedah ini pada semua elemen anak yang diperlukan. Contoh utama corak ini ialah UI (sama ada java.awt atau 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());
  }
}
Seperti yang kita dapat lihat, kami telah menambah komponen pada bekas. Dan kemudian kami meminta bekas untuk menggunakan orientasi baharu komponen. Dan bekas itu, mengetahui komponen yang terdiri daripadanya, mewakilkan pelaksanaan arahan ini kepada semua komponen kanak-kanak. Corak lain yang menarik ialah corak " Jambatan ". Ia dipanggil ini kerana ia menerangkan sambungan atau jambatan antara dua hierarki kelas yang berbeza. Satu daripada hierarki ini dianggap sebagai abstraksi dan satu lagi pelaksanaan. Ini diserlahkan kerana abstraksi itu sendiri tidak melakukan tindakan, tetapi mewakilkan pelaksanaan ini kepada pelaksanaan. Corak ini sering digunakan apabila terdapat kelas "kawalan" dan beberapa jenis kelas "platform" (contohnya, Windows, Linux, dll.). Dengan pendekatan ini, salah satu daripada hierarki ini (abstraksi) akan menerima rujukan kepada objek hierarki lain (pelaksanaan) dan akan mewakilkan kerja utama kepada mereka. Oleh kerana semua pelaksanaan akan mengikut antara muka biasa, ia boleh ditukar ganti dalam abstraksi. Di Jawa, contoh yang jelas tentang ini ialah java.awt:
Corak Reka Bentuk dalam Java - 5
Untuk maklumat lanjut, lihat artikel " Corak dalam Java AWT ". Antara corak struktur, saya juga ingin perhatikan corak " Fasad ". Intipatinya adalah untuk menyembunyikan kerumitan penggunaan perpustakaan/rangka kerja di sebalik API ini di sebalik antara muka yang mudah dan ringkas. Sebagai contoh, anda boleh menggunakan JSF atau EntityManager daripada JPA sebagai contoh. Terdapat juga corak lain yang dipanggil " Flyweight ". Intipatinya ialah jika objek yang berbeza mempunyai keadaan yang sama, maka ia boleh digeneralisasikan dan disimpan bukan dalam setiap objek, tetapi di satu tempat. Dan kemudian setiap objek akan dapat merujuk bahagian biasa, yang akan mengurangkan kos memori untuk penyimpanan. Corak ini selalunya melibatkan pra-cache atau mengekalkan kumpulan objek. Menariknya, kami juga mengetahui corak ini dari awal lagi:
Corak Reka Bentuk dalam Java - 6
Dengan analogi yang sama, kumpulan rentetan boleh disertakan di sini. Anda boleh membaca artikel mengenai topik ini: " Corak Reka Bentuk Flyweight ".
Corak Reka Bentuk dalam Java - 7

Corak tingkah laku

Jadi, kami mengetahui cara objek boleh dibuat dan cara hubungan antara kelas boleh diatur. Perkara yang paling menarik yang tinggal adalah untuk memberikan fleksibiliti dalam mengubah tingkah laku objek. Dan corak tingkah laku akan membantu kita dengan ini. Salah satu corak yang paling kerap disebut ialah corak " Strategi ". Di sinilah kajian corak dalam buku " Head First. Design Patterns " bermula. Menggunakan corak "Strategi", kita boleh menyimpan di dalam objek bagaimana kita akan melakukan tindakan itu, i.e. objek di dalam menyimpan strategi yang boleh diubah semasa pelaksanaan kod. Ini adalah corak yang sering kami gunakan apabila menggunakan pembanding:
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);
  }
}
Sebelum kita - TreeSet. Ia mempunyai tingkah laku TreeSetmengekalkan susunan unsur, i.e. mengisih mereka (kerana ia adalah SortedSet). Tingkah laku ini mempunyai strategi lalai, yang kita lihat dalam JavaDoc: menyusun dalam "tertib semula jadi" (untuk rentetan, ini ialah susunan leksikografi). Ini berlaku jika anda menggunakan pembina tanpa parameter. Tetapi jika kita mahu menukar strategi, kita boleh lulus Comparator. Dalam contoh ini, kita boleh mencipta set kita sebagai new TreeSet(comparator), dan kemudian susunan elemen penyimpanan (strategi penyimpanan) akan berubah kepada yang ditentukan dalam pembanding. Menariknya, terdapat corak yang hampir sama yang dipanggil " State ". Corak "Negeri" mengatakan bahawa jika kita mempunyai beberapa tingkah laku dalam objek utama yang bergantung pada keadaan objek ini, maka kita boleh menggambarkan keadaan itu sendiri sebagai objek dan menukar objek keadaan. Dan mewakilkan panggilan daripada objek utama kepada negeri. Satu lagi corak yang kita ketahui daripada mempelajari asas-asas bahasa Jawa ialah corak " Perintah ". Corak reka bentuk ini menunjukkan bahawa arahan yang berbeza boleh diwakili sebagai kelas yang berbeza. Corak ini sangat serupa dengan corak Strategi. Tetapi dalam corak Strategi, kami mentakrifkan semula cara tindakan tertentu akan dilakukan (contohnya, mengisih dalam TreeSet). Dalam corak "Perintah", kami mentakrifkan semula tindakan yang akan dilakukan. Perintah corak ada bersama kami setiap hari apabila kami menggunakan benang:
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();
  }
}
Seperti yang anda lihat, arahan mentakrifkan tindakan atau arahan yang akan dilaksanakan dalam urutan baharu. Ia juga patut mempertimbangkan corak " Rantaian tanggungjawab ". Corak ini juga sangat mudah. Corak ini mengatakan bahawa jika sesuatu perlu diproses, maka anda boleh mengumpul pengendali dalam rantai. Sebagai contoh, corak ini sering digunakan dalam pelayan web. Pada input, pelayan mempunyai beberapa permintaan daripada pengguna. Permintaan ini kemudiannya melalui rantaian pemprosesan. Rangkaian pengendali ini termasuk penapis (contohnya, tidak menerima permintaan daripada senarai hitam alamat IP), pengendali pengesahan (benarkan pengguna yang dibenarkan sahaja), pengendali pengepala permintaan, pengendali caching, dsb. Tetapi terdapat contoh yang lebih mudah dan lebih mudah difahami di Jawa 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");
  }
}
Seperti yang anda lihat, Pengendali ditambahkan pada senarai pengendali pembalak. Apabila pembalak menerima mesej untuk diproses, setiap mesej tersebut melalui rangkaian pengendali (daripada logger.getHandlers) untuk pembalak itu. Corak lain yang kita lihat setiap hari ialah " Iterator ". Intipatinya adalah untuk memisahkan koleksi objek (iaitu kelas yang mewakili struktur data. Contohnya, List) dan traversal koleksi ini.
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());
    }
  }
}
Seperti yang anda lihat, iterator bukan sebahagian daripada koleksi, tetapi diwakili oleh kelas berasingan yang merentasi koleksi. Pengguna iterator mungkin tidak tahu koleksi apa yang sedang diulang, i.e. koleksi apa yang dia lawati? Patut dipertimbangkan corak " Pelawat ". Corak pelawat sangat serupa dengan corak lelaran. Corak ini membantu anda memintas struktur objek dan melakukan tindakan pada objek ini. Mereka agak berbeza dalam konsep. Iterator melintasi koleksi supaya klien yang menggunakan iterator tidak peduli dengan koleksi yang ada di dalamnya, hanya elemen dalam urutan yang penting. Pelawat bermaksud terdapat hierarki atau struktur tertentu objek yang kita lawati. Sebagai contoh, kita boleh menggunakan pemprosesan direktori berasingan dan pemprosesan fail berasingan. Java mempunyai pelaksanaan luar kotak bagi corak ini dalam bentuk 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
    }
  }
}
Kadangkala terdapat keperluan untuk beberapa objek untuk bertindak balas terhadap perubahan dalam objek lain, dan kemudian corak "Pemerhati" akan membantu kita . Cara yang paling mudah ialah menyediakan mekanisme langganan yang membolehkan sesetengah objek memantau dan bertindak balas terhadap peristiwa yang berlaku dalam objek lain. Corak ini sering digunakan dalam pelbagai Pendengar dan Pemerhati yang bertindak balas terhadap peristiwa yang berbeza. Sebagai contoh mudah, kita boleh mengingati pelaksanaan corak ini daripada versi pertama 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!");
  }
}
Terdapat satu lagi corak tingkah laku yang berguna - " Pengantara ". Ia berguna kerana dalam sistem yang kompleks ia membantu untuk mengalih keluar sambungan antara objek yang berbeza dan mewakilkan semua interaksi antara objek kepada beberapa objek, yang merupakan perantara. Salah satu aplikasi yang paling menarik bagi corak ini ialah Spring MVC, yang menggunakan corak ini. Anda boleh membaca lebih lanjut tentang ini di sini: " Spring: Corak Pengantara ". Anda sering dapat melihat perkara yang sama dalam contoh 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);
  }
}
Contoh kelihatan lebih seperti corak arahan. Dan intipati corak "Pengantara" tersembunyi dalam pelaksanaan Timer'a. Di dalam pemasa terdapat baris gilir tugas TaskQueue, terdapat benang TimerThread. Kami, sebagai pelanggan kelas ini, tidak berinteraksi dengan mereka, tetapi berinteraksi dengan Timerobjek, yang, sebagai tindak balas kepada panggilan kami kepada kaedahnya, mengakses kaedah objek lain yang mana ia adalah perantara. Secara luaran ia mungkin kelihatan sangat serupa dengan "Fasad". Tetapi perbezaannya ialah apabila Fasad digunakan, komponen tidak tahu bahawa fasad itu wujud dan bercakap antara satu sama lain. Dan apabila "Pengantara" digunakan, komponen mengetahui dan menggunakan perantara, tetapi tidak menghubungi satu sama lain secara langsung. Perlu mempertimbangkan corak " Kaedah Templat ". Corak itu jelas daripada namanya. Intinya ialah kod itu ditulis sedemikian rupa sehingga pengguna kod (pembangun) disediakan dengan beberapa templat algoritma, langkah-langkahnya dibenarkan untuk ditakrifkan semula. Ini membenarkan pengguna kod untuk tidak menulis keseluruhan algoritma, tetapi hanya memikirkan cara melaksanakan satu atau satu lagi langkah algoritma ini dengan betul. Sebagai contoh, Java mempunyai kelas abstrak AbstractListyang mentakrifkan tingkah laku iterator dengan List. Walau bagaimanapun, iterator itu sendiri menggunakan kaedah daun seperti: get, set, remove. Tingkah laku kaedah ini ditentukan oleh pembangun keturunan AbstractList. Oleh itu, iterator dalam AbstractList- ialah templat untuk algoritma untuk lelaran pada helaian. Dan pembangun pelaksanaan khusus AbstractListmengubah gelagat lelaran ini dengan mentakrifkan gelagat langkah tertentu. Corak terakhir yang kami analisis ialah corak " Syot Kilat " (Momento). Intipatinya adalah untuk mengekalkan keadaan tertentu objek dengan keupayaan untuk memulihkan keadaan ini. Contoh yang paling dikenali daripada JDK ialah pensirilan objek, i.e. java.io.Serializable. Mari lihat contoh:
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
    }
  }
}
Corak Reka Bentuk dalam Java - 8

Kesimpulan

Seperti yang kita lihat daripada ulasan, terdapat pelbagai jenis corak. Setiap daripada mereka menyelesaikan masalah sendiri. Dan mengetahui corak ini boleh membantu anda memahami tepat pada masanya cara menulis sistem anda supaya ia fleksibel, boleh diselenggara dan tahan terhadap perubahan. Dan akhirnya, beberapa pautan untuk menyelam lebih mendalam: #Viacheslav
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION