নীচের কোড স্নিপেট থেকে / অন্যথায়- যদি অনেকের থেকে বাঁচার আরও ভাল উপায় কী?


14

আমি একটি সার্লেট লিখতে চেষ্টা করছি যা "ক্রিয়া" মানের উপর ভিত্তি করে টাস্ক করে এটি ইনপুট হিসাবে প্রেরণ করে।

যার নমুনা এখানে দেওয়া হল

public class SampleClass extends HttpServlet {
     public static void action1() throws Exception{
          //Do some actions
     }
     public static void action2() throws Exception{
          //Do some actions
     }
     //And goes on till action9


     public void doPost(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException {
          String action = req.getParameter("action");

          /**
           * I find it difficult in the following ways
           * 1. Too lengthy - was not comfortable to read
           * 2. Makes me fear that action1 would run quicker as it was in the top
           * and action9 would run with a bit delay - as it would cross check with all the above if & else if conditions
           */

          if("action1".equals(action)) {
               //do some 10 lines of action
          } else if("action2".equals(action)) {
               //do some action
          } else if("action3".equals(action)) {
               //do some action
          } else if("action4".equals(action)) {
               //do some action
          } else if("action5".equals(action)) {
               //do some action
          } else if("action6".equals(action)) {
               //do some action
          } else if("action7".equals(action)) {
               //do some action
          } else if("action8".equals(action)) {
               //do some action
          } else if("action9".equals(action)) {
               //do some action
          }

          /**
           * So, the next approach i tried it with switch
           * 1. Added each action as method and called those methods from the swith case statements
           */
          switch(action) {
          case "action1": action1();
               break;
          case "action2": action2();
               break;
          case "action3": action3();
               break;
          case "action4": action4();
               break;
          case "action5": action5();
               break;
          case "action6": action6();
               break;
          case "action7": action7();
               break;
          case "action8": action8();
               break;
          case "action9": action9();
               break;
          default:
               break;
          }

          /**
           * Still was not comfortable since i am doing un-necessary checks in one way or the other
           * So tried with [reflection][1] by invoking the action methods
           */
          Map<String, Method> methodMap = new HashMap<String, Method>();

        methodMap.put("action1", SampleClass.class.getMethod("action1"));
        methodMap.put("action2", SampleClass.class.getMethod("action2"));

        methodMap.get(action).invoke(null);  

       /**
        * But i am afraid of the following things while using reflection
        * 1. One is Security (Could any variable or methods despite its access specifier) - is reflection advised to use here?
        * 2. Reflection takes too much time than simple if else
        */

     }
    }

আমার কেবলমাত্র আরও অনেকের হাত থেকে বাঁচতে হবে যদি / অন্যথায় - আরও ভাল পাঠযোগ্যতার জন্য এবং আরও ভাল কোড রক্ষণাবেক্ষণের জন্য আমার কোডটিতে চেক করা হয়। সুতরাং অন্যান্য বিকল্পের জন্য চেষ্টা করে

1. স্যুইচ কেস - এখনও আমার ক্রিয়াটি করার আগে এটি অনেক বেশি চেক করে

2. প্রতিবিম্ব

i] একটি প্রধান বিষয় সুরক্ষা - যা আমাকে ক্লাসের মধ্যে এমনকি অ্যাক্সেস সুনির্দিষ্ট সত্ত্বেও ভেরিয়েবল এবং পদ্ধতিগুলি অ্যাক্সেস করতে দেয় - আমি নিশ্চিত নই যে আবহাওয়া আমি আমার কোডটিতে এটি ব্যবহার করতে পারি

ii] এবং অন্যটি হ'ল যদি / অন্য-যদি চেক হয় তবে এটি সাধারণের চেয়ে বেশি সময় নেয়

উপরের কোডটি আরও ভাল উপায়ে সাজানোর পরামর্শ দেওয়ার মতো আরও ভাল কোনও পদ্ধতির বা আরও ভাল ডিজাইন রয়েছে কি?

সম্পাদিত

আমি যোগ করেছি উত্তর উপরে স্নিপেট বিবেচনা করার জন্য উত্তর নিচে

কিন্তু তবুও, "এক্সিকিউটারএ" এবং "এক্সিকিউটারবি" নিম্নলিখিত ক্লাসগুলি কোডের কয়েকটি লাইন করে। এটি একটি পদ্ধতি হিসাবে যুক্ত করার চেয়ে তাদের শ্রেণি হিসাবে যুক্ত করা কি ভাল অনুশীলন? এই বিষয়ে পরামর্শ করুন।



2
আপনি কেন 9 টি পৃথক ক্রিয়া সহ একটি একক সার্লেটটি ওভারলোড করছেন? আলাদা আলাদা সার্লেটের সাহায্যে প্রতিটি ক্রিয়াকে কেবল আলাদা পৃষ্ঠায় ম্যাপ করবেন না কেন? এই পদক্ষেপের ক্রিয়াটি ক্লায়েন্ট দ্বারা সম্পন্ন হয় এবং আপনার সার্ভার কোডটি কেবল ক্লায়েন্টের অনুরোধটি পরিবেশন করার উপর দৃষ্টি নিবদ্ধ করে।
পারে_ফ্যাক্টর

উত্তর:


13

পূর্ববর্তী উত্তরের উপর ভিত্তি করে, জাভা এনামগুলিকে বৈশিষ্ট্যগুলি রাখার অনুমতি দেয় যাতে আপনি কোনও কৌশল বিন্যাস সংজ্ঞায়িত করতে পারেন something

public enum Action {
    A ( () -> { //Lambda Sintax
        // Do A
       } ), 
    B ( () -> executeB() ), // Lambda with static method
    C (new ExecutorC()) //External Class 

    public Action(Executor e)
        this.executor = e;
    }

    //OPTIONAL DELEGATED METHOD
    public foo execute() {
        return executor.execute();
    }

    // Action Static Method
    private static foo executeB(){
    // Do B
    }
}

তাহলে আপনার Executor(কৌশল) হবে

public interface Executor {
    foo execute();
}

public class ExecutorC implements Executor {
    public foo execute(){
        // Do C
    }
}

এবং আপনার সমস্ত যদি / আপনার doPostপদ্ধতিতে অন্য কিছু হয়ে ওঠে

public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    String action = req.getParameter("action");
    Action.valueOf(action).execute();
}

এইভাবে আপনি এনামগুলিতে নির্বাহকদের জন্য ল্যাম্বডাস ব্যবহার করতে পারেন।


ভাল বলেছেন .. তবে আমার একটি ছোট স্পষ্টতা দরকার .. আমার সমস্ত ক্রিয়া ক্রিয়াকলাপ 1 (), ক্রিয়া 2 () কোডের কয়েকটি লাইন হবে .. এটি কোনও শ্রেণীর মধ্যে প্যাক করা ভাল হবে?
টম টেলর

4
এটি এমন লাইনগুলির সংখ্যা নয় যা আপনাকে নির্দিষ্ট শ্রেণি / অবজেক্ট তৈরি করতে রাজি করতে হবে, তবে তারা বিভিন্ন আচরণের প্রতিনিধিত্ব করে। 1 ধারণা / ধারণা = 1 লজিকাল অবজেক্ট।
mgoeminne

2
@ রাজাসুবা সুব্রাহ্মণীয় আপনি যদি কোনও ক্লাস খুব বেশি ভারী বলে মনে করেন তবে আপনি ল্যাম্বডা বা পদ্ধতির রেফারেন্সও ব্যবহার করতে পারেন। Executorএকটি (বা হতে পারে) একটি ক্রিয়ামূলক ইন্টারফেস।
হাল্ক

1
@ জে। পিচার্ডো আপডেটের জন্য ধন্যবাদ :) যেহেতু আমি এখনও জাভা in তে আছি আমি ল্যাম্বডা এক্সপ্রেশন ব্যবহার করতে পারিনি .. সুতরাং, dzone.com/articles/strategy-pattern- অজানা
টম টেলর

1
@ রাজাসুবা সুব্রাহ্মণীয় শান্ত, আমি নতুন কিছু শিখলাম,
জে পিচার্ডো

7

প্রতিবিম্বটি ব্যবহার করার পরিবর্তে, একটি উত্সর্গীকৃত ইন্টারফেস ব্যবহার করুন।

এর পরিবর্তে:

      /**
       * Still was not comfortable since i am doing un-necessary checks in one way or the other
       * So tried with [reflection][1] by invoking the action methods
       */
      Map<String, Method> methodMap = new HashMap<String, Method>();

    methodMap.put("action1", SampleClass.class.getMethod("action1"));
    methodMap.put("action2", SampleClass.class.getMethod("action2"));

    methodMap.get(action).invoke(null);  

ব্যবহার

 public interface ProcessAction{
       public void process(...);
 }

প্রতিটি ক্রিয়াকলাপের জন্য তাদের প্রতিটিকে কার্যকর করে এবং তারপরে:

 // as attribute
Map<String, ProcessAction> methodMap = new HashMap<String, ProcessAction>();
// now you can add to the map you can either hardcode them in an init function
methodMap.put("action1",action1Process);

// but if you want some more flexibility you should isolate the map in a class dedicated :
// let's say ActionMapper and add them on init : 

public class Action1Manager{
    private static class ProcessAction1 implements ProcessAction{...}

    public Action1Manager(ActionMapper mapper){
       mapper.addNewAction("action1", new ProcessAction1());
    }
}

অবশ্যই এই সমাধানটি সবচেয়ে উঁচুতে নয়, তাই আপনাকে এই দৈর্ঘ্যের দিকে যেতে হবে না।


আমার মনে হয় এর ProcessActionবদলে অবশ্যই হওয়া উচিত ActionProcessতাই না ...?
টম টেলর

1
হ্যাঁ আমি এটি স্থির করেছি।
ওয়ালফ্র্যাট

1
এবং আরও সাধারণভাবে উত্তরটি হ'ল "ওওপি মেকানিজম ব্যবহার করুন"। সুতরাং, এখানে আপনার "পরিস্থিতি" এবং এর সাথে সম্পর্কিত আচরণের বিষয়টি উল্লেখ করা উচিত। অন্য কথায়, কোনও বিমূর্ত বস্তুর দ্বারা আপনার যুক্তি উপস্থাপন করা এবং তারপরে এই বিষয়টিকে এর অন্তর্নিহিত বাদাম এবং বল্টের পরিবর্তে ম্যানিপুলেট করুন।
mgoeminne

এছাড়াও, @ ওয়ালফ্র্যাট দ্বারা প্রস্তাবিত পদ্ধতির একটি প্রাকৃতিক বর্ধিতকরণ নির্দিষ্ট স্ট্রিং প্যারামিটারের উপর নির্ভর করে সঠিক প্রসেসএশন তৈরি / প্রদান করে এমন একটি (বিমূর্ত) কারখানার প্রস্তাব দেওয়ার মধ্যে থাকবে।
mgoeminne

@ এমগোইমিনে এই শব্দটি ঠিকই শোনাচ্ছে
জে পিচার্ডো

2

কমান্ড প্যাটার্নটি ব্যবহার করুন , এর জন্য একটি কমান্ড ইন্টারফেসের প্রয়োজন হবে:

interface CommandInterface {
    CommandInterface execute();
}

যদি Actionsলাইটওয়েট এবং নির্মাণে সস্তা হয় তবে একটি কারখানা পদ্ধতি ব্যবহার করুন। কোনও বৈশিষ্ট্য ফাইল থেকে শ্রেণিকামগুলি লোড করুন যা actionName=classNameকার্যকর করার জন্য ক্রিয়াগুলি তৈরি করতে একটি সাধারণ কারখানার পদ্ধতি মানচিত্র করে এবং ব্যবহার করে।

    public Invoker execute(final String targetActionName) {
        final String className = this.properties.getProperty(targetAction);
        final AbstractCommand targetAction = (AbstractCommand) Class.forName(className).newInstance();
        targetAction.execute();
    return this;
}

অ্যাকশনগুলি যদি ব্যয় করতে ব্যয় হয় তবে একটি পুল ব্যবহার করুন, যেমন হ্যাশম্যাপ ; তবে বেশিরভাগ ক্ষেত্রেই আমি প্রস্তাব করব এই অধীনে এড়ানো যেত একক দায়িত্ব নীতি প্রতিনিধিরূপে ব্যয়বহুল বরং কমান্ড নিজেদের চেয়ে কিছু প্রাক নির্মাণ সাধারণ উৎসগুলো পুল উপাদান।

    public class CommandMap extends HashMap<String, AbstractAction> { ... }

এরপরে এগুলি কার্যকর করা যেতে পারে

    public Invoker execute(final String targetActionName) {
        commandMap.get(targetActionName).execute();
        return this;
}

এটি একটি অত্যন্ত দৃ and় এবং decoupled পদ্ধতির যা এসআরপি, এলএসপি এবং সলিড নীতিগুলির আইএসপি প্রয়োগ করে । নতুন কমান্ডগুলি কমান্ড ম্যাপার কোডটি পরিবর্তন করে না। আদেশগুলি কার্যকর করা সহজ। এগুলি কেবল প্রকল্প এবং সম্পত্তি ফাইলগুলিতে যুক্ত করা যেতে পারে। কমান্ডগুলি পুনরায় প্রবেশ করা উচিত এবং এটি এটি খুব পারফরম্যান্ট করে তোলে।


1

স্ট্রিংয়ের মানগুলিকে হার্ডকডিংয়ের প্রয়োজনীয়তা হ্রাস করতে আপনি গণনা ভিত্তিক অবজেক্টটি ব্যবহার করতে পারেন। এটি আপনার কিছুটা সময় সাশ্রয় করবে এবং ভবিষ্যতে কোডটি পড়তে ও প্রসারিত করতে অনেক ঝরঝরে করে তুলবে।

 public static enum actionTypes {
      action1, action2, action3....
  }

  public void doPost {
      ...
      switch (actionTypes.valueOf(action)) {
          case action1: do-action1(); break;
          case action2: do-action2(); break;
          case action3: do-action3(); break;
      }
  }

1

ফ্যাক্টরি পদ্ধতির প্যাটার্নটি হ'ল যা আপনি দেখতে পাচ্ছেন যদি আপনি স্কেলযোগ্য এবং কম রক্ষণাবেক্ষণযোগ্য ডিজাইনের সন্ধান করছেন।

কারখানা পদ্ধতির প্যাটার্নটি কোনও অবজেক্ট তৈরির জন্য একটি ইন্টারফেসকে সংজ্ঞায়িত করে তবে সাবক্লাসটি সিদ্ধান্ত নিতে পারে কোন শ্রেণিটি ইনস্ট্যান্ট করতে হবে। কারখানার পদ্ধতিটি একটি শ্রেণিকে সাবক্লাসে স্থগিত করে দেয় inst

 abstract class action {abstract doStuff(action)}

ক্রিয়া 1, ক্রিয়া 2 ........ doStuff পদ্ধতিতে করণীয় কার্যকর করার সাথে অ্যাকশনএন কংক্রিট বাস্তবায়ন।

শুধু কল

    action.doStuff(actionN)

ভবিষ্যতে যদি আরও অ্যাকশন চালু করা হয় তবে আপনার কেবল কংক্রিট ক্লাস যুক্ত করা দরকার।


টাইপ বিমূর্তি -> প্রথম কোড লাইনে বিমূর্ত। সম্পাদনা করুন। এছাড়াও, আপনি এই উদাহরণটিকে আরও সরাসরি দেখানোর জন্য আরও কিছু কোড যুক্ত করতে পারেন যাতে এটি ওপির প্রশ্নের উত্তর কীভাবে দেয়?
জে এলস্টন

0

@ জে রেফারেন্স সহ। পিচার্ডো উত্তর আমি নীচের হিসাবে উপরের স্নিপেট সংশোধন লিখছি

public class SampleClass extends HttpServlet {

public enum Action {
    A (new ExecutorA()),
    B (new ExecutorB())

    Executor executor;

    public Action(Executor e)
        this.executor = e;
    }

    //The delegate method
    public void execute() {
        return executor.execute();
    }
}

public foo Executor {
    foo execute();
}

public class ExecutorA implements Executor{
   public void execute() {
      //Do some action
   }
}

public class ExecutorB implements Executor{
   public void execute() {
      //Do some action
   }
}

public void doPost(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException {

  String action = req.getParameter("action"); 
  Action.valueOf(action).execute();
  }
}

খুব বেশি অ্যাকশন থাকলে আপনি কি খুব বেশি ক্লাস তৈরি করছেন না? আমাদের কি আরও ভাল বাস্তবায়ন আছে?
বৈভব শর্মা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.