جافا:غير قابل للتغيير إلى التحويلات غير القابلة للتغيير

StackOverflow https://stackoverflow.com/questions/280706

سؤال

لقد كنت أفكر في طرق لتوفير السكر النحوي لإطار العمل الذي كنت أعمل عليه.أريد أن أتعامل مع الأشياء غير القابلة للتقليد بشكل حصري.

لنفترض أن لدي كائنًا غير قابل للتغيير وأرغب في إنشاء نسخة معدلة منه.هل، من وجهة نظرك، فئة غير قابلة للإنشاء مع طريقة مصنع ثابتة واحدة تنتهك مبادئ OO؟


كمثال باستخدام سلسلة:

public final class LOWERCASE {

    private LOWERCASE() {}

    public static String string( final String STRING ) {

      return STRING.toLowerCase();
    }
}

لذلك من هذا المثال يمكنني أن أكتب:

String lowercaseString = LOWERCASE.string( targetString );

الذي أجده قابلاً للقراءة جدًا.


هل هناك أي شروط ضد مثل هذا النهج؟

هل كانت مفيدة؟

المحلول

وأنا لا أعتقد أنها فكرة جيدة لإنشاء فئة واحدة في الأسلوب. هل يمكن بدلا من ذلك إنشاء فئة الأساليب الوحيدة الثابتة، واسمه منها مثلا StringUtils وتنفيذ الطرق. بهذه الطريقة يمكنك أن أسميه:

وسلسلة lowerCaseString = StringUtils.lowercase (targetString)؛

وهذا من شأنه ايضا ان نقدم لكم المساعدة التحسس بينما كنت تكتب. سوف قائمة الفصول الدراسية تذهب خلاف كبير جدا. حتى بالنسبة لهذا المثال البسيط، يجب تنفيذ أكثر من الطبقات بالأحرف الصغيرة، بحيث يمكن أيضا لتلبية احتياجات الظروف أن CulutureInfo يجب أن تؤخذ بعين الاعتبار.

وأنا لا أعتقد أن هذا يكسر مبادئ OO بأي شكل من الأشكال أو أن هو تصميم سيئة. في لغات أخرى، روبي على سبيل المثال، يمكنك إضافة أساليب مباشرة إلى الفئة سلسلة. الأساليب التي تنتهي! دلالة على أن يتم تعديل الكائن الأصلي. كل الطرق الأخرى بإرجاع نسخة معدلة. روبي على القضبان الإطار يضيف بعض الأساليب لفئة سلسلة وهناك بعض الجدل حول ما إذا كان هذا هو أسلوب جيد أم لا. وهو مفيد بالتأكيد بالرغم من ذلك.

نصائح أخرى

وعادة على الأشياء الثابتة، وأود أن طريقة عودته نسخة معدلة من وجوه. حتى إذا كان لديك بعض جمع غير قابل للتغيير، يمكن أن يكون لها طريقة الفرز ()، التي تقوم بإرجاع مجموعة جديدة التي تم فرزها. ومع ذلك، في سبيل المثال سلسلة الخاص بك لم يكن ذلك ممكنا، لأنك لا يمكن أن تمس فئة سلسلة.

والنهج الخاص بك هو مقروء جدا، وأعتقد لحالات حافة مثل هذا، على ما يرام تماما. لكائنات ثابتة تكتب نفسك، كنت قد والأسلوب على الكائن نفسه.

سلسلة اريك ليبرت على الأشياء الثابتة في C # هي جيد جدا، بالمناسبة.

في رأيي، النقطة الوحيدة من هذا الطراز المصنع سيكون إذا قدمت الطبقة أنواع مختلفة من الكائنات غير قابل للتغيير.

مثال:

public final class Lowercase {

  private Lowercase() {}

  public static String string( final String string ) {

   return new String( string.toLowerCase() );
  }

  public static Foo foo( final Foo f ) {
     boolean isLowerCase = true;
     return new Foo(f, isLowerCase );
  }
}

وعلى خلاف ذلك، يجب تنفيذ طريقتك في فئة ثابتة نفسها مثل toLowerCase () في سلسلة الفئة.

وفي كلتا الحالتين، وأنا لا أعتقد أن هذا يكسر أي مبدأ OO.

وأنا أتفق مع إريك.يجب أن تحتوي الكائنات غير القابلة للتغيير دائمًا على طريقة لإرجاع نسخة معدلة من الكائن بدلاً من طريقة ثابتة.هناك أيضًا أمثلة في JDK:

  • سلسلة.subString(كثافة العمليات)
  • BigDecimal.movePointLeft(int)

إن القيام بذلك بهذه الطريقة له ميزة أنك لا تحتاج إلى تمرير المثيل الذي تريد تعديله كوسيطة لطريقة ما.بالنسبة لفئات مثل String أو Integer، أفضّل استخدام فئة مجمعة.ثم يمكنك التحكم في وقت إنشاء مثل هذا الكائن (بواسطة مُنشئ فئة الغلاف أو إحدى طرق الفئة).إذا كنت ستستخدم الفئة Integer، فسيكون التحكم في ذلك أكثر تعقيدًا حيث يمكن للجميع إنشاء مثيل له.

من ناحية أخرى، يعتبر مثالك لبعض فئات المرافق مثل StringUtils لحزمة Apache commons-lang.مجرد إلقاء نظرة على هذا كما أعتقد أنك تريد إنشاء شيء مثل هذا.(لا تعيد اختراع العجلة)

وnew String() هو رائحة الكود - هو تقريبا <م> دائما لا لزوم لها بسبب <م> ثبات من String. مرة واحدة في المثال String له قيمة، تلك الحالة لن، يكون لها قيمة مختلفة من أي وقت مضى.

في الأسلوب التالي، new String() لا لزوم لها:

public static String string( final String string ) {
    return new String( string.toLowerCase() );
}

وtoLowerCase() إرجاع (مختلفة) مثلا String الجديد - new String() لا تفعل أي شيء مفيد هنا بعضا من تسبب إنشاء كائن أخرى لها قيمة الدقيقة للالمثال String إرجاعها بواسطة toLowerCase()

وهنا نصي صغير رائع يبين مفهوم (آمل - ملاحظة، وهذا هو جافا تحت لغة البرمجة النصية):

String a = 'CamelCase'
String b = a.toLowerCase()

println "a='${a}'"
println "b='${b}'"

وإنتاج

a='CamelCase'
b='camelcase'

لاحظ أن a <م> لم يتغير - هو غير قابل للتغيير. b هو قيمة String جديدة.

ونفس الشيء ينطبق على BigDecimal.movePointLeft() أو أي وسيلة أخرى على BigDecimal وترجع BigDecimal - انهم حالات جديدة، وترك المثيل الأصلي دون تغيير

.

حسنا، الآن أن أجيب على سؤالك:

وبعد مجموعة من عمليات Strings التي تؤدي غرضا مفيدا في التطبيق الخاص بك هو فكرة جيدة. باستخدام مصنع ربما ليس من الضروري لشيء من هذا القبيل String، ولكن قد يكون لفئة ثابتة المختلفة التي يأخذ بعض الجهد لبناء.

في حالة ما إذا لم يكن من الممكن تمديد الفئة الأساسية، مثل String، فئة static methods كماkgiannakakis وصف ما يرام.

وإلا، إذا الطبقة "ثابتة" هي جزء من التطبيق، حيث لديك حق الوصول إلى تعريف فئة / تعريف وأساليب عودته مثيل جديد، في نموذج BigDecimal، String، وما إلى ذلك، سيكون من الأفضل. هذا هو في جوهر ما، @ برونو كوندي وreallyinsane وقالErik هيسلينك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top