JavaRush /Blog Jawa /Random-JV /Pola Desain ing Jawa
Viacheslav
tingkat

Pola Desain ing Jawa

Diterbitake ing grup
Pola utawa pola desain minangka bagean sing asring diabaikan saka proyek pangembang, nggawe kode angel dijaga lan adaptasi karo syarat anyar. Aku suggest dipikir apa iku lan carane digunakake ing JDK. Alamiah, kabeh pola dhasar ing salah siji wangun utawa liyane wis watara kita kanggo dangu. Ayo padha ndeleng ing review iki.
Pola Desain ing Jawa - 1
Isi:

Cithakan

Salah sawijining syarat sing paling umum ing lowongan yaiku "Kawruh pola." Kaping pisanan, sampeyan kudu njawab pitakonan sing prasaja - "Apa Pola Desain?" Pola diterjemahake saka basa Inggris minangka "template". Yaiku, iki minangka pola tartamtu miturut sing ditindakake. Padha bener ing program. Ana sawetara praktik paling apik lan pendekatan kanggo ngrampungake masalah umum. Saben programmer minangka arsitek. Malah nalika sampeyan nggawe mung sawetara kelas utawa malah siji, iku gumantung ing sampeyan suwene kode bisa urip ing syarat ganti, carane trep kanggo digunakake dening wong liya. Lan ing kene kawruh babagan template bakal mbantu, amarga ... Iki bakal ngidini sampeyan ngerti kanthi cepet carane nulis kode sing paling apik tanpa nulis maneh. Kaya sing sampeyan ngerteni, programer minangka wong sing kesed lan luwih gampang nulis kanthi apik tinimbang mbaleni kaping pirang-pirang) Pola uga katon padha karo algoritma. Nanging padha duwe prabédan. Algoritma kasusun saka langkah-langkah tartamtu sing nggambarake tumindak sing dibutuhake. Pola mung njlèntrèhaké pendekatan, nanging ora njlèntrèhaké langkah implementasine. Pola kasebut beda-beda, amarga ... ngatasi masalah beda. Biasane, kategori ing ngisor iki dibedakake:
  • Generatif

    Pola kasebut ngrampungake masalah nggawe obyek sing fleksibel

  • Struktural

    Pola kasebut ngrampungake masalah kanthi efektif mbangun sambungan antarane obyek

  • Kelakuane

    Pola kasebut ngrampungake masalah interaksi efektif antarane obyek

Kanggo nimbang conto, aku saranake nggunakake kompiler kode online repl.it.
Pola Desain ing Jawa - 2

Pola kreasi

Ayo diwiwiti saka wiwitan siklus urip obyek - kanthi nggawe obyek. Cithakan generatif mbantu nggawe obyek luwih trep lan menehi keluwesan ing proses iki. Salah siji sing paling misuwur yaiku " Pembangun ". Pola iki ngidini sampeyan nggawe obyek sing rumit kanthi langkah-langkah. Ing Jawa, conto sing paling misuwur yaiku 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());
  }
}
Pendekatan liyane sing kondhang kanggo nggawe obyek yaiku mindhah kreasi menyang cara sing kapisah. Cara iki dadi, kaya, pabrik obyek. Mulane pola kasebut diarani " Metode Pabrik ". Ing Jawa, contone, efek bisa katon ing kelas java.util.Calendar. Kelas kasebut dhewe Calendarabstrak, lan kanggo nggawe metode kasebut digunakake 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());
  }
}
Iki asring amarga logika nggawe obyek bisa rumit. Contone, ing kasus ing ndhuwur, kita ngakses kelas dhasar Calendar, lan kelas digawe GregorianCalendar. Yen kita katon ing konstruktor, kita bisa ndeleng sing implementasine beda digawe gumantung ing kahanan Calendar. Nanging kadhangkala siji cara pabrik ora cukup. Kadhangkala sampeyan kudu nggawe obyek sing beda-beda supaya padha pas. Cithakan liyane bakal mbantu kita babagan iki - " Pabrik abstrak ". Banjur kita kudu nggawe pabrik beda ing sak panggonan. Ing wektu sing padha, kauntungan iku rincian implementasine ora penting kanggo kita, i.e. iku ora Matter kang pabrik tartamtu kita njaluk. Ingkang utama yaiku nggawe implementasine sing bener. Tuladha super:
Pola Desain ing Jawa - 3
Yaiku, gumantung saka lingkungan (sistem operasi), kita bakal nampa pabrik tartamtu sing bakal nggawe unsur sing kompatibel. Minangka alternatif kanggo pendekatan nggawe liwat wong liya, kita bisa nggunakake pola " Prototipe ". Intine prasaja - obyek anyar digawe ing gambar lan mirip obyek sing wis ana, yaiku. miturut prototipe. Ing Jawa, kabeh wong wis nemokake pola iki - iki nggunakake antarmuka 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
    }
  }
}
Nalika sampeyan bisa ndeleng, panelpon ora ngerti carane clone. Tegese, nggawe obyek adhedhasar prototipe minangka tanggung jawab obyek kasebut dhewe. Iki migunani amarga ora dasi pangguna kanggo implementasine saka obyek cithakan. Ya, sing paling pungkasan ing dhaptar iki yaiku pola "Singleton". Tujuane prasaja - kanggo nyedhiyakake conto siji obyek kanggo kabeh aplikasi. Pola iki menarik amarga asring nuduhake masalah multithreading. Kanggo tampilan sing luwih jero, priksa artikel iki:
Pola Desain ing Jawa - 4

Pola struktural

Kanthi nggawe obyek dadi luwih jelas. Saiki iki wektu kanggo ndeleng pola struktural. Tujuane yaiku mbangun hierarki kelas sing gampang didhukung lan hubungane. Salah sawijining pola pisanan lan kondhang yaiku " Wakil " (Proxy). Proxy nduweni antarmuka sing padha karo obyek nyata, mula ora ana bedane kanggo klien bisa liwat proxy utawa langsung. Conto sing paling gampang yaiku 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"));
  }
}
Kaya sing sampeyan ngerteni, ing conto kita duwe asli - iki sing HashMapngetrapake antarmuka Map. Sabanjure, kita nggawe proxy sing ngganti sing asli HashMapkanggo bagean klien, sing diarani putlan metode get, nambah logika kita dhewe sajrone nelpon. Minangka kita bisa ndeleng, interaksi ing pola dumadi liwat antarmuka. Nanging kadhangkala pengganti ora cukup. Banjur pola " Dekorator " bisa digunakake. A decorator uga disebut wrapper utawa wrapper. Proxy lan dekorator meh padha, nanging yen sampeyan ndeleng contone, sampeyan bakal weruh bedane:
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);
  }
}
Ora kaya proxy, dekorator mbungkus barang sing dilewati minangka input. Proksi bisa nampa apa sing kudu diproksi lan uga ngatur urip obyek sing diproksi (contone, nggawe obyek sing diproksi). Ana pola menarik liyane - " Adaptor ". Iku padha karo dekorator - dekorator njupuk siji obyek minangka input lan ngasilake bungkus ing obyek iki. Bentenane yaiku tujuane ora ngganti fungsi, nanging kanggo ngganti antarmuka siji menyang liyane. Jawa nduweni conto sing cetha banget babagan iki:
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));
  }
}
Ing input kita duwe array. Sabanjure, kita nggawe adaptor sing nggawa array menyang antarmuka List. Nalika nggarap, kita bener-bener nggarap array. Mulane, nambah unsur ora bakal bisa, amarga ... Larik asli ora bisa diganti. Lan ing kasus iki kita bakal entuk UnsupportedOperationException. Pendekatan menarik sabanjure kanggo ngembangake struktur kelas yaiku pola Komposit . Iku menarik amarga sawetara unsur tartamtu nggunakake siji antarmuka disusun ing hirarki wit-kaya tartamtu. Kanthi nelpon cara ing unsur tiyang sepah, kita njaluk telpon kanggo cara iki ing kabeh unsur anak perlu. Conto utama pola iki yaiku UI (kaya java.awt utawa 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());
  }
}
Minangka kita bisa ndeleng, kita wis nambah komponèn kanggo wadhah. Banjur kita takon wadhah kanggo aplikasi orientasi anyar saka komponen. Lan wadhah kasebut, ngerti komponen apa sing kalebu, delegasi eksekusi printah iki kanggo kabeh komponen anak. Pola liyane sing menarik yaiku pola " Jembatan ". Iki diarani amarga nggambarake sambungan utawa jembatan antarane rong hirarki kelas sing beda. Salah siji saka hirarki iki dianggep abstraksi lan liyane implementasine. Iki disorot amarga abstraksi dhewe ora nindakake tumindak, nanging utusan eksekusi iki kanggo implementasine. Pola iki asring digunakake nalika ana kelas "kontrol" lan sawetara jinis kelas "platform" (contone, Windows, Linux, lsp.). Kanthi pendekatan iki, salah siji saka hirarki kasebut (abstraksi) bakal nampa referensi kanggo obyek saka hirarki liyane (implementasi) lan bakal utusan karya utama kanggo wong-wong mau. Amarga kabeh implementasine bakal ngetutake antarmuka umum, bisa diijolake ing abstraksi. Ing Jawa, conto sing jelas yaiku java.awt:
Pola Desain ing Jawa - 5
Kanggo informasi luwih lengkap, deleng artikel " Pola ing Jawa AWT ". Antarane pola struktural, aku uga pengin nyathet pola " Fasad ". Intine yaiku ndhelikake kerumitan nggunakake perpustakaan / kerangka ing mburi API iki ing mburi antarmuka sing trep lan ringkes. Contone, sampeyan bisa nggunakake JSF utawa EntityManager saka JPA minangka conto. Ana uga pola liyane sing disebut " Flyweight ". Intine yaiku yen obyek sing beda duwe negara sing padha, mula bisa digeneralisasi lan disimpen ora ing saben obyek, nanging ing sak panggonan. Lan banjur saben obyek bakal bisa kanggo referensi bagean umum, kang bakal ngurangi biaya memori kanggo panyimpenan. Pola iki asring kalebu pra-caching utawa njaga blumbang obyek. Apike, kita uga ngerti pola iki wiwit wiwitan:
Pola Desain ing Jawa - 6
Kanthi analogi sing padha, blumbang senar bisa dilebokake ing kene. Sampeyan bisa maca artikel babagan topik iki: " Pola Desain Flyweight ".
Pola Desain ing Jawa - 7

Pola tingkah laku

Dadi, kita ngerti carane obyek bisa digawe lan carane sambungan antarane kelas bisa diatur. Sing paling menarik yaiku nyedhiyakake keluwesan kanggo ngganti prilaku obyek. Lan pola prilaku bakal mbantu kita. Salah sawijining pola sing paling kerep disebutake yaiku pola " Strategi ". Ing kene sinau babagan pola ing buku " Kepala Pisanan. Pola Desain "Diwiwiti. Nggunakake pola "Strategi", kita bisa nyimpen nang obyek carane kita bakal nindakake tumindak, i.e. obyek nang nyimpen strategi sing bisa diganti sak eksekusi kode. Iki minangka pola sing asring digunakake nalika nggunakake komparator:
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);
  }
}
Sadurunge kita - TreeSet. Wis prilaku TreeSetnjaga urutan unsur, i.e. diurutake (amarga iku SortedSet). Prilaku iki nduweni strategi standar, sing kita deleng ing JavaDoc: ngurutake "urutan alami" (kanggo senar, iki minangka urutan leksikografis). Iki kedadeyan yen sampeyan nggunakake konstruktor tanpa parameter. Nanging yen kita pengin ngganti strategi, kita bisa pass Comparator. Ing conto iki, kita bisa nggawe set kita minangka new TreeSet(comparator), banjur urutan nyimpen unsur (strategi panyimpenan) bakal diganti menyang sing ditemtokake ing komparator. Sing nggumunake, ana pola sing meh padha sing diarani " Negara ". Pola "Negara" nyatakake yen kita duwe sawetara prilaku ing obyek utama sing gumantung marang kahanan obyek kasebut, mula kita bisa njlèntrèhaké negara kasebut minangka obyek lan ngganti obyek negara. Lan utusan telpon saka obyek utama menyang negara. Pola liyane sing kita kenal nalika sinau babagan dhasar basa Jawa yaiku pola " Parentah ". Pola desain iki nuduhake manawa printah sing beda bisa dituduhake minangka kelas sing beda. Pola iki meh padha karo pola Strategi. Nanging ing pola Strategy, kita padha redefining carane tumindak tartamtu bakal dileksanakake (contone, ngurutake ing TreeSet). Ing pola "Command", kita nemtokake maneh tumindak sing bakal ditindakake. Printah pola ana karo kita saben dina nalika nggunakake utas:
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();
  }
}
Nalika sampeyan bisa ndeleng, printah nemtokake tumindak utawa printah sing bakal kaleksanan ing thread anyar. Sampeyan uga kudu nimbang pola " Rantai tanggung jawab ". Pola iki uga prasaja banget. Pola iki ujar manawa ana sing kudu diproses, mula sampeyan bisa ngumpulake pawang ing rantai. Contone, pola iki asring digunakake ing server web. Ing input, server duwe sawetara panjaluk saka pangguna. Panjaluk iki banjur ngliwati rantai pangolahan. Rantai panangan iki kalebu saringan (contone, ora nampa panjaluk saka dhaptar ireng alamat IP), panangan otentikasi (mung ngidini pangguna sing sah), panyuwun header panjaluk, pawang cache, lsp. Nanging ana conto sing luwih prasaja lan bisa dingerteni ing 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");
  }
}
Nalika sampeyan bisa ndeleng, Handler ditambahake menyang dhaptar panangan logger. Nalika logger nampa pesen kanggo diproses, saben pesen kasebut ngliwati rantai panangan (saka logger.getHandlers) kanggo logger kasebut. Pola liyane sing kita deleng saben dina yaiku " Iterator ". Intine yaiku misahake koleksi obyek (yaiku kelas sing makili struktur data. Contone, List) lan traversal koleksi iki.
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());
    }
  }
}
Nalika sampeyan bisa ndeleng, iterator ora bagéan saka koleksi, nanging diwakili dening kelas kapisah sing traverses koleksi. Pangguna iterator bisa uga ora ngerti koleksi apa sing lagi diulang, yaiku. koleksi apa sing dikunjungi? Perlu dipikirake pola " Pengunjung ". Pola pengunjung meh padha karo pola iterator. Pola iki mbantu sampeyan ngliwati struktur obyek lan nindakake tumindak ing obyek kasebut. Padha beda-beda ing konsep. Iterator ngliwati koleksi kasebut supaya klien sing nggunakake iterator ora peduli apa sing ana ing koleksi kasebut, mung unsur-unsur ing urutan sing penting. Pengunjung tegese ana hierarki utawa struktur tartamtu saka obyek sing kita kunjungi. Contone, kita bisa nggunakake pangolahan direktori sing kapisah lan pangolahan file sing kapisah. Jawa nduweni implementasi out-of-the-box saka pola iki ing wangun 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
    }
  }
}
Kadhangkala ana perlu kanggo sawetara obyek kanggo nanggepi owah-owahan ing obyek liyane, lan banjur pola "Observer" bakal bantuan kita . Cara sing paling trep yaiku nyedhiyakake mekanisme langganan sing ngidini sawetara obyek bisa ngawasi lan nanggapi acara sing kedadeyan ing obyek liyane. Pola iki asring digunakake ing macem-macem Pendengar lan Pengamat sing menehi reaksi marang kedadeyan sing beda-beda. Minangka conto prasaja, kita bisa ngelingi implementasine pola iki saka versi pisanan 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!");
  }
}
Ana pola prilaku liyane sing migunani - " Mediator ". Iku migunani amarga ing sistem Komplek mbantu kanggo mbusak sambungan antarane obyek beda lan utusan kabeh interaksi antarane obyek kanggo sawetara obyek, kang intermediary. Salah sawijining aplikasi sing paling nyenengake saka pola iki yaiku Spring MVC, sing nggunakake pola iki. Sampeyan bisa maca liyane babagan iki: " Spring: Pola Mediator ". Sampeyan bisa kerep ndeleng padha ing conto 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);
  }
}
Conto katon luwih kaya pola printah. Lan inti saka pola "Mediator" didhelikake ing implementasine saka Timer'a. Ing njero timer ana antrian tugas TaskQueue, ana benang TimerThread. Kita, minangka klien kelas iki, ora sesambungan karo wong-wong mau, nanging sesambungan karo Timerobyek kasebut, sing, kanggo nanggepi telpon kanggo metode kasebut, ngakses metode obyek liya sing dadi perantara. Eksternal bisa uga katon meh padha karo "Fasad". Nanging bedane yaiku nalika Facade digunakake, komponen ora ngerti manawa fasad kasebut ana lan ngobrol. Lan nalika "Mediator" digunakake, komponen ngerti lan nggunakake perantara, nanging ora langsung kontak saben liyane. Perlu dipikirake pola " Metode Cithakan ". Pola kasebut jelas saka jenenge. Ing ngisor iki yaiku kode kasebut ditulis kanthi cara supaya pangguna kode (pangembang) diwenehake karo sawetara cithakan algoritma, langkah-langkah sing diijini didefinisikan maneh. Iki ngidini pangguna kode ora nulis kabeh algoritma, nanging mung mikir babagan carane nindakake siji utawa langkah liyane saka algoritma iki. Contone, Jawa nduweni kelas abstrak AbstractListsing nemtokake prilaku iterator kanthi List. Nanging, iterator dhewe nggunakake cara godhong kayata: get, set, remove. Prilaku cara kasebut ditemtokake dening pangembang turunane AbstractList. Mangkono, iterator ing AbstractList- minangka cithakan kanggo algoritma kanggo iterasi liwat sheet. Lan pangembang implementasi tartamtu AbstractListngganti prilaku pengulangan iki kanthi nemtokake prilaku langkah tartamtu. Pola pungkasan sing dianalisis yaiku pola " Snapshot " (Momento). Intine yaiku kanggo njaga kahanan tartamtu saka obyek kanthi kemampuan kanggo mulihake negara kasebut. Conto sing paling bisa dingerteni saka JDK yaiku serialisasi obyek, yaiku. java.io.Serializable. Ayo ndeleng conto:
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
    }
  }
}
Pola Desain ing Jawa - 8

Kesimpulan

Kaya sing kita deleng saka review, ana macem-macem pola. Saben wong ngrampungake masalah dhewe. Lan kawruh babagan pola kasebut bisa mbantu sampeyan ngerti babagan cara nulis sistem supaya fleksibel, bisa dijaga lan tahan kanggo owah-owahan. Lan pungkasane, sawetara tautan kanggo nyilem sing luwih jero: #Viacheslav
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION