ওও ভাষায় অবজেক্টের রাষ্ট্রের প্রয়োগ?


11

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

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

আমি যতদূর দেখতে পাচ্ছি, গাড়ি রাজ্যটি কেবল তার নিজস্ব শ্রেণির মধ্যেই ব্যবহৃত হয়।

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

আমি এখানে যে প্রধান সমস্যাটি দেখতে পাচ্ছি তা হ'ল স্যুইচ বিবৃতিটি সম্ভবত খুব বড় হয়ে উঠতে পারে কারণ আমরা আরও রাজ্য যুক্ত করি (যদি মনে করা হয়) এবং কোডটি অযৌক্তিক এবং বজায় রাখা শক্ত হয়ে উঠতে পারে।

এই সমস্যার আরও ভাল সমাধান কী হতে পারে?


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

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

1
আমি এখনও মনে করি আপনার কোড কোডভিউতে পোস্ট করার কথা বিবেচনা করা উচিত।
রবার্ট হার্ভে

1
আমার কাছে একটি রাষ্ট্রীয় যন্ত্রের মতো শোনাচ্ছে। object.state = object.function(object.state);
রবার্ট ব্রিস্টো-জনসন

গৃহীত উত্তর সহ এখন পর্যন্ত প্রদত্ত সমস্ত উত্তরগুলি স্যুইচ বিবৃতিটিকে খারাপ বলে বিবেচনা করার মূল কারণটি মিস করে। তারা মুক্ত / বদ্ধ নীতি মেনে চলতে দেয় না।
ডঙ্ক

উত্তর:


13
  • আমি স্টেট প্যাটার্ন ব্যবহার করে গাড়িটিকে এক ধরণের রাজ্য মেশিনে পরিণত করেছি । নোট নং switchবা if-then-elseবিবৃতি রাষ্ট্র নির্বাচনের জন্য ব্যবহৃত হয়।

  • এই ক্ষেত্রে সমস্ত রাজ্য অন্তর্গত শ্রেণি তবে এটি অন্যথায় কার্যকর করা যেতে পারে।

  • প্রতিটি রাজ্যে এটিতে পরিবর্তিত হতে পারে এমন বৈধ রাষ্ট্র রয়েছে।

  • একের অধিক সম্ভব হলে ব্যবহারকারীকে পরবর্তী রাজ্যে অনুরোধ জানানো হয় বা কেবলমাত্র একজনের পক্ষে সম্ভব হলে তা নিশ্চিত করার জন্য to

  • আপনি এটি সংকলন করতে এবং এটি পরীক্ষা করতে এটি চালাতে পারেন।

  • আমি গ্রাফিক সংলাপ বাক্সটি ব্যবহার করেছি কারণ এটি গ্রহণের ক্ষেত্রে ইন্টারেক্টিভভাবে চালানো সহজতর উপায় ছিল।

এখানে চিত্র বর্ণনা লিখুন

ইউএমএল চিত্রটি এখান থেকে নেওয়া হয়েছে

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JOptionPane;

public class Car {

    private State state;
    public static final int ST_OFF=0;
    public static final int ST_IDDLE=1;
    public static final int ST_DRIVE=2;
    public static final int ST_REVERSE=3;

    Map<Integer,State> states=new HashMap<Integer,State>();

    public Car(){
        this.states.put(Car.ST_OFF, new Off());
        this.states.put(Car.ST_IDDLE, new Idle());
        this.states.put(Car.ST_DRIVE, new Drive());
        this.states.put(Car.ST_REVERSE, new Reverse()); 
        this.state=this.states.get(Car.ST_OFF);
    }

    private abstract class State{

        protected List<Integer> nextStates = new ArrayList<Integer>();

        public abstract void handle();
        public abstract void change();

        protected State promptForState(String prompt){
            State s = state;
            String word = JOptionPane.showInputDialog(prompt);
            int ch = -1;
            try {
                ch = Integer.parseInt(word);
            }catch (NumberFormatException e) {
            }   

            if (this.nextStates.contains(ch)){
                s=states.get(ch);
            } else {
                System.out.println("Invalid option");
            }
            return s;               
        }       

    }

    private class Off extends State{

        public Off(){ 
            super.nextStates.add(Car.ST_IDDLE);             
        }

        public void handle() { System.out.println("Stopped");}

        public void change() {
            state = this.promptForState("Stopped, iddle="+Car.ST_IDDLE+": ");
        }

    }

    private class Idle extends State{
        private List<Integer> nextStates = new ArrayList<Integer>();
        public Idle(){
            super.nextStates.add(Car.ST_DRIVE);
            super.nextStates.add(Car.ST_REVERSE);
            super.nextStates.add(Car.ST_OFF);       
        }

        public void handle() {  System.out.println("Idling");}

        public void change() { 
            state=this.promptForState("Idling, enter 0=off 2=drive 3=reverse: ");
        }

    }

    private class Drive extends State{

        private List<Integer> nextStates = new ArrayList<Integer>();
        public Drive(){
            super.nextStates.add(Car.ST_IDDLE);
        }       
        public void handle() {System.out.println("Driving");}

        public void change() {
            state=this.promptForState("Idling, enter 1=iddle: ");
        }       
    }

    private class Reverse extends State{
        private List<Integer> nextStates = new ArrayList<Integer>();
        public Reverse(){ 
            super.nextStates.add(Car.ST_IDDLE);
        }           
        public void handle() {System.out.println("Reversing");} 

        public void change() {
            state = this.promptForState("Reversing, enter 1=iddle: ");
        }       
    }

    public void request(){
        this.state.handle();
    }

    public void changeState(){
        this.state.change();
    }

    public static void main (String args[]){
        Car c = new Car();
        c.request(); //car is stopped
        c.changeState();
        c.request(); // car is iddling
        c.changeState(); // prompts for next state
        c.request(); 
        c.changeState();
        c.request();    
        c.changeState();
        c.request();        
    }

}

1
আমি সত্যিই এটি পছন্দ করি. আমি শীর্ষের উত্তরের প্রশংসা করি এবং এটি স্যুইচ বিবৃতিগুলির প্রতিরক্ষা (আমি এখনই চিরকালের জন্য এটি স্মরণ করব), সত্যই আমি এই প্যাটার্নটির ধারণা পছন্দ করি। আপনাকে ধন্যবাদ
পাইথননিউব

@ পাইথননিউব আপনি কি এটি চালিয়েছেন?
তুলিনস কর্ডোভা

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

1
@ পাইথনউইবিবি আমি একটি ইন্টারফেসের পরিবর্তে একটি অ্যাবস্ট্রাক্ট ক্লাস ব্যবহার করে ইনপুট লজিকের জন্য পরিবর্তন রাষ্ট্র / প্রম্পটটিকে পুনরায় ব্যবহার করে কোডটি একটি সংক্ষিপ্ত সংস্করণে পরিবর্তন করেছি। এটি 20 টি লাইন সংক্ষিপ্ত কিন্তু আমি পরীক্ষিত এবং একই কাজ করে। আপনি সম্পাদনা ইতিহাসের দিকে তাকানো সর্বদা পুরানো, দীর্ঘতর সংস্করণ পেতে পারেন।
তুলাইনস কর্ডোভা

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

16

সুইচ স্টেটমেন্ট খারাপ

এটি এই জাতীয় ওভার সরলিকরণ যা অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিংকে একটি খারাপ নাম দেয়। ব্যবহার ifকরা ঠিক ততটা "খারাপ" যেমন একটি সুইচ স্টেটমেন্ট ব্যবহার করে। যে কোনও উপায়ে আপনি বহির্মুখীভাবে প্রেরণ করছেন না।

যদি আপনার অবশ্যই একটি নিয়ম থাকে যা একটি সাউন্ড কামড়ের সাথে ফিট করে তবে এটি ব্যবহার করে দেখুন:

আপনার দুটি কপি থাকা মুহুর্তে স্যুইচ স্টেটমেন্টগুলি খুব খারাপ হয়ে যায়।

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

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

আপনার যদি রিফ্যাক্টরিং স্যুইচ স্টেটমেন্টগুলি সম্পর্কে কয়েকটি সাউন্ড কামড়ের বেশি পড়ার সময় থাকে তবে সি 2 এর স্যুইচ স্টেটমেন্টের গন্ধ সম্পর্কে খুব ভাল ভারসাম্যযুক্ত পৃষ্ঠা রয়েছে ।

এমনকি ওওপি কোডেও প্রতিটি স্যুইচ খারাপ হয় না। এটি আপনি কীভাবে ব্যবহার করছেন এবং কেন।


2

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


2

স্যুইচ স্টেটমেন্টগুলি খারাপ নয়। "স্যুইচ স্ট্যাটাস খারাপ" এর মতো জিনিস বলে এমন লোকদের কথা শুনবেন না! স্যুইচ স্টেটমেন্টের কিছু নির্দিষ্ট ব্যবহার একটি অ্যান্টিপ্যাটার্ন, যেমন সাবক্লাস্টিং অনুকরণ করার জন্য সুইচ ব্যবহার করা। (তবে আপনি যদি এই এন্টিপ্যাটার্নটি ইফ এর সাথেও প্রয়োগ করতে পারেন, তবে আমার ধারণা খুব খারাপ যদি হয়)!

আপনার বাস্তবায়ন ঠিক আছে। আপনি ঠিক বলেছেন আপনি আরও অনেকগুলি রাজ্য যুক্ত করলে রক্ষণাবেক্ষণ করা শক্ত হয়ে উঠবে। তবে এটি কেবল বাস্তবায়নের ইস্যু নয় - অনেকগুলি রাজ্যের সাথে বিভিন্ন আচরণের সাথে একটি বিষয় থাকা নিজেই একটি সমস্যা। আপনার গাড়ীর ছবিতে 25 টি রাজ্য রয়েছে প্রতিটিই আলাদা আলাদা আচরণ এবং রাষ্ট্রের পরিবর্তনের জন্য বিভিন্ন বিধি প্রদর্শন করে। কেবল এই আচরণটি নির্দিষ্ট এবং ডকুমেন্ট করা একটি বিশাল কাজ হবে। আপনার হাজার হাজার রাষ্ট্র-রূপান্তর বিধি থাকবে! এর আকারটি কেবল switchএকটি বৃহত্তর সমস্যার লক্ষণ হবে। সুতরাং যদি সম্ভব হয় তবে এই রাস্তায় নামা এড়িয়ে চলুন।

একটি সম্ভাব্য প্রতিকার হ'ল রাষ্ট্রকে স্বাধীন সাবস্টেটে বিভক্ত করা। উদাহরণস্বরূপ, সত্যই কি ড্রাইভ থেকে পৃথক রাষ্ট্র? সম্ভবত গাড়ির রাজ্যগুলি দুটি ভাঙতে পারে: ইঞ্জিন স্টেট (অফ, আইডিএল, ড্রাইভ) এবং দিকনির্দেশ (ফরোয়ার্ড, রিভার্স)। ইঞ্জিনের অবস্থা এবং দিকনির্দেশনা সম্ভবত বেশিরভাগ স্বতন্ত্র হবে, সুতরাং আপনি যুক্তির সদৃশ এবং রাষ্ট্রের রূপান্তর বিধি হ্রাস করবেন। সংখ্যক রাজ্যের একক অবজেক্টের তুলনায় কম রাজ্যের বেশি বস্তু পরিচালনা করা অনেক সহজ।


1

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

আমার প্রথম পরামর্শটি হ'ল রূপান্তরটির যুক্তিটিকে তার নিজস্ব ফাংশনে (বা শ্রেণি, যদি আপনার ভাষা প্রথম শ্রেণির ফাংশন সমর্থন করে না) breaking

আমার দ্বিতীয় পরামর্শটি হ'ল রাষ্ট্রের মধ্যেই রূপান্তর যুক্তিটি ভাঙ্গার বিষয়টি বিবেচনা করা, যার নিজস্ব ফাংশন (বা শ্রেণি, যদি আপনার ভাষা প্রথম শ্রেণির ফাংশন সমর্থন করে না)।

উভয়ই স্কিমে, রাষ্ট্রের পরিবর্তনের প্রক্রিয়াটি এরকম কিছু দেখবে:

mycar.transition()

অথবা

mycar.state.transition()

দ্বিতীয়টি অবশ্যই প্রথম শ্রেণীর মতো দেখতে তুচ্ছভাবে গাড়ী শ্রেণিতে আবৃত হতে পারে।

উভয় পরিস্থিতিতে, একটি নতুন রাষ্ট্র যুক্ত করা (বলুন, ড্রাফ্টিং) কেবলমাত্র একটি নতুন ধরণের স্টেট অবজেক্ট যুক্ত করা এবং সেই বস্তুগুলিকে পরিবর্তন করা যা বিশেষত নতুন রাজ্যে স্যুইচ করে।


0

এটি কতটা বড় switchহতে পারে তার উপর নির্ভর করে ।

আপনার উদাহরণে, আমি মনে করি switchএটি ঠিক আছে যেহেতু আপনার কাছে Carথাকতে পারে এমন কোনও রাজ্যই আমি ভাবতে পারি না , তাই এটি সময়ের সাথে বড় হতে পারে না।

যদি একমাত্র ইস্যুতে একটি বৃহত্তর সুইচ থাকে যেখানে প্রত্যেকের caseকাছে প্রচুর নির্দেশনা থাকে তবে কেবল প্রত্যেকের জন্য আলাদা আলাদা ব্যক্তিগত পদ্ধতি তৈরি করুন।

কখনও কখনও লোকেরা রাষ্ট্রের নকশা বিন্যাসের পরামর্শ দেয় তবে আপনি জটিল যুক্তি মোকাবেলা করার সময় এটি আরও উপযুক্ত, এবং বিভিন্ন স্বতন্ত্র ক্রিয়াকলাপের জন্য বিভিন্ন ব্যবসায়িক সিদ্ধান্ত নেওয়ার বিষয়ে রাজ্যগুলি। অন্যথায়, সহজ সমস্যার সরল সমাধান হওয়া উচিত।

কিছু পরিস্থিতিতে, আপনার কাছে এমন পদ্ধতি থাকতে পারে যা কেবল তখনই কার্য সম্পাদন করতে পারে যখন রাজ্যটি A বা B হয়, তবে সি বা ডি নয় বা একাধিক পদ্ধতি রয়েছে যা খুব সাধারণ ক্রিয়াকলাপের সাথে রাজ্যের উপর নির্ভরশীল। তারপরে এক বা একাধিক switchবক্তব্য আরও ভাল হবে।


0

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

অন্যরা যেমন বলেছে, স্যুইচ স্টেটমেন্টগুলির সাথে অন্তর্নিহিত কোনও ভুল নেই। বিকল্পগুলি প্রায়শই আরও জটিল এবং বোঝা শক্ত।

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

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