لنتحدث عن ذلك أولاً
في الآونة الأخيرة ، كنت أدرس وسيطة قاعدة بيانات MySQL المحلية مفتوحة المصدر. بعد سحب أحدث إصدار من الكود إلى Eclipse ، وبدء تشغيله ، والقيام باختبارات مختلفة وتتبع التعليمات البرمجية. عندما أرغب في إغلاقه بعد استخدامه ، أخرج فئة التوقف وأريد تشغيله. لقد وجدت أنه تم كتابة الأسطر التالية من الكود فقط في هذا الفصل ، لذلك شعرت أنني قد تأذيت كثيرًا في لحظة.
public static void main (string [] args) {system.out.println (new date () + "، server leptdown!") ؛ }عند بدء تشغيل هذا الوسيطة وتشغيله ، يتم تمكين الاستماع ، وبدأ تشغيل العديد من المواضيع ، وهناك العديد من اتصالات المقبس. ولكن لا توجد طريقة أنيقة لإيقافها. لذلك في اليأس ، لم أتمكن إلا من الذهاب إلى النقطة الحمراء الصغيرة من الكسوف وأوقفت VM بقوة.
إذا كان برنامجًا له بنية جيدة ونموذجية وبنية واضحة ، وخاصة برنامج يشبه الخادم ، فمن المهم للغاية أن يكون لديك مجموعة من آليات إدارة دورة الحياة. لا يمكن فقط إدارة دورة حياة كل وحدة ، بل يمكن أن تكون أيضًا أكثر أناقة عند بدء تشغيل البرنامج بالكامل وإيقافه دون فقدان أي موارد.
التنفيذ البسيط لآلية دورة الحياة
دورة دورة الحياة
حالة دورة الحياة للوحدة بشكل عام لها ما يلي:
حديثي الولادة-> التهيئة-> التهيئة المكتملة-> التهيئة-> التهيئة المكتملة-> التهيئة-> التهيئة-> توقف-استرداد-> استرداد-> تدمير-> تدمير-> تدمير. إذا فشل التحويل بين أي ولايات ، فسوف يدخل حالة أخرى: الفشل.
للقيام بذلك ، يمكنك استخدام فئة التعداد لتعداد هذه الحالات ، كما هو موضح أدناه:
LifecyClestate التعداد العام {new ، // newsen تهيئة ، تهيئة ، // تهيئة البدء ، بدأت ، // ابدأ في تعليق ، تعليق ، // استئناف الإيقاف المؤقت ، استئناف ، // استعادة التدمير ، دمر ،//تدمير فشل ؛//فشل}واجهة
تتطلب المعايير السلوكية المختلفة في دورة الحياة أيضًا واجهة لتحديدها ، كما هو موضح أدناه:
الواجهة العامة ilifecycle { / ** * تهيئة * * throws lifecyclexception * / public void init () rem -ecyclexception ؛ / ** * start * * throws lifecyclexception */ public void start () remrows LifeCycleException ؛ / ** * Pause * * Throws LifecyCleexception */ public void supernd () remrows LifeCycleException ؛ / ** * Recover * * throws LifecyCleexception */ public void resume () remrows LifeCycleException ؛ / ** * تدمير * * Throws LifecyCleexception */ public void Dride () يلقي LifeCycleException ؛ / ** * إضافة مستمع دورة الحياة * * param المستمع */ public void addlifecyclelistener (مستمع ilifecyclelistener) ؛ / ** * حذف مستمع دورة الحياة * * param المستمع */ public void removelifecyclelistener (ilifecyclelistener beasherer) ؛}عند حدوث انتقال ولاية دورة الحياة ، قد يحتاج المستمعون المهتمين بنوع معين من الأحداث إلى إطلاقه ، لذلك يحدد Ilifecycle أيضًا طريقتين لإضافة المستمعين وإزالتهم. هم: الفراغ العام addlifecyclelistener (مستمع ilifecyclelistener) ؛ و public void lexovelifecyclelistener (Ilifecyclelistener beasherer) ؛
يحدد المستمع أيضًا قواعده السلوكية من خلال واجهة ، كما هو موضح أدناه:
الواجهة العامة ilifecyclelistener { / *** التعامل مع أحداث دورة الحياة** @param أحداث دورة الحياة* / public void lifecyclevent (حدث LifecyClevent) ؛}يتم تمثيل أحداث دورة الحياة من خلال دورة الحياة ، كما هو موضح أدناه:
Public Class LifeCycleVent {Private LifecyClestate State ؛ دورة الحياة العامة (حالة LifecyClestate) {this.state = state ؛ } / ** * @Regurn the State * / Public LifecyClestate getState () {return state ؛ }}تنفيذ الهيكل العظمي
باستخدام واجهة Ilifecycle ، سيتم استخدام أي فئة تنفذ هذه الواجهة ككائن لإدارة دورة الحياة. يمكن أن تكون هذه الفئة خدمة استماع للمقبس ، أو يمكن أن تمثل وحدة معينة ، وما إلى ذلك. هل نحتاج فقط إلى تنفيذ Ilifecycle؟ يمكن القول ذلك ، ولكن بالنظر إلى أن كل كائن إدارة دورة الحياة سيكون له بعض السلوكيات الشائعة في مراحل مختلفة من دورة الحياة ، مثل:
وضع حالة دورة حياتك الخاصة للتحقق مما إذا كان انتقال الدولة يتوافق مع المنطق لإخطار المستمع بأن حالة دورة الحياة قد تغيرت. لذلك ، من الأهمية بمكان توفير فئة مجردة ملخصية acctionlifecycle حيث أن التنفيذ الهيكلي لـ Ilifecycle ، والذي يتجنب الكثير من الكود المكررة ويجعل البنية أكثر وضوحًا. ستنفذ هذه الفئة التجريدية جميع طرق الواجهة المحددة في Ilifecycle وإضافة طرق تجريدية مقابلة لتنفيذ الفئة الفرعية. يمكن تنفيذ AbstractLifecycle على هذا النحو:
Public Class Class AbstractLifecycle تنفذ Ilifecycle {قائمة خاصة <IlifecyCleListener> المستمعين = New CopyOnWriteArrayList <IlifecyClelistener> () ؛ / *** تمثل الحالة حالة دورة الحياة الحالية*/ حالة LifecyClestate الخاصة = LifecyClestate.new ؛ / * * see ilifecycle#init () */ Override public final void init () remscyclexception {if (state! = lifecyClestate.new) {return ؛ } setStateAndFireEvent (LifecyClestate.Initializing) ؛ حاول {init0 () ؛ } catch (throwable t) {setStateAndFireEvent (lifecyclestate.failed) ؛ if (t eastyof lifeCycleException) {throw (lifeCycleException) t ؛ } آخر {رمي New LifeCycleException (formatString ("فشل في تهيئة {0} ، خطأ msg: {1}" ، toString () ، t.getMessage ()) ، t) ؛ }} setStateAndFireEvent (LifecyClestate.Initialized) ؛ } محمية مجردة void init0 () يلقي دورة LifeCyclexception ؛ / * * see elifecycle#start () */ Override public final void start () remrows LifeCycleException {if (state == lifecyclestate.new) {init () ؛ } if (state! = lifecyclestate.initialized) {return ؛ } setStateAndFireEvent (LifecyClestate.starting) ؛ حاول {start0 () ؛ } catch (throwable t) {setStateAndFireEvent (lifecyclestate.failed) ؛ if (t eastyof lifeCycleException) {throw (lifeCycleException) t ؛ } آخر {رمي New LifeCycleException (formatString ("فشل في البدء {0} ، خطأ msg: {1}" ، toString () ، t.getMessage ()) ، t) ؛ }} setStateAndFireEvent (LifecyClestate.started) ؛ } محمي التجريد void start0 () يلقي دورة LifeCyclexception ؛ / * * see ilifecycle#sopdend () */ Override public final void supplend () remrows lifecycleexception {if (state == lifecyclestate.suspending || state == lifecyclestate.suspended) {return ؛ } if (state! = lifecyclestate.started) {return ؛ } setStateAndFireEvent (lifecyclestate.suspending) ؛ حاول {suppend0 () ؛ } catch (throwable t) {setStateAndFireEvent (lifecyclestate.failed) ؛ if (t eastyof lifeCycleException) {throw (lifeCycleException) t ؛ } آخر {رمي New LifeCycleException (formatString ("فشل في تعليق {0} ، خطأ msg: {1}" ، toString () ، t.getMessage ()) ، t) ؛ }} setStateAndFireEvent (LifecyClestate.suspended) ؛ } محمية خاضعة باطلة suppend0 () يلقي دورة الحياة ؛ / * * see ilifecycle#resume () */ Override public final void resume () remrows lifecycleexception {if (state! = lifecyclestate.suspended) {return ؛ } setStateAndFireEvent (LifecyClestate.Resuming) ؛ حاول {resume0 () ؛ } catch (throwable t) {setStateAndFireEvent (lifecyclestate.failed) ؛ if (t eastyof lifeCycleException) {throw (lifeCycleException) t ؛ } آخر {رمي New LifeCycleException (formatString ("فشل في استئناف {0} ، خطأ msg: {1}" ، toString () ، t.getMessage ()) ، t) ؛ }} setStateAndFireEvent (LifecyClestate.Resumed) ؛ } محمي خلاصة void resume0 () رمي دورة الحياة ؛ / * * see elifecycle#DRIDER () */ Override public final void dorder () rewrows lifecycleexception {if (state == lifecyclestate.destroying || state == lifecyclestate.destroyed) {return ؛ } setStateAndFireEvent (lifecyclestate.destroying) ؛ جرب {Dride0 () ؛ } catch (throwable t) {setStateAndFireEvent (lifecyclestate.failed) ؛ if (t eastyof lifeCycleException) {throw (lifeCycleException) t ؛ } آخر {رمي New LifeCycleException (formatString ("فشل في تدمير {0} ، خطأ msg: {1}" ، toString () ، t.getMessage ()) ، t) ؛ }} setStateAndFireEvent (lifecyclestate.destroyed) ؛ } محمية التجريدية void dorder0 () يلقي دورة الحياة ؛ / * * see * ilifecycle#addLifecyCleListener (Ilifecyclelistener) */ Override public void addlifecyclelistener (ilifecyclistener beasherer) {leaders.add (beather) ؛ } / * * @see * ilifecycle#removelistener (ilifecyclelistener) * / Override public void removelifecyclelistener (ilifecyclistener beasherer) {leaders.remove (beather) ؛ } private void firelifecyclevent (حدث LifecyClevent) {for (iterator <ilifecyclelistener> it = leaders.iterator () ؛ it.hasnext () ؛) المستمع. }} محمية LifecyCyclestate getState () {return state ؛ } private void setStateAndFireevent (LifecyClestate Newstate) يلقي LifeCycleException {State = NewState ؛ firelifecyclevent (New LifecycleVent (State)) ؛ } private string formatString (نمط السلسلة ، الكائن ... وسيطات) {return messageformat.format (نمط ، وسيطات) ؛ } / * * see java.lang.object#toString () * / Override public toString () {return getClass (). getSimplename () ؛ }}يمكن ملاحظة أن تنفيذ الهيكل العظمي المجردة من الطبقة التجريدية يقوم بعدة أشياء شائعة في إدارة دورة الحياة ، والتحقق مما إذا كان الانتقال بين الحالات قانونيًا (على سبيل المثال ، يجب أن يكون قبل البدء) ، وضع الحالة الداخلية ، وتشغيل المستمع المقابل.
بعد أن تنفذ الفئة التجريدية الطريقة التي تحددها Ilifecycle ، فإنه يترك طرقًا مجردة مقابلة لفصله الفرعي للتنفيذ. كما هو موضح في الكود أعلاه ، تتضمن الطرق التجريدية التي تم تركها ما يلي:
Protced Void Void init0 () يلقي دورة الحياة ؛ محمي خلاصة الفراغ start0 () يلقي دورة الحياة. محمية باطلة باطلة suckend0 () يلقي دورة الحياة. استئناف باطل مجردة محمية 10 () يلقي دورة الحياة ؛ تدمير الفراغ التجريدي المحمي 10 () يلقي دورة الحياة ؛
التنفيذ الأنيق
حتى الآن ، قمنا بتعريف الواجهة Ilifecycle ، ويقوم الهيكل العظمي بتنفيذ AbstractLifecycle ، وأضفوا آلية مستمع. يبدو أنه يمكننا البدء في كتابة فصل لروث AbstractLifecycle وإعادة كتابة الطريقة المجردة التي تحددها ، حتى الآن جيد جدًا.
ولكن قبل أن نبدأ ، نحتاج إلى النظر في العديد من القضايا الأخرى.
هل فصول التنفيذ الخاصة بنا مهتمة بجميع الأساليب المجردة؟
هل يحتاج كل تطبيق إلى تنفيذ init0 ، start0 ، supernd0 ، resume0 ، destroy0 ، Dorting0؟
هل في بعض الأحيان لا تدعم فصولنا المعيشية أو الوحدات النمطية التعليق أو الاسترداد؟
وراثي مباشرة الملخصة يعني أنه يجب تنفيذ جميع أساليبها التجريدية.
لذلك ، نحتاج أيضًا إلى تطبيق افتراضي ، و defaultlifecycle ، والسماح لها براث مجردة lefecycle ، وتنفيذ جميع الأساليب المجردة ، لكنه لا يفعل أي شيء عملي ، لا يفعل شيئًا. فقط دعونا نرث فئة التنفيذ الحقيقية فئة التنفيذ الافتراضية وتجاوز طريقة الاهتمام.
لذلك ، ولدت DefaultLifecycle:
يمتد DefaultLifecycle من الفئة العامة الملخص agrectlifecycle { / * * see ustructionLifecycle#init0 () * /override void init0 () rem -remCycleException {// do nothing} / * * seee usselifecycle#start0 () * / @ @ see abstractlifecycle#suckend0 () */ override محمية باطلة supendinternal () يلقي LifecyClexception {// لا شيء Override محمية void dorder0 () يلقي LifeCycleException {// لا شيء}} بالنسبة إلى DefaultLifecycle ، لا شيء هو مسؤوليتها.
بعد ذلك ، يمكننا كتابة فئة التنفيذ الخاصة بنا ، وروث DefaultLifecycle ، وإعادة كتابة طرق دورة الحياة هذه.
على سبيل المثال ، لدي فصل لا يحتاج إلا إلى القيام ببعض المهام أثناء التهيئة ، بدء التشغيل ، والتدمير ، حتى أتمكن من كتابته مثل هذا:
استيراد java.io.ioException ؛ استيراد java.net.serversocket ؛ استيراد java.net.socket ؛ يمتد الفئة العامة socketserver defaultlifecycle {private serversocke receptor = null ؛ منفذ int الخاص = 9527 ؛ / * * seee defaultLifecycle#init0 () */ Override void init0 () remscleexception {try {receptor = new ServersOcket (port) ؛ } catch (ioException e) {رمي New LifectionException (e) ؛ }} / * * seee defaultlifecycle#start0 () * / Override void start0 () remSeCyCleexception {socket socket = null ؛ حاول {socket = appetor.accept () ؛ // افعل شيئًا مع Socket} catch (ioException e) {رمي New LifeCycleException (e) ؛ } أخيرًا {if (socket! = null) {try {socket.close () ؛ } catch (ioException e) {// todo acto catch block e.printstacktrace () ؛ }}}}} / * * seee defaultLifecycle#DRIDE0 () * / Override void void destroy0 () relmed lifeCycleException {if (receptor! = null) {try {entalor.close () ؛ } catch (ioException e) {// todo acto catch block e.printstacktrace () ؛ }}}} في ServersOcket هنا ، يقوم init0 بتهيئة الاستماع إلى المقبس ، وتبدأ Start0 في الحصول على اتصال المقبس ، وتدمير 10 يدمر الاستماع إلى المقبس.
بموجب آلية إدارة دورة الحياة هذه ، سنقوم بسهولة بإدارة الموارد ، ولن يكون هناك أي إغلاق للموارد ، وستكون الهندسة المعمارية والنموذج أكثر وضوحًا.
نهاية
حتى الآن ، نفذت هذه المقالة آلية إدارة دورة حياة بسيطة وأعطت جميع رموز التنفيذ. بعد ذلك ، سيتم وضع كل رمز المصدر على جيثب. يرجى الانتباه إلى تحديث هذه المقالة.