هل تحتوي نمط استراتيجية Java على فئة سياق زائدة عن الحاجة؟

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

سؤال

نموذج التعليمات البرمجية التالي هو تطبيق لنمط الاستراتيجية نسخ من ويكيبيديا. وبعد سؤالي الكامل يتبع ذلك ...

الويكي main طريقة:

//StrategyExample test application

class StrategyExample {

    public static void main(String[] args) {

        Context context;

        // Three contexts following different strategies
        context = new Context(new ConcreteStrategyAdd());
        int resultA = context.executeStrategy(3,4);

        context = new Context(new ConcreteStrategySubtract());
        int resultB = context.executeStrategy(3,4);

        context = new Context(new ConcreteStrategyMultiply());
        int resultC = context.executeStrategy(3,4);

    }

}

قطع النمط:

// The classes that implement a concrete strategy should implement this

// The context class uses this to call the concrete strategy
interface Strategy {

    int execute(int a, int b);

}

// Implements the algorithm using the strategy interface
class ConcreteStrategyAdd implements Strategy {

    public int execute(int a, int b) {
        System.out.println("Called ConcreteStrategyA's execute()");
        return a + b;  // Do an addition with a and b
    }

}

class ConcreteStrategySubtract implements Strategy {

    public int execute(int a, int b) {
        System.out.println("Called ConcreteStrategyB's execute()");
        return a - b;  // Do a subtraction with a and b
    }

}

class ConcreteStrategyMultiply implements Strategy {

    public int execute(int a, int b) {
        System.out.println("Called ConcreteStrategyC's execute()");
        return a  * b;   // Do a multiplication with a and b
    }

}

// Configured with a ConcreteStrategy object and maintains a reference to a Strategy object
class Context {

    private Strategy strategy;

    // Constructor
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int a, int b) {
        return strategy.execute(a, b);
    }

}

النظر على وجه التحديد المثال أعلاه، هو Context فئة زائدة؟

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

(( يحرر: في هذا السيناريو البسيط، عندما أترك فئة السياق، هل سأحقق خطأ في المستقبل؟ ))

public static void main(String[] args) {

    IStrategy strategy;

    // Three strategies
    strategy = new ConcreteStrategyAdd();
    int resultA = strategy.executeStrategy(3,4);

    strategy = new ConcreteStrategySubtract();
    int resultB = strategy.executeStrategy(3,4);

    strategy = new ConcreteStrategyMultiply();
    int resultC = strategy.executeStrategy(3,4);

}

ملخص التحديث

القائمة في النقطة شكل ما تم اكتشافه من خلال الإجابات والتعليقات:

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

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

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

المحلول

كما يوحي الاسم، Context هو ما يغلف النقطة التي يتم بها تنفيذ الاستراتيجية. بدون ذلك، لديك فقط عار Strategy, ، ويتختار فئة الاتصال الآن مسؤولية إضافية: معرفة متى تسمي Strategy بحد ذاتها. مثالك ربما بسيطة للغاية، وفي هذه الحالة بالذات، أود أن أقول أن Context لا تحصل لك كثيرا.

مثال ربما يوضح أفضل فائدة Context هو أشبه بما يلي:

public class LoadingDock {   // Context.
  private LoadStrategy ls;   // Strategy.

  public void setLoadStrategy(LoadStrategy ls) { ... }

  // Clients of LoadingDock use this method to do the relevant work, rather
  // than taking the responsibility of invoking the Strategy themselves.
  public void shipItems(List<ShippingItem> l) {
    // verify each item is properly packaged     \
    // ...                                        |  This code is complex and shouldn't be
    // verify all addresses are correct           |  subsumed into consumers of LoadingDock.
    // ...                                        |  Using a Context here is a win because
    // load containers onto available vehicle     |  now clients don't need to know how a
    Vehicle v = VehiclePool.fetch();        //    |  LoadingDock works or when to use a
    ls.load(v, l);                          //   /   LoadStrategy.
  }
}

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

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

نصائح أخرى

هذا هو مثال أفضل على كيفية حقيقي "Context "يمكن للفئة النظر في هذا السيناريو:

class Accumulator {
    private Strategy strategy; 

    public Accumulator(Strategy strategy) { 
        this.strategy = strategy; 
    } 

    public int accumulate(List<Integer> values) { 
        int result = values.get(0);
        for (int i = 1; i < values.size(); i++) {
           result = strategy.execute(result, values.get(i));
        }
        return result;
    } 
}

تعديل: الخطأ المطبعي في منشئ ثابت

قد يكون ذلك لهذا المثال الصنع، ولكن بعد ذلك، لن أسميه هذه الإستراتيجية NE Plus فائقة الاستراتيجية.

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

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

Context لن تكون زائدة عن الحاجة Strategy نمط وهو مفيد في السيناريوهات أدناه:

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

    على سبيل المثال Context سوف تحصل على استراتيجية وعمالة المستخدمين كمعلمة. قبل التنفيذ Strategy, Context تحتاج إلى توفير الكثير من المعلومات الإضافية المتعلقة بملف تعريف المستخدم. Context سيحضر المعلومات المطلوبة وتنفذ الطريقة الاستراتيجية للاستراتيجية. في حالة عدم وجود سياق، يجب عليك تكرار الرمز عند 100 مكان مختلف إذا اتصلت بالطريقة الاستراتيجية في 100 مكان مختلف.

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

  4. إذا كان عليك العمل على استراتيجيات متعددة، Context هو أفضل مكان. اقترحت Axtavt الإجابة عن استخدام Accumulator هو مثال واحد.

الرجوع إلى هذا المنشور مزيد من التفاصيل.

مثال العالم الحقيقي على نمط الاستراتيجية

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