জাভাতে বিবৃতি দিলে দীর্ঘ তালিকা


101

দুঃখিত, আমি এর উত্তর দেওয়ার জন্য একটি প্রশ্ন খুঁজে পাচ্ছি না, আমি ইতিমধ্যে অন্য কেউ এর আগে উত্থাপিত প্রায় নিশ্চিত।

আমার সমস্যাটি হ'ল আমি এম্বেড থাকা ডিভাইসগুলি চালানোর জন্য কিছু সিস্টেম লাইব্রেরি লিখছি। আমার কাছে কমান্ড রয়েছে যা রেডিও সম্প্রচারের মাধ্যমে এই ডিভাইসে প্রেরণ করা যায়। এটি কেবল পাঠ্য দ্বারা করা যেতে পারে। সিস্টেম লাইব্রেরির ভিতরে আমার কাছে একটি থ্রেড রয়েছে যা কমান্ডগুলি হ্যান্ডেল করে যা দেখে মনে হয়

if (value.equals("A")) { doCommandA() }
else if (value.equals("B")) { doCommandB() } 
else if etc. 

সমস্যাটি হ'ল এতে প্রচুর কমান্ড রয়েছে যা কিছুটা নিয়ন্ত্রণের বাইরে চলে যায়। দেখতে খুব ভয়ঙ্কর, ডিবাগ করার জন্য বেদনাদায়ক এবং কয়েক মাসের মধ্যে বুঝতে বুদ্ধিমান মন।


16
একটি মন্তব্য - আমি দৃ strongly়ভাবে গ্যাং অফ ফোর প্যাটার্ন বইয়ের বাছাইয়ের পরামর্শ দেব বা আপনি যদি নিদর্শনগুলিতে নতুন হন তবে জাভা বইয়ের প্রধান ফার্স্ট ডিজাইন প্যাটার্নস (যা বেশ সহজ পঠনযোগ্য এবং প্রচলিত সাধারণ নিদর্শনগুলির দুর্দান্ত ভূমিকা) )। উভয়ই মূল্যবান সংস্থান এবং উভয়ই আমার বেকন একাধিকবার সংরক্ষণ করেছে।
অপারকিন্স

2
হ্যাঁ আসলে আমি তাদের মালিকানা পেয়েছি তবে তারা নিখোঁজ রয়েছে :) আমি নিশ্চিত যে কেন আমি করছিলাম তা ভুল ছিল :) যদিও এর সঠিক সমাধান খুঁজে পাওয়া গেল না! হতে পারে এটি একটি দুর্দান্ত গুগল পজিশন পেয়েছে
স্টিভ

2
এটি সোমবার এখানে কমান্ড প্যাটার্ন!
নিক ভিস

উত্তর:


171

কমান্ড প্যাটার্ন ব্যবহার করে :

public interface Command {
     void exec();
}

public class CommandA() implements Command {

     void exec() {
          // ... 
     }
}

// etc etc

তারপরে একটি Map<String,Command>বস্তু তৈরি করুন এবং Commandউদাহরণ সহ এটি তৈরি করুন :

commandMap.put("A", new CommandA());
commandMap.put("B", new CommandB());

তারপরে আপনি আপনার যদি / অন্যথায় শৃঙ্খলে প্রতিস্থাপন করতে পারেন :

commandMap.get(value).exec();

সম্পাদনা

এছাড়াও আপনি বিশেষ কমান্ডগুলি যুক্ত করতে পারেন যেমন UnknownCommandবা NullCommand, তবে CommandMapক্লায়েন্টের চেকগুলি হ্রাস করার জন্য আপনার এই কোণার কেসগুলি পরিচালনা করে এমন একটি দরকার ।


1
... যথাযথ চেক দিয়ে সেই কমান্ডম্যাপ.জেট () বাতিল করে না :-)
ব্রায়ান অ্যাগনিউ

3
অবশ্যই, আমি সরলতার জন্য কিছু বয়লারপ্লেট কোড বাদ দিয়েছি
dfa

10
একটি হ্যাশম্যাপের পরিবর্তে আপনি একটি জাভা এনাম ব্যবহার করতে পারেন, যা আপনাকে মুশি মানচিত্রের পরিবর্তে কমান্ডগুলির একটি সুসংযুক্ত সেট দেয়। আপনার এনামে একটি গেটর থাকতে পারে: কমান্ড গেটকমন্ড (); বা এমনকি এনামে এক্সট্রাক্ট পদ্ধতি হিসাবে এক্সিকিউট () প্রয়োগ করে, যা প্রতিটি উদাহরণ প্রয়োগ করে (কমান্ড হিসাবে এনাম)।
জিবি

2
এটি এনামে সমস্ত কমান্ড প্রয়োগ করতে বাধ্য করবে ... এটি আদর্শ হতে পারে। একটি ইন্টারফেসের সাহায্যে আপনি ডেকোরেটর প্যাটার্নও প্রয়োগ করতে পারেন (যেমন, ডিবাগকম্যান্ডডেকোরেটর, ট্রেসকম্যান্ডডেকটর), একটি সাধারণ জাভা ইন্টারফেসে বিল্ট-ইন রয়েছে আরও অনেক নমনীয়তা
ডিএফএ

5
ঠিক আছে, ছোট এবং কখনই বাড়ছে না এমন কমান্ডের সেটগুলির জন্য একটি এনাম একটি কার্যকর সমাধান।
ডিএফএ

12

আমার পরামর্শটি এনাম এবং কমান্ড অবজেক্টের এক ধরণের হালকা ওজনের সমন্বয় হবে combination এটি কার্যকর জাভার আইটেম 30 এ জোশুয়া ব্লচ দ্বারা প্রস্তাবিত একটি প্রতিমা।

public enum Command{
  A{public void doCommand(){
      // Implementation for A
    }
  },
  B{public void doCommand(){
      // Implementation for B
    }
  },
  C{public void doCommand(){
      // Implementation for C
    }
  };
  public abstract void doCommand();
}

অবশ্যই আপনি ডকমন্ডে প্যারামিটারগুলি পাস করতে পারেন বা রিটার্নের ধরণ থাকতে পারেন।

যদি ডওকমন্ডের বাস্তবায়নগুলি এনাম টাইপের সাথে সত্যই "ফিট" না হয় তবে এই সমাধানটি সম্ভবত যথাযথ নয় - যা সাধারণত যখন আপনাকে ট্রেড অফ করতে হয় - কিছুটা অস্পষ্ট।


7

কমান্ড একটি এনাম আছে:

public enum Commands { A, B, C; }
...

Command command = Commands.valueOf(value);

switch (command) {
    case A: doCommandA(); break;
    case B: doCommandB(); break;
    case C: doCommandC(); break;
}

আপনার যদি কয়েকটি কমান্ডের বেশি থাকে তবে কমান্ড প্যাটার্নটি অন্য কোথাও উত্তর হিসাবে ব্যবহার করে দেখুন (যদিও আপনি এনামটি ধরে রাখতে পারেন এবং কলটি হ্যাশম্যাপ ব্যবহার না করে এনামের মধ্যে প্রয়োগকারী শ্রেণিতে এম্বেড করতে পারেন)। উদাহরণস্বরূপ অনুগ্রহ করে এ প্রশ্নের উত্তর আন্দ্রেস বা জেনসের উত্তর দেখুন।


5
আপনার যুক্ত প্রতিটি নতুন কমান্ডের জন্য আপনার স্যুইচটি সম্পাদনা করতে হবে: এই কোডটি খোলা / বন্ধ নীতিটি অনুসরণ করে না
dfa

কমান্ডগুলি কম, বা অনেকগুলি তা নির্ভর করে? এছাড়াও এই সাইটটি আজকাল খুব খারাপভাবে ধীরে ধীরে ধীরে ধীরে উত্তরটি সম্পাদনা করতে 5 টি প্রচেষ্টা লাগে takes
জিবি

এটি আরও অনুকূল কীভাবে করবেন তার জন্য এই স্ট্যাকওভারফ্লো . com/ প্রশ্নগুলি / ১১৯9964646// ২ দেখতে অনুকূল নয়।
আন্দ্রেয় পিটারসন

হ্যাঁ, আমি আমার মন্তব্যের নীচে যা লিখেছি তা প্রয়োগ করতে সময় ব্যয় করার জন্য আপনাকে ধন্যবাদ - কমান্ড প্যাটার্ন হিসাবে জাভা এনুম। আমি যদি আমার পোস্টটি সম্পাদনা করতে পারি তবে আমি এটি উল্লেখ করব, তবে এই সাইটটি মারা যাচ্ছে।
জিবি

আমি মনে করি যে এই প্রশ্নগুলি একটি স্যুইচ বিবৃতিতে চিৎকার করছে!
মাইকেল ব্রাউন 14

7

ডিএফএ দ্বারা সহজ এবং স্পষ্টভাবে প্রদর্শিত হিসাবে একটি ইন্টারফেস বাস্তবায়ন পরিষ্কার এবং মার্জিত (এবং "সরকারীভাবে" সমর্থিত উপায়)। এটি ইন্টারফেস ধারণাটির জন্য কী বোঝায়।

সি # তে আমরা এমন প্রোগ্রামারদের জন্য প্রতিনিধিদের ব্যবহার করতে পারি যারা সিতে ফান্টন পয়েন্টার ব্যবহার করতে পছন্দ করে তবে ডিএফএ এর কৌশলটি ব্যবহারের উপায়।

আপনারও অ্যারে থাকতে পারে

Command[] commands =
{
  new CommandA(), new CommandB(), new CommandC(), ...
}

তারপরে আপনি সূচক অনুসারে একটি আদেশ কার্যকর করতে পারেন

commands[7].exec();

ডিএফএ এর কাছ থেকে চুরি করা, তবে ইন্টারফেসের পরিবর্তে একটি বিমূর্ত বেস ক্লাস করা। সেমিডিকি লক্ষ্য করুন যা পরে ব্যবহৃত হবে। অভিজ্ঞতার দ্বারা, আমি বুঝতে পারি যে প্রায়শই একটি সরঞ্জাম কমন্ডের সাব-কম্যান্ডগুলিও থাকে।

abstract public class Command()
{
  abstract public byte exec(String subCmd);
  public String cmdKey;
  public String subCmd;
}

আপনার আদেশগুলি এভাবে তৈরি করুন,

public class CommandA
extends Command
{
  public CommandA(String subCmd)
  {
    this.cmdKey = "A";
    this.subCmd = subCmd;
  }

  public byte exec()
  {
    sendWhatever(...);
    byte status = receiveWhatever(...);
    return status;
  }
}

এরপরে আপনি কী-ভ্যালু জুটি চুষার ক্রিয়াকলাপ সরবরাহ করে জেনেরিক হ্যাশম্যাপ বা হ্যাশ টেবিল প্রসারিত করতে পারেন:

public class CommandHash<String, Command>
extends HashMap<String, Command>
(
  public CommandHash<String, Command>(Command[] commands)
  {
    this.commandSucker(Command[] commands);
  }
  public commandSucker(Command[] commands)
  {
    for(Command cmd : commands)
    {
      this.put(cmd.cmdKey, cmd);
    }
  }
}

তারপরে আপনার কমান্ড স্টোরটি তৈরি করুন:

CommandHash commands =
  new CommandHash(
  {
    new CommandA("asdf"),
    new CommandA("qwerty"),
    new CommandB(null),
    new CommandC("hello dolly"),
    ...
  });

এখন আপনি নিয়ন্ত্রণমূলকভাবে পাঠাতে পারেন could

commands.get("A").exec();
commands.get(condition).exec();

কোনও .NET লোকেরা যদি এই প্রশ্নটি দেখে ও ওয়ান-পদ্ধতি ইন্টারফেসের সাথে উন্মাদ হয়ে যায় তবে প্রতিনিধিদের উল্লেখ করার জন্য +1। তবে তারা কার্যত পয়েন্টারগুলির সাথে তুলনীয় নয়। তারা কমান্ড প্যাটার্নের একটি ভাষা-সমর্থিত সংস্করণের নিকটে রয়েছে।
ড্যানিয়েল আর্উইকার

5

ভাল আমি কমান্ড অবজেক্ট তৈরি করার পরামর্শ দিয়েছি এবং স্ট্রিং-কে কী হিসাবে হ্যাশম্যাপে রেখেছি।


3

এমনকি যদি আমি বিশ্বাস করি যে কমান্ড প্যাটার্ন পদ্ধতির পক্ষে সর্বোত্তম অভ্যাসের দিকে আরও বেশি এবং দীর্ঘমেয়াদে রক্ষণাবেক্ষণযোগ্য হয় তবে আপনার জন্য এখানে একটি লাইনার বিকল্প রয়েছে:

org.apache.commons.beanutils.MethodUtils.invokeMethod (এই, "doCommand," + মান, নাল);


2

আমি সাধারণত এটি সমাধান করার চেষ্টা করি:

public enum Command {

A {void exec() {
     doCommandA();
}},

B {void exec() {
    doCommandB();
}};

abstract void exec();
 }

এর অনেক সুবিধা রয়েছে:

1) এক্সিকিউট কার্যকর না করে এনাম যুক্ত করা সম্ভব নয়। সুতরাং আপনি একটি এ মিস করবেন না

2) আপনাকে এটি কোনও কমান্ড মানচিত্রে যুক্ত করতে হবে না, তাই মানচিত্রটি তৈরি করার জন্য কোনও বয়লারপ্লেট কোড নেই। কেবল বিমূর্ত পদ্ধতি এবং এর বাস্তবায়ন। (যা তর্কযোগ্যভাবে বয়লারপ্লেটও হয় তবে এটি কোনও ছোট হয় না ..)

3) আপনি যদি এর কোনও দীর্ঘ তালিকার মধ্য দিয়ে গিয়ে বা হ্যাশকোডগুলি গণনা করে এবং লুকআপ করে কোনও নষ্ট সিপিইউ চক্র সংরক্ষণ করবেন।

সম্পাদনা করুন: যদি আপনার কাছে এনাম না থাকে তবে উত্স হিসাবে স্ট্রিং থাকে না তবে কেবল Command.valueOf(mystr).exec()এক্সিকিউট পদ্ধতিতে কল করতে ব্যবহার করুন । আপনি অন্য প্যাকেজ থেকে কল করতে চান এক্সিকিফ এ আপনাকে অবশ্যই জনসাধারণের পরিবর্তনকারী ব্যবহার করতে হবে তা নোট করুন।


2

আপনি সম্ভবত মানচিত্রের মানচিত্র ব্যবহার করে সেরা হন।

তবে আপনার কী মানচিত্রের প্রচুর পরিমাণে কড়া নাড়তে পারে তা পরিচালনা করতে এইগুলির একটি সেট আছে। তারপরে এনামসের সাথে এটি করা ভাল।

আপনি যদি "মান" এর সমাধান করার জন্য এনামে কোনও পদ্ধতি যুক্ত করেন তবে আপনি সুইচগুলি ব্যবহার না করে কোনও এনাম দিয়ে এটি করতে পারেন (উদাহরণস্বরূপ আপনার সম্ভবত উদাহরণস্বরূপদের দরকার নেই)। তারপরে আপনি ঠিক করতে পারেন:

আপডেট: প্রতিটি কলের পুনরাবৃত্তি এড়াতে স্থির মানচিত্র যুক্ত করা হয়েছে। এই উত্তরটি লজ্জাজনকভাবে চিটানো ।

Commands.getCommand(value).exec();

public interface Command {
    void exec();
}

public enum Commands {
    A("foo", new Command(){public void exec(){
        System.out.println(A.getValue());
    }}),
    B("bar", new Command(){public void exec(){
        System.out.println(B.getValue());
    }}),
    C("barry", new Command(){public void exec(){
        System.out.println(C.getValue());
    }});

    private String value;
    private Command command;
    private static Map<String, Commands> commandsMap;

    static {
        commandsMap = new HashMap<String, Commands>();
        for (Commands c : Commands.values()) {
            commandsMap.put(c.getValue(), c);    
        }
    }

    Commands(String value, Command command) {
        this.value= value;
        this.command = command;
    }

    public String getValue() {
        return value;
    }

    public Command getCommand() {
        return command;
    }

    public static Command getCommand(String value) {
        if(!commandsMap.containsKey(value)) {
            throw new RuntimeException("value not found:" + value);
        }
        return commandsMap.get(value).getCommand();
    }
}

2

@Dfa এর দেওয়া উত্তরটি আমার মতে সেরা সমাধান।

আপনি জাভা 8 ব্যবহার করছেন এবং লাম্বডাস ব্যবহার করতে চান সেই ক্ষেত্রে আমি কিছু স্নিপেট সরবরাহ করছি !

পরামিতি ছাড়াই কমান্ড:

Map<String, Command> commands = new HashMap<String, Command>();
commands.put("A", () -> System.out.println("COMMAND A"));
commands.put("B", () -> System.out.println("COMMAND B"));
commands.put("C", () -> System.out.println("COMMAND C"));
commands.get(value).exec();

(আপনি কমান্ডের পরিবর্তে রান্নেবল ব্যবহার করতে পারেন, তবে আমি এটিকে শব্দার্থিকভাবে সঠিক বিবেচনা করি না):

একটি প্যারামিটার সহ কমান্ড:

আপনি যদি কোনও প্যারামিটার আশা করতে পারেন তবে আপনি ব্যবহার করতে পারেন java.util.function.Consumer:

Map<String, Consumer<Object>> commands = new HashMap<String, Consumer<Object>>();
commands.put("A", myObj::doSomethingA);
commands.put("B", myObj::doSomethingB);
commands.put("C", myObj::doSomethingC);
commands.get(value).accept(param);

উপরের উদাহরণে, doSomethingXএকটি myObjশ্রেণীর ক্লাসে উপস্থিত এমন একটি পদ্ধতি যা কোনও অবজেক্টকে ( paramএই উদাহরণে নাম দেওয়া হয়েছে) আর্গুমেন্ট হিসাবে গ্রহণ করে।


1

যদি আপনার একাধিক এম্ব্রিবিটেড 'যদি' বিবৃতি থাকে তবে এটি কোনও নিয়ম ইঞ্জিন ব্যবহারের জন্য একটি প্যাটার্ন । দেখুন, উদাহরণস্বরূপ জেবিওএস ড্রোলস



0

যদি পদ্ধতিগুলির একটি অ্যারে (যা আপনি আদেশগুলি বলেছিলেন) থাকা সম্ভব হত যা দরকারী হতে পারে ..

তবে আপনি আপনার কোড লিখতে একটি প্রোগ্রাম লিখতে পারেন। (মান = 'এ') কমান্ডএ () থাকলে এগুলি সবই খুব নিয়মতান্ত্রিক; অন্যথায় যদি (........................ ইত্যাদি)


0

আপনার বিভিন্ন কমান্ডের আচরণের মধ্যে যদি আপনার কোনও ওভারল্যাপ থাকে তবে আমি নিশ্চিত নই, তবে আপনি চেইন অফ দায়িত্বশীলতার ধরণটিও দেখে নিতে পারেন যা একাধিক কমান্ডকে কিছু ইনপুট মানগুলি হ্যান্ডেল করার অনুমতি দিয়ে আরও নমনীয়তা সরবরাহ করতে পারে।


0

কমান্ড প্যাটার্ন হ'ল উপায়। জাভা 8 ব্যবহার করে একটি উদাহরণ এখানে দেওয়া হয়েছে:

1. ইন্টারফেস সংজ্ঞায়িত:

public interface ExtensionHandler {
  boolean isMatched(String fileName);
  String handle(String fileName);
}

2. প্রতিটি এক্সটেনশনের সাথে ইন্টারফেস প্রয়োগ করুন:

public class PdfHandler implements ExtensionHandler {
  @Override
  public boolean isMatched(String fileName) {
    return fileName.endsWith(".pdf");
  }

  @Override
  public String handle(String fileName) {
    return "application/pdf";
  }
}

এবং

public class TxtHandler implements ExtensionHandler {
  @Override public boolean isMatched(String fileName) {
    return fileName.endsWith(".txt");
  }

  @Override public String handle(String fileName) {
    return "txt/plain";
  }
}

ইত্যাদি

3. ক্লায়েন্ট সংজ্ঞায়িত:

public class MimeTypeGetter {
  private List<ExtensionHandler> extensionHandlers;
  private ExtensionHandler plainTextHandler;

  public MimeTypeGetter() {
    extensionHandlers = new ArrayList<>();

    extensionHandlers.add(new PdfHandler());
    extensionHandlers.add(new DocHandler());
    extensionHandlers.add(new XlsHandler());

    // and so on

    plainTextHandler = new PlainTextHandler();
    extensionHandlers.add(plainTextHandler);
  }

  public String getMimeType(String fileExtension) {
    return extensionHandlers.stream()
      .filter(handler -> handler.isMatched(fileExtension))
      .findFirst()
      .orElse(plainTextHandler)
      .handle(fileExtension);
  }
}

৪. এবং এটি নমুনার ফলাফল:

  public static void main(String[] args) {
    MimeTypeGetter mimeTypeGetter = new MimeTypeGetter();

    System.out.println(mimeTypeGetter.getMimeType("test.pdf")); // application/pdf
    System.out.println(mimeTypeGetter.getMimeType("hello.txt")); // txt/plain
    System.out.println(mimeTypeGetter.getMimeType("my presentation.ppt")); // "application/vnd.ms-powerpoint"
  }

-1

যদি এটি অনেক কিছু করে, তবে প্রচুর কোড আসবে, আপনি সত্যিই এ থেকে দূরে সরে পারবেন না। কেবল অনুসরণ করা সহজ করুন, ভেরিয়েবলগুলিকে খুব অর্থপূর্ণ নাম দিন, মন্তব্যগুলিও সহায়তা করতে পারে ...

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