Corak Reka Bentuk Tanggungjawab di Jawa

1. Pengenalan

Dalam artikel ini, kita akan melihat corak reka bentuk tingkah laku yang banyak digunakan : Rantai Tanggungjawab .

Kita dapat mencari lebih banyak corak reka bentuk dalam artikel sebelumnya.

2. Rantai Tanggungjawab

Wikipedia mendefinisikan Rantai Tanggungjawab sebagai corak reka bentuk yang terdiri dari "sumber objek perintah dan serangkaian memproses objek".

Setiap objek pemprosesan dalam rantai bertanggung jawab untuk jenis perintah tertentu, dan pemprosesan dilakukan, ia meneruskan perintah ke pemproses berikutnya dalam rantai.

Corak Rantai Tanggungjawab berguna untuk:

  • Memisahkan pengirim dan penerima arahan
  • Memilih strategi pemprosesan pada masa pemprosesan

Oleh itu, mari kita lihat contoh corak yang mudah.

3. Contoh

Kami akan menggunakan Rantai Tanggungjawab untuk membuat rangkaian untuk menangani permintaan pengesahan.

Jadi, penyedia pengesahan input akan menjadi perintah , dan setiap pemproses pengesahan akan menjadi objek pemproses yang berasingan .

Mari buat kelas asas abstrak untuk pemproses kami:

public abstract class AuthenticationProcessor { public AuthenticationProcessor nextProcessor; // standard constructors public abstract boolean isAuthorized(AuthenticationProvider authProvider); }

Seterusnya, mari buat pemproses konkrit yang memperluas AuthenticationProcessor :

public class OAuthProcessor extends AuthenticationProcessor { public OAuthProcessor(AuthenticationProcessor nextProcessor) { super(nextProcessor); } @Override public boolean isAuthorized(AuthenticationProvider authProvider) { if (authProvider instanceof OAuthTokenProvider) { return true; } else if (nextProcessor != null) { return nextProcessor.isAuthorized(authProvider); } return false; } }
public class UsernamePasswordProcessor extends AuthenticationProcessor { public UsernamePasswordProcessor(AuthenticationProcessor nextProcessor) { super(nextProcessor); } @Override public boolean isAuthorized(AuthenticationProvider authProvider) { if (authProvider instanceof UsernamePasswordProvider) { return true; } else if (nextProcessor != null) { return nextProcessor.isAuthorized(authProvider); } return false; } }

Di sini, kami membuat dua pemproses konkrit untuk permintaan kebenaran masuk kami: UsernamePasswordProcessor dan OAuthProcessor .

Untuk setiap satu, kami mengatasi kaedah isAuthorized .

Sekarang mari buat beberapa ujian:

public class ChainOfResponsibilityTest { private static AuthenticationProcessor getChainOfAuthProcessor() { AuthenticationProcessor oAuthProcessor = new OAuthProcessor(null); return new UsernamePasswordProcessor(oAuthProcessor); } @Test public void givenOAuthProvider_whenCheckingAuthorized_thenSuccess() { AuthenticationProcessor authProcessorChain = getChainOfAuthProcessor(); assertTrue(authProcessorChain.isAuthorized(new OAuthTokenProvider())); } @Test public void givenSamlProvider_whenCheckingAuthorized_thenSuccess() { AuthenticationProcessor authProcessorChain = getChainOfAuthProcessor(); assertFalse(authProcessorChain.isAuthorized(new SamlTokenProvider())); } }

Contoh di atas mewujudkan rangkaian pemproses pengesahan: UsernamePasswordProcessor -> OAuthProcessor . Dalam ujian pertama, kebenaran berjaya, dan yang lain, ia gagal.

Pertama, UsernamePasswordProcessor memeriksa untuk melihat jika pembekal pengesahan adalah contoh UsernamePasswordProvider .

Tidak menjadi input yang diharapkan, UsernamePasswordProcessor mewakilkan kepada OAuthProcessor .

Terakhir, OAuthProcessor memproses arahan. Pada ujian pertama, ada pertandingan dan ujian lulus. Pada yang kedua, tidak ada lagi pemproses dalam rantai, dan, sebagai hasilnya, ujian gagal.

4. Prinsip Pelaksanaan

Kita perlu ingat beberapa prinsip penting semasa melaksanakan Rantai Tanggungjawab:

  • Setiap pemproses dalam rangkaian akan melaksanakannya untuk memproses perintah
    • Dalam contoh kami di atas, semua pemproses mempunyai pelaksanaannya dari yang Sah
  • Setiap pemproses dalam rangkaian harus mempunyai rujukan ke pemproses seterusnya
    • Di atas, UsernamePasswordProcessor mewakilkan kepada OAuthProcessor
  • Setiap pemproses bertanggungjawab untuk mendelegasikan ke pemproses seterusnya jadi berhati-hati dengan perintah yang dijatuhkan
    • Sekali lagi dalam contoh kami, jika perintah itu adalah contoh SamlProvider maka permintaan tersebut mungkin tidak dapat diproses dan tidak akan dibenarkan
  • Pemproses tidak boleh membentuk kitaran rekursif
    • Dalam contoh kami, kami tidak mempunyai kitaran dalam rantaian kami: UsernamePasswordProcessor -> OAuthProcessor . Tetapi, jika kita secara jelas menetapkan UsernamePasswordProcessor sebagai pemproses OAuthProcessor seterusnya , maka kita akan berakhir dengan satu kitaran dalam rantaian kita : UsernamePasswordProcessor -> OAuthProcessor -> UsernamePasswordProcessor. Mengambil pemproses seterusnya dalam konstruktor dapat membantu dengan ini
  • Hanya satu pemproses dalam rantai yang menangani arahan yang diberikan
    • Dalam contoh kami, jika arahan masuk mengandungi contoh OAuthTokenProvider , maka hanya OAuthProcessor yang akan mengendalikan perintah

5. Penggunaan di Dunia Sebenar

Di dunia Jawa, kita mendapat manfaat dari Rantai Tanggungjawab setiap hari. Salah satu contoh klasik seperti Servlet Filters di Java yang membolehkan banyak filter memproses permintaan HTTP. Walaupun demikian, setiap penapis menggunakan rantai dan bukannya penapis seterusnya.

Mari lihat coretan kod di bawah untuk pemahaman yang lebih baik mengenai corak ini di Servlet Filters :

public class CustomFilter implements Filter { public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // process the request // pass the request (i.e. the command) along the filter chain chain.doFilter(request, response); } }

Seperti yang dilihat dalam kod snippet di atas, kita perlu sembah FilterChain 's doFilter Cara untuk lulus permintaan tersebut kepada pemproses seterusnya di rantai.

6. Kekurangan

Dan setelah kita melihat betapa menariknya Rantai Tanggungjawab, mari kita ingat beberapa kelemahan:

  • Selalunya, ia mudah pecah:
    • jika pemproses gagal memanggil pemproses seterusnya, arahan akan dijatuhkan
    • jika pemproses memanggil pemproses yang salah, ia boleh menyebabkan kitaran
  • Ia dapat membuat jejak timbunan dalam, yang dapat mempengaruhi prestasi
  • Ini boleh menyebabkan kod pendua di seluruh prosesor, meningkatkan penyelenggaraan

7. Kesimpulannya

Dalam artikel ini, kami membincangkan mengenai Rantai Tanggungjawab dan kekuatan dan kelemahannya dengan bantuan rangkaian untuk membenarkan permintaan pengesahan masuk.

Dan, seperti biasa, kod sumber boleh didapati di GitHub.