Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mari bercakap secara mendalam tentang "Model Rantaian Tanggungjawab", alat corak reka bentuk yang berkuasa (dengan proses pelaksanaan go)

Mari bercakap secara mendalam tentang "Model Rantaian Tanggungjawab", alat corak reka bentuk yang berkuasa (dengan proses pelaksanaan go)

藏色散人
藏色散人ke hadapan
2023-01-17 11:43:371636semak imbas

Artikel ini membawakan anda pengetahuan yang berkaitan tentang corak reka bentuk golang terutamanya memperkenalkan corak rantaian tanggungjawab dan nilainya, serta kaedah pelaksanaan khusus kod Golang. Semoga dapat membantu mereka yang memerlukan.

Hari ini saya akan terus mengemas kini artikel yang berkaitan dengan corak reka bentuk Dalam dua artikel sebelum ini mengenai corak templat dan corak strategi, saya memberitahu anda tentang "teori ganas" yang saya rumuskan: "Templat, strategi dan. Tiga corak reka bentuk rantaian tanggungjawab adalah alat yang berkuasa untuk menyelesaikan titik kesakitan proses sistem perniagaan yang kompleks dan boleh diubah ". Dalam artikel ini, mari bercakap tentang alat corak reka bentuk ketiga—corak rantai tanggungjawab.

Model rantaian tanggungjawab

Rantai tanggungjawab - nama Inggeris Rantaian tanggungjawab kadangkala diterjemahkan ke dalam rantaian model tanggungjawab. Saya melihat bahawa terdapat lebih banyak nama di Internet yang dipanggil rantaian tanggungjawab, tetapi di sini semua orang tahu bahawa mereka adalah perkara yang sama.

Ia ialah corak reka bentuk tingkah laku. Menggunakan corak ini, kita boleh membuat pautan yang terdiri daripada berbilang pemproses untuk permintaan Setiap pemproses bertanggungjawab untuk tanggungjawabnya sendiri dan tidak digabungkan antara satu sama lain Selepas menyelesaikan tugasnya sendiri, objek permintaan dihantar ke yang seterusnya dalam pautan pemproses untuk pemprosesan.

Rantai tanggungjawab digunakan dalam banyak komponen Rangka Kerja yang popular seperti perisian tengah dan pemintas semuanya menggunakan corak reka bentuk ini dengan lebih kerap. Apabila membangunkan antara muka Web, operasi biasa projek yang serupa seperti merakam log akses, menghurai Token, dan memformatkan struktur bersatu tindak balas antara muka semuanya diselesaikan dalam perisian tengah dan pemintas, supaya operasi asas ini boleh disepadukan dengan antara muka Logik perniagaan dipisahkan.

Komponen perisian tengah dan pemintas direka untuk kami mengikut rangka kerja dan boleh dimasukkan terus ke dalamnya. Perkara yang akan kami bincangkan dalam artikel hari ini ialah cara menerapkan rantaian tanggungjawab pada proses perniagaan teras kami reka bentuk, bukannya hanya melakukan operasi awam asas tersebut.

Nilai rantaian tanggungjawab

Di atas kita bercakap tentang beberapa aplikasi rantaian tanggungjawab dalam komponen awam daripada projek itu, mari Kita boleh menambah beberapa fungsi biasa asas pada pra dan pasca proses logik teras. Tetapi sebenarnya, dalam sesetengah perniagaan teras, menerapkan model rantaian tanggungjawab boleh membolehkan kami mengembangkan langkah-langkah proses perniagaan tanpa rasa sakit .

Sebagai contoh, semasa Taobao mula ditubuhkan, proses pemprosesan pesanan beli-belah mungkin seperti ini pada mulanya.

Mari bercakap secara mendalam tentang Model Rantaian Tanggungjawab, alat corak reka bentuk yang berkuasa (dengan proses pelaksanaan go)

Model Rantaian Tanggungjawab—Pesanan Beli-belah—Versi Tulen

Seluruh prosesnya agak bersih“Pengesahan parameter pengguna – Pengesahan data troli beli-belah – Pengesahan inventori produk – pengiraan tambang – potongan inventori – penjanaan pesanan” , mari kita panggil versi tulen proses pesanan beli-belah Ini biasanya apabila produk pergi dari 0 hingga 1. Proses ini agak tulen dan dalam talian membeli-belah, anda hanya boleh memilih produk, membuat pesanan dan membayar dalam talian.

Tetapi kami semua veteran melayari Internet, dan kami semua sudah biasa dengannya Jika proses ini kekal begitu murni, PM dan operasi syarikat boleh pergi. Selepas laman web beli-belah berjalan dan ada pengguna, untuk meningkatkan jualan, beberapa kaedah promosi seperti diskaun penuh untuk kategori barangan tertentu biasanya akan ditambah.

Operasi tidak boleh melahu sama ada Bercakap lebih lanjut tentang pelanggan, buat festival beli-belah dan aturkan kupon untuk menarik lebih ramai pengguna. Dengan cara ini, semasa proses membuat pesanan, adalah perlu untuk menentukan sama ada produk dalam troli beli-belah memenuhi syarat diskaun, sama ada pengguna mempunyai kupon, dan jika ya, jumlahnya boleh dikurangkan atau dikurangkan. Ia bersamaan dengan menambah dua sub-proses di tengah-tengah proses pesanan dalaman kami.

Mari bercakap secara mendalam tentang Model Rantaian Tanggungjawab, alat corak reka bentuk yang berkuasa (dengan proses pelaksanaan go)

Model Rantaian Tanggungjawab - Pesanan Membeli-belah - Versi Berpengalaman

Untuk melaksanakan logik yang baru ditambah, kita perlu sekurang-kurangnya menambah yang berikut pada proses pesanan bertulis Menambah dua cabang jika lain boleh menambah dua logik ini. Tetapi perkara yang paling dahsyat adalah kerana keseluruhan proses digabungkan bersama, selepas pengubahsuaian, kami perlu menguji keseluruhan proses . Dan dengan pengalaman di atas, kita juga harus tahu bahawa proses ini pasti akan diperluaskan pada masa hadapan. anda perlu mengubah suai langkah yang telah ditulis Adakah anda takut dengan kod tersebut?

Sesetengah rakan mungkin mengatakan bahawa proses membeli-belah e-dagang Internet mungkin agak pelbagai, dan proses setiap syarikat adalah berbeza. Kita ambil satu lagi contoh pesakit pergi ke hospital untuk berjumpa doktor Langkah asas untuk pesakit berjumpa doktor ialah:

Pendaftaran—>Berjumpa doktor di klinik—> Membayar di pejabat caj—>Mendapatkan ubat di farmasi

Walau bagaimanapun, mungkin terdapat pesakit yang memerlukan ujian makmal, filem, dll. Proses rawatan perubatan mereka di hospital mungkin seperti berikut:

Pendaftaran—> Radiografi di jabatan pengimejan—> ;Bilik pemeriksaan semula—>Bayaran di pejabat caj—>Ambil ubat di farmasi

Jadi proses rawatan perubatan juga akan mempunyai lebih banyak langkah bergantung pada keadaan pesakit.

Kini kami boleh mengesahkan: Jika langkah-langkah proses tidak ditetapkan, untuk menambah langkah-langkah kepada proses tanpa mengubah suai proses asal yang dibangunkan dan diuji, kami perlu membuat keseluruhan proses Menyahgandingkan pelbagai langkah untuk meningkatkan kebolehskalaan proses Dalam kes ini, model rantaian tanggungjawab boleh digunakan Model ini membolehkan kita menetapkan langkah-langkah dalam pautan proses dahulu dan kemudian melaksanakan .

Menggunakan model rantaian tanggungjawab untuk melaksanakan proses

Jika kami diminta untuk mereka bentuk rantaian tanggungjawab , bagaimana kita harus mereka bentuknya? Apakah kaedah yang perlu disediakan dan dilaksanakan? Bagaimana untuk menggunakannya untuk menyusun langkah-langkah dalam proses? Di sini kami menggunakan model rantaian tanggungjawab untuk melaksanakan langkah-langkah proses dalam senario berjumpa doktor untuk memberi anda demonstrasi Proses membeli-belah dan membuat pesanan adalah serupa daripada model rantaian tanggungjawab dan buat beberapa contoh Mock Setelah anda menguasainya, anda boleh cuba menggunakannya untuk menyelesaikan masalah perniagaan.

Pertama sekali, kita boleh memikirkan titik kesakitan pengembangan proses di atas Setiap langkah dalam proses harus diselesaikan oleh objek pemprosesan untuk melengkapkan abstraksi logik memproses logik mereka sendiri Kedua, mereka juga harus mengekalkan rujukan kepada objek pemprosesan seterusnya Selepas logik langkah semasa diproses, kaedah pemprosesan objek seterusnya dipanggil, dan permintaan diserahkan kepada objek seterusnya untuk diproses. , dan proses berjalan mengikut urutan sehingga akhir proses.

Ringkasnya, objek yang melaksanakan corak rantaian tanggungjawab perlu mengandungi sekurang-kurangnya ciri berikut:

  • Atribut ahli
    • nextHandler: Seterusnya objek menunggu untuk dipanggil Instance
  • Kaedah ahli
    • SetNext: ikat tika objek seterusnya pada sifat nextHandler objek semasa; >
    • : Kemasukan logik perniagaan objek semasa, di mana setiap objek pemprosesan melaksanakan logiknya sendiri Do
    • : Bertanggungjawab untuk pemprosesan dan penghantaran permintaan pada rantaian tanggungjawab; ; ia akan memanggil objek semasa Execute , jika Do tidak kosong, panggil nextHandler; jika nextHandler.Do
disarikan ke dalam rajah kelas UML, ia akan kelihatan seperti berikut.

Mari bercakap secara mendalam tentang Model Rantaian Tanggungjawab, alat corak reka bentuk yang berkuasa (dengan proses pelaksanaan go)

mentakrifkan antara muka

untuk objek pemprosesan corak rantaian tanggungjawab, yang dilaksanakan oleh Handler – jenis objek pemprosesan tertentu. ConcreteHandler

Memerhatikan gambar di atas dan analisis ciri-ciri objek di atas, kita sebenarnya dapat melihat bahawa kedua-dua tingkah laku

dan SetNext adalah sama untuk setiap Execute, jadi kedua-duanya boleh diserahkan ke abstraksi Ia dilaksanakan mengikut jenis pemprosesan, dan setiap objek pemprosesan tertentu mewarisi jenis abstrak, yang boleh mengurangkan operasi berulang. ConcreteHandler

Jadi abstraksi dan penghalusan pola rantaian tanggungjawab boleh berkembang menjadi angka berikut:

Mari bercakap secara mendalam tentang Model Rantaian Tanggungjawab, alat corak reka bentuk yang berkuasa (dengan proses pelaksanaan go)

Setelah memahami bagaimana pola rantaian tanggungjawab harus dilaksanakan dari segi reka bentuk antara muka dan jenis Akhir sekali, kami memasuki fasa pelaksanaan kod Model rantaian tanggungjawab adalah sangat mudah untuk dilaksanakan dalam bahasa berorientasikan objek tulen Hanya terjemahkan rajah kelas UML di atas terus ke dalam antara muka dan kelas abstrak buat beberapa kelas pelaksanaan dan anda sudah selesai.

Masih agak sukar untuk menterjemah gambar rajah kelas UML di atas ke dalam kod Go. Di sini kami menyediakan contoh kod yang menggunakan Go untuk melaksanakan model rantaian tanggungjawab untuk melengkapkan proses rawatan hospital.

Pelaksanaan kod Go rantai tanggungjawab

Walaupun Go tidak menyokong warisan, kami masih boleh menggunakan gabungan jenis tanpa nama Untuk mencapai matlamat ini, contoh khusus disediakan di bawah, mengambil proses pesakit pergi ke hospital untuk rawatan perubatan sebagai contoh.

Proses khusus berjumpa doktor adalah seperti berikut:

Pendaftaran—>Berjumpa doktor di klinik—>Membayar di pejabat caj—>Mendapatkan ubat di farmasi

Kami Matlamatnya adalah untuk menggunakan model rantaian tanggungjawab untuk melaksanakan setiap langkah dalam proses ini tanpa berganding antara satu sama lain, dan untuk menyokong penambahan langkah kepada proses tersebut.

Pertama, mari kita laksanakan bahagian awam corak rantaian tanggungjawab—iaitu, antara muka corak dan kelas abstrak

type PatientHandler interface {
 Execute(*patient) error SetNext(PatientHandler) PatientHandler Do(*patient) error}// 充当抽象类型,实现公共方法,抽象方法不实现留给实现类自己实现type Next struct {
 nextHandler PatientHandler}func (n *Next) SetNext(handler PatientHandler) PatientHandler {
 n.nextHandler = handler return handler}func (n *Next) Execute(patient *patient) (err error) {
 // 调用不到外部类型的 Do 方法,所以 Next 不能实现 Do 方法
 if n.nextHandler != nil {
  if err = n.nextHandler.Do(patient); err != nil {
   return
  }

  return n.nextHandler.Execute(patient)
 }

 return}
Jenis

dalam kod di atas bertindak sebagai kelas abstrak dalam corak Perihal Ini Next jenis akan diserlahkan di sini. Next

在我们的职责链的UML图里有说明Do方法是一个抽象方法,留给具体处理请求的类来实现,所以这里Next类型充当抽象类型,只实现公共方法,抽象方法留给实现类自己实现。并且由于 Go 并不支持继承,即使Next实现了Do方法,也不能达到在父类方法中调用子类方法的效果—即在我们的例子里面用Next 类型的Execute方法调用不到外部实现类型的Do方法。

所以我们这里选择Next类型直接不实现Do方法,这也是在暗示这个类型是专门用作让实现类进行内嵌组合使用的。

接下来我们定义职责链要处理的请求,再回看一下我们的UML图,实现处理逻辑和请求传递的DoExecute方法的参数都是流程中要处理的请求。这里是医院接诊的流程,所以我们定义一个患者类作为流程的请求。

//流程中的请求类--患者type patient struct {
 Name              string
 RegistrationDone  bool
 DoctorCheckUpDone bool
 MedicineDone      bool
 PaymentDone       bool}

然后我们按照挂号—>诊室看病—>收费处缴费—>药房拿药这个流程定义四个步骤的处理类,来分别实现每个环节的逻辑。

// Reception 挂号处处理器type Reception struct {
 Next}func (r *Reception) Do(p *patient) (err error) {
 if p.RegistrationDone {
  fmt.Println("Patient registration already done")
  return
 }
 fmt.Println("Reception registering patient")
 p.RegistrationDone = true
 return}// Clinic 诊室处理器--用于医生给病人看病type Clinic struct {
 Next}func (d *Clinic) Do(p *patient) (err error) {
 if p.DoctorCheckUpDone {
  fmt.Println("Doctor checkup already done")
  return
 }
 fmt.Println("Doctor checking patient")
 p.DoctorCheckUpDone = true
 return}// Cashier 收费处处理器type Cashier struct {
 Next}func (c *Cashier) Do(p *patient) (err error) {
 if p.PaymentDone {
  fmt.Println("Payment Done")
  return
 }
 fmt.Println("Cashier getting money from patient patient")
 p.PaymentDone = true
 return}// Pharmacy 药房处理器type Pharmacy struct {
 Next}func (m *Pharmacy) Do (p *patient) (err error) {
 if p.MedicineDone {
  fmt.Println("Medicine already given to patient")
  return
 }
 fmt.Println("Pharmacy giving medicine to patient")
 p.MedicineDone = true
 return}

处理器定义好了,怎么给用他们串成患者就诊这个流程呢?

func main() {
 receptionHandler := &Reception{}
 patient := &patient{Name: "abc"}
 // 设置病人看病的链路
 receptionHandler.SetNext(&Clinic{}).SetNext(&Cashier{}).SetNext(&Pharmacy{})
  receptionHandler.Execute(patient)}

上面的链式调用看起来是不是很清爽,嘿嘿别高兴太早,这里边有个BUG— 即Reception接诊挂号这个步骤提供的逻辑没有调用到,所以我们这里再定义个StartHandler 类型,它不提供处理实现只是作为第一个Handler向下转发请求

// StartHandler 不做操作,作为第一个Handler向下转发请求type StartHandler struct {
 Next}// Do 空Handler的Dofunc (h *StartHandler) Do(c *patient) (err error) {
 // 空Handler 这里什么也不做 只是载体 do nothing...
 return}

这也是Go 语法限制,公共方法Exeute并不能像面向对象那样先调用this.Do 再调用this.nextHandler.Do 具体原因咱们上边已经解释过了,如果觉得不清楚的可以拿Java实现一遍看看区别,再琢磨一下为啥Go里边不行。

所以整个流程每个环节都能被正确执行到,应该这样把处理类串起来。

func main() {
 patientHealthHandler := StartHandler{}
 //
 patient := &patient{Name: "abc"}
 // 设置病人看病的链路
 patientHealthHandler.SetNext(&Reception{}).// 挂号
  SetNext(&Clinic{}). // 诊室看病
  SetNext(&Cashier{}). // 收费处交钱
  SetNext(&Pharmacy{}) // 药房拿药
 //还可以扩展,比如中间加入化验科化验,图像科拍片等等

 // 执行上面设置好的业务流程
 if err := patientHealthHandler.Execute(patient); err != nil {
  // 异常
  fmt.Println("Fail | Error:" + err.Error())
  return
 }
 // 成功
 fmt.Println("Success")}

总结

职责链模式所拥有的特点让流程中的每个处理节点都只需关注满足自己处理条件的请求进行处理即可,对于不感兴趣的请求,会直接转发给下一个节点对象进行处理。

另外职责链也可以设置中止条件,针对我们文中的例子就是在Execute方法里加判断,一旦满足中止后就不再继续往链路的下级节点传递请求。Gin 的中间件的abort方法就是按照这个原理实现的,同时这也是职责链跟装饰器模式的一个区别,装饰器模式无法在增强实体的过程中停止,只能执行完整个装饰链路。

后面大家可以看看针对那些可能未来经常会变的核心业务流程,可以在设计初期就考虑使用职责链来实现,减轻未来流程不停迭代时不好扩展的痛点。当然职责链也不是万能的,对于那些固定的流程显然是不适合的。咱们千万不要手里拿着锤子就看什么都是钉子,所有的设计模式一定要用在合适的地方。

既然这里提到了装饰器,那么下一期就写写装饰器吧,不对,装饰器算是代理模式的一个特殊应用,那就还是先介绍代理未来再介绍装饰器吧,这样阅读体验会更好一些。

喜欢这系列文章的朋友们还请多多关注,转发起来吧。

推荐学习:《go视频教程

Atas ialah kandungan terperinci Mari bercakap secara mendalam tentang "Model Rantaian Tanggungjawab", alat corak reka bentuk yang berkuasa (dengan proses pelaksanaan go). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:learnku.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam