পলিমারফিজমের সাথে শর্তাধীন একটি সঠিক উপায়ে প্রতিস্থাপন করবেন?


10

দুটি ক্লাস Dogএবং Catউভয় Animalপ্রোটোকল অনুসারে বিবেচনা করুন (সুইফ্ট প্রোগ্রামিং ভাষার ক্ষেত্রে। এটি জাভা / সি # তে ইন্টারফেস হবে)।

আমাদের কাছে একটি স্ক্রিন রয়েছে যা কুকুর এবং বিড়ালের মিশ্রিত তালিকা প্রদর্শন করে। এমন Interactorক্লাস রয়েছে যা পর্দার আড়ালে যুক্তি পরিচালনা করে।

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

func tryToDeleteModel(model: Animal) {
    if let model = model as? Cat {
        tellSceneToShowConfirmationAlert()
    } else if let model = model as? Dog {
        deleteModel(model: model)
    }
}

এই কোডটি কীভাবে রিফ্যাক্টর করা যেতে পারে? এটা অবশ্যই গন্ধ

উত্তর:


9

আপনি নিজেরাই প্রোটোকল টাইপ আচরণ নির্ধারণ করতে দিচ্ছেন। আপনি বাস্তবায়নকারী শ্রেণি ব্যতীত আপনার প্রোগ্রামে সমস্ত প্রোটোকলকে একইরূপে আচরণ করতে চান । পারেন এই ভাবে করছেন Liskov এর উপকল্পন নীতি, যা আপনি পাস করতে সক্ষম হওয়া উচিত বলে সম্মান করা হয় Catবা Dog(অথবা অন্য কোন প্রোটোকল আপনাকে অবশেষে অধীনে থাকতে পারে Animalসম্ভাব্য), এবং এটি উদাসীনভাবে কাজ আছে।

তাই সম্ভবতঃ আপনি একটি অ্যাড চাই isCriticalথেকে func Animalউভয় দ্বারা বাস্তবায়িত করা Dogএবং Cat। যে কোনও বাস্তবায়নই Dogমিথ্যা প্রত্যাবর্তন করবে এবং বাস্তবায়নকৃত কিছু Catসত্যই আসবে।

এই মুহুর্তে, আপনাকে কেবলমাত্র করতে হবে (সিনট্যাক্স সঠিক না হলে আমার ক্ষমা চাই। সুইফ্টের কোনও ব্যবহারকারী নয়):

func tryToDeleteModel(model: Animal) {
    if model.isCritical() {
        tellSceneToShowConfirmationAlert()
    } else {
        deleteModel(model: model)
    }
}

এটির সাথে কেবল একটি ছোট সমস্যা রয়েছে এবং এটি হ'ল Dogএবং Catএটি প্রোটোকল, অর্থ তারা নিজেরাই isCriticalসিদ্ধান্ত নেওয়ার জন্য প্রতিটি বাস্তবায়নকারী শ্রেণীর কাছে রেখে কী ফিরে আসে তা নির্ধারণ করে না। আপনি বাস্তবায়নের অনেক আছে, তাহলে এটি সম্ভবত একটি extendable বর্গ তৈরি করার জন্য আপনার সময় মূল্য হবে Catবা Dogযা ইতিমধ্যে সঠিকভাবে কার্যকরী isCriticalএবং কার্যকরভাবে ওভাররাইড করার প্রয়োজনীয়তা থেকে সব implementating শ্রেণীর ক্লিয়ারিং isCritical

যদি এটি আপনার প্রশ্নের উত্তর না দেয় তবে দয়া করে মন্তব্যে লিখুন এবং আমি আমার উত্তরটি সেই অনুযায়ী প্রসারিত করব!


এটি প্রশ্নের বিবৃতিতে কিছুটা অস্পষ্ট, তবে Dogএবং Catএটি ক্লাস হিসাবে বর্ণিত হয়েছে, যখন Animalএমন একটি প্রোটোকল যা এই ক্লাসগুলির প্রতিটি দ্বারা প্রয়োগ করা হয়। সুতরাং প্রশ্ন এবং আপনার উত্তরের মধ্যে কিছুটা অমিল আছে।
কালেব

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

হ্যাঁ, অস্পষ্ট প্রশ্ন সম্পর্কে দুঃখিত, আমি কয়েকটি সম্পাদনা করেছি। এখন আরও পরিষ্কার হওয়া উচিত
আন্দ্রে গর্দিভ

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

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

4

জিজ্ঞাসা করুন বনাম

আপনি যে শর্তযুক্ত পন্থা দেখিয়েছেন সেটিকে আমরা " জিজ্ঞাসা " বলব । এইখানে গ্রাসকারী ক্লায়েন্ট জিজ্ঞাসা করে "আপনি কেমন আছেন?" এবং সেই অনুসারে বস্তুর সাথে তাদের আচরণ এবং মিথস্ক্রিয়াটিকে কাস্টমাইজ করে।

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

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

গ্রাহক গ্রাহক সর্বদা এটি নির্দিষ্ট সাবক্লাসের সাথে কাজ না করে তা নিশ্চিতকরণের পদ্ধতিটি ব্যবহার করবেন, যা জিজ্ঞাসার পরিবর্তে মিথস্ক্রিয়াটিকে বলায়

(আরেকটি পদ্ধতি হ'ল নিশ্চিতকরণটিকে মুছে ফেলার ক্ষেত্রে চাপ দেওয়া, তবে এটি মুছে ফেলা অপারেশন সফল হওয়ার আশা করে এমন গ্রাহকরা অবাক করে দেবে would)


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

2
ঠিক আছে, হ্যাঁ, এটি একটি আলাদা প্রশ্ন, একটি পৃথক উত্তর প্রয়োজন।
এরিক tদ

2

নিশ্চিতকরণের প্রয়োজন আছে কিনা তা নির্ধারণ করা Catশ্রেণীর দায়িত্ব , সুতরাং সেই ক্রিয়াটি সম্পাদন করতে সক্ষম করুন। আমি কোটলিনকে জানি না, তাই আমি সি # তে জিনিস প্রকাশ করব। আশা করি ধারণাগুলি তখন কোটলিনেও স্থানান্তরযোগ্য।

interface Animal
{
    bool IsOkToDelete();
}

class Cat : Animal
{
    private readonly Func<bool> _confirmation;

    public Cat (Func<bool> confirmation) => _confirmation = confirmation;

    public bool IsOkToDelete() => _confirmation();
}

class Dog : Animal
{
    public bool IsOkToDelete() => true;
}

তারপরে, Catউদাহরণ তৈরি করার সময় আপনি এটি সরবরাহ করে TellSceneToShowConfirmationAlertযা trueমুছে ফেলার জন্য যদি ঠিক থাকে তবে ফিরে আসতে হবে :

var model = new Cat(TellSceneToShowConfirmationAlert);

এবং তারপরে আপনার ফাংশনটি হয়ে যায়:

void TryToDeleteModel(Animal model) 
{
    if (model.IsOKToDelete())
    {
        DeleteModel(model)
    }
}

1
এটি কি মোছার যুক্তিকে মুছে ফেলবে না? এটি হ্যান্ডেল করার জন্য অন্য কোনও অবজেক্টটি ব্যবহার করা কি আরও ভাল হবে না? সম্ভবত কোনও অ্যাপ্লিকেশনসেবার ভিতরে <<> অভিধানের মতো একটি ডেটা স্ট্রাকচার; বিড়ালের উপস্থিতি আছে কিনা তা পরীক্ষা করে দেখুন এবং তা যদি নিশ্চিতকরণ সতর্কতা বন্ধ করে দেয়?
keelerjr12

@ keelerjr12, এটি ক্লাসে মুছার জন্য কোনও নিশ্চিতকরণ প্রয়োজন কিনা তা নির্ধারণের জন্য দায়িত্বটি সরিয়ে দেয় Cat। আমি যুক্তি দিয়েছি যে এটিই যেখানে। কীভাবে নিশ্চিতকরণটি অর্জন হয় (এটি ইনজেকশনযুক্ত) এবং এটি নিজেই মুছবে না তা সিদ্ধান্ত নিতে পারে না। সুতরাং না, এটি মোছা যুক্তিকে সরান না।
ডেভিড আরনো

2
আমি অনুভব করি যে এই পদ্ধতির দ্বারা ক্লাসের সাথে সংযুক্ত টোন এবং ইউআই-সম্পর্কিত কোডের টন তৈরি হবে। যদি ক্লাসটি একাধিক UI স্তর জুড়ে ব্যবহারের উদ্দেশ্যে করা হয়, তবে সমস্যাটি বেড়ে যায়। তবে এটি যদি ব্যবসায়ের সত্তার চেয়ে ভিউমোডেল ধরণের শ্রেণি হয় তবে এটি উপযুক্ত বলে মনে হয়।
গ্রাহাম

@ গ্রাহাম, হ্যাঁ এই পদ্ধতির সাথে অবশ্যই এটি ঝুঁকিপূর্ণ: এটি এর TellSceneToShowConfirmationAlertউদাহরণে ইনজেকশন করা সহজ হওয়ার উপর নির্ভর করে Cat। এমন পরিস্থিতিতে যখন এটি কোনও সহজ জিনিস নয় (যেমন কোনও বহু-স্তরযুক্ত সিস্টেমে যেখানে এই কার্যকারিতাটি গভীর স্তরে রয়েছে), তবে এই পদ্ধতিটি ভাল হবে না।
ডেভিড আরনো

1
ঠিক কি আমি পেয়েছিলাম। একটি ভিউমোডেল ক্লাস বনাম একটি ব্যবসায়ের সত্তা। ব্যবসায় ডোমেনে, কোনও বিড়ালকে ইউআই সম্পর্কিত কোড সম্পর্কে জানতে হবে না। আমার পরিবারের বিড়াল কাউকে সতর্ক করে না। ধন্যবাদ!
keelerjr12

1

আমি একটি দর্শনার্থী প্যাটার্ন জন্য যেতে পরামর্শ চাই। আমি জাভাতে একটি ছোট বাস্তবায়ন করেছি। আমি সুইফ্টের সাথে পরিচিত নই, তবে আপনি এটিকে সহজেই মানিয়ে নিতে পারেন।

ভ্রমণকারী

public interface AnimalVisitor<R>{
    R visitCat();
    R visitDog();
}

আপনার মডেল

abstract class Animal { // can also be an interface like VisitableAnimal
    abstract <R> R accept(AnimalVisitor<R> visitor);
}

class Cat extends Animal {
    public <R> R accept(AnimalVisitor<R> visitor) {
         return visitor.visitCat();
     }
}

class Dog extends Animal {
    public <R> R accept(AnimalVisitor<R> visitor) {
         return visitor.visitDog();
     }
}

দর্শনার্থীকে ফোন করা

public void tryToDelete(Animal animal) {
    animal.accept( new AnimalVisitor<Void>() {
        public Void visitCat() {
            tellSceneToShowConfirmation();
            return null;
        }

        public Void visitDog() {
            deleteModel(animal);
            return null;
        }
    });
}

আপনার পছন্দমতো অ্যানিম্যালভিসিটারের যতটা বাস্তবায়ন থাকতে পারে।

উদাহরণ:

public void isColorValid(Color color) {
    animal.accept( new AnimalVisitor<Boolean>() {
        public Boolean visitCat() {
            return Color.BLUE.equals(color);
        }

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