কৌশল প্যাটার্ন তাৎপর্যপূর্ণ শাখা ছাড়াই বাস্তবায়ন করা যায়?


14

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

কারখানার:

// All of these classes implement OrderStrategy
switch (orderType) {
case NEW_ORDER: return new NewOrder();
case CANCELLATION: return new Cancellation();
case RETURN: return new Return();
}

এর পরে কোডটি উদ্বিগ্ন হওয়ার দরকার নেই, এবং এখন একটি নতুন অর্ডার প্রকার যুক্ত করার জন্য কেবলমাত্র একটি জায়গা রয়েছে, তবে কোডের এই বিভাগটি এখনও বর্ধিত নয়। এটি একটি ডেটা ফাইলের মধ্যে টান দিয়ে পঠনযোগ্যতা কিছুটা সহায়তা করে (বিতর্কযোগ্য, আমি জানি):

<strategies>
   <order type="NEW_ORDER">com.company.NewOrder</order>
   <order type="CANCELLATION">com.company.Cancellation</order>
   <order type="RETURN">com.company.Return</order>
</strategies>

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

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

এই জটিলতা প্রশমিত করার কৌশল বিন্যাস বাস্তবায়নের কোন উপায় আছে কি? বা এটি যেমনটি পায় ঠিক তত সহজ এবং আরও এগিয়ে যাওয়ার চেষ্টা করলে সামান্য লাভের জন্য বিমূর্ততার আরও একটি স্তর যুক্ত হবে?


হুমম্মমম .... এই জাতীয় জিনিসগুলির সাথে জিনিসগুলি সহজ করা সম্ভব হতে পারে eval... জাভাতে কাজ করবে না তবে অন্য ভাষায় হতে পারে?
হতাশ

1
@ ফ্রাস্ট্রেটেড উইথফোর্ডস ডিজাইনার প্রতিবিম্ব হ'ল জাভাতে যাদু শব্দ
র‌্যাচেট ফ্রিক

2
আপনার এখনও কোথাও এই শর্তগুলির প্রয়োজন হবে। তাদের কারখানায় ঠেলা দিয়ে, আপনি কেবল ডিআরওয়াইয়ের সাথে সম্মতি দিচ্ছেন, অন্যথায় যদি বা সুইচ বিবৃতিটি একাধিক জায়গায় উপস্থিত হতে পারে।
ড্যানিয়েল বি

1
আপনি যে ত্রুটিটির কথা বলছেন তা প্রায়শই ওপেন-ক্লোজড-প্রসিপিলের লঙ্ঘন
k3b

সম্পর্কিত প্রশ্নের স্বীকৃত উত্তর অভিধান / মানচিত্রের বিকল্প হিসাবে যদি-অন্যটি এবং স্যুইচ-এর বিকল্প হিসাবে প্রস্তাবিত করে
gnat

উত্তর:


16

অবশ্যই না. এমনকি আপনি যদি আইওসি পাত্রে ব্যবহার করেন তবে আপনার কোথাও শর্ত থাকতে হবে, সিদ্ধান্ত নেবেন যে কোন কংক্রিটের প্রয়োগ কার্যকর করা হবে। এটি কৌশল প্যাটার্নের প্রকৃতি।

লোকেরা কেন এটি একটি সমস্যা বলে মনে হয় তা আমি সত্যিই দেখছি না। কিছু বইতে ফাউলারের রিফ্যাক্টরিংয়ের মতো বিবৃতি রয়েছে যে আপনি যদি অন্য কোডের মাঝামাঝি একটি স্যুইচ / কেস বা যদি / এলসগুলির একটি শৃঙ্খলা দেখতে পান তবে আপনার সেই গন্ধ বিবেচনা করা উচিত এবং এটিকে তার নিজস্ব পদ্ধতিতে স্থানান্তরিত করা উচিত। যদি প্রতিটি ক্ষেত্রে কোডটি একটি লাইনের চেয়ে বেশি হয়, তবে দুটি হতে পারে, তবে আপনার সেই পদ্ধতিটিকে ফ্যাক্টরি পদ্ধতি হিসাবে বিবেচনা করা উচিত, কৌশলগুলি ফিরে আসবে।

কিছু লোক এটিকে বোঝায় যে একটি স্যুইচ / কেসটি খারাপ। এই ক্ষেত্রে না হয়. তবে এটি যদি সম্ভব হয় তবে এটি নিজেরাই থাকা উচিত।


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

স্যুইচ স্টেটমেন্টগুলি (এবং দীর্ঘ যদি / অন্যথায়-যদি ব্লক হয়) খারাপ হয় এবং আপনার কোডটি বজায় রাখার জন্য যদি সম্ভব হয় তবে তা এড়ানো উচিত। এটি বলেছিল "যদি সম্ভব হয় তবে" স্বীকার করে যে এমন কিছু ক্ষেত্রে আছে যেখানে স্যুইচ থাকতে হবে, এবং এই ক্ষেত্রে এটি একটি এক জায়গায় রাখার চেষ্টা করুন, এবং এটি একটি কাজকে কম রাখার চেষ্টা করে (এটি এত সহজ) দুর্ঘটনাক্রমে আপনি কোডটি সঠিকভাবে বিচ্ছিন্ন না করার সময় কোডের 5 টির মধ্যে 1 টি মিস করুন you
শ্যাডো ম্যান

10

কৌশল প্যাটার্ন তাৎপর্যপূর্ণ শাখা ছাড়াই বাস্তবায়ন করা যায়?

হ্যাঁ , একটি হ্যাশম্যাপ / অভিধান ব্যবহার করে যেখানে প্রতিটি কৌশল বাস্তবায়িত হয়। কারখানার পদ্ধতিটি এমন কিছু হয়ে যাবে

Class strategyType = allStrategies[orderType];
return runtime.create(strategyType);

প্রতিটি কৌশল বাস্তবায়নের জন্য কারখানার অর্ডার টাইপ এবং শ্রেণি তৈরির উপায় সম্পর্কে কিছু তথ্য অবশ্যই কারখানায় নিবন্ধভুক্ত করতে হবে।

factory.register(NEW_ORDER, NewOrder.class);

আপনার ভাষা যদি এটি সমর্থন করে তবে আপনি নিবন্ধের জন্য স্থিতিক নির্মাণকারী ব্যবহার করতে পারেন।

রেজিস্টার পদ্ধতি হ্যাশম্যাপে নতুন মান যুক্ত করা ছাড়া আর কিছুই করে না:

void register(OrderType orderType, Class class)
{
   allStrategies[orderType] = class;
}

[আপডেট 2012-05-04]
এই সমাধানটি মূল "স্যুইচ সমাধান" এর চেয়ে অনেক জটিল, যা আমি বেশিরভাগ সময় পছন্দ করি prefer

তবে এমন পরিবেশে যেখানে কৌশলগুলি প্রায়শই পরিবর্তিত হয় (যেমন গ্রাহক, সময়, .... উপর নির্ভর করে দামের গণনা) আইওসি-কনটেইনার সাথে মিলিত এই হ্যাশম্যাপ সমাধানটি ভাল সমাধান হতে পারে।


3
সুতরাং এখন আপনি কৌশল একটি পুরো হাশম্যাপ পেয়েছেন, একটি স্যুইচ / কেস এড়াতে? সারিগুলির factory.register(NEW_ORDER, NewOrder.class);চেয়ে ক্লিনারগুলির সারিগুলি কীভাবে , বা ওসিপির কম লঙ্ঘন হয় case NEW_ORDER: return new NewOrder();?
পিডিআর

5
এটি মোটেই পরিষ্কার নয় is এটা পাল্টা স্বজ্ঞাত। এটি উন্মুক্ত-বন্ধ-প্রসিপলকে উন্নত করতে এটি-স্টিপল-মূর্খ-নীতিটিকে ত্যাগ করে। বিপর্যয়-নিয়ন্ত্রণ এবং নির্ভরতা-ইনজেকশন ক্ষেত্রেও এটি একই প্রযোজ্য: সাধারণ সমাধানের চেয়ে এগুলি বোঝা আরও কঠিন। প্রশ্ন ছিল "বাস্তবায়ন ... উল্লেখযোগ্য শাখাবিন্যাস ছাড়া" এবং "কিভাবে আরও বেশি ধারণাসম্পন্ন soltuion তৈরি করতে"
k3b

1
আমি দেখতে পাচ্ছি না যে আপনিও শাখা প্রশাখা এড়িয়ে গেছেন। আপনি এখনই বাক্য গঠন পরিবর্তন করেছেন।
পিডিআর

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

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

2

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


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

@dmux: অবশ্যই, আমার উত্তরটি তদনুসারে সম্পাদিত।
ডক ব্রাউন

1

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

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


1

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

enum FactoryType {
   Type1(Type1.class),
   Type2(Type2.class);

   private Class<? extends Type> clazz;

   private FactoryType(Class<? extends Type> clazz) {
      this.clazz = clazz;
   }

   public Class<? extends Type> getTypeClass() {
      return clazz;
   }
}

এটি মারাত্মকভাবে কারখানার কোড হ্রাস করে:

public Type create(FactoryType type) throws Exception {
   return type.getTypeClass().newInstance();
}

(দয়া করে দরিদ্র ত্রুটি পরিচালনা - উদাহরণ কোড :) উপেক্ষা করুন

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


হোম পেজে ফিরে যাওয়ার কারণ কী তা নিশ্চিত নয় তবে এটি একটি ভাল উত্তর এবং জাভা 8-এ আপনি এখন প্রতিফলন ছাড়াই কনস্ট্রাক্টর রেফারেন্স তৈরি করতে পারেন।
জিমি জেমস

1

প্রতিটি শ্রেণীর নিজস্ব আদেশের ধরণ নির্ধারণের মাধ্যমে এক্সটেনসিবিলিটি উন্নত করা যায়। তারপরে আপনার কারখানাটি মেলে এমন একটি নির্বাচন করে।

উদাহরণ স্বরূপ:

public interface IOrderStrategy
{
    OrderType OrderType { get; }
}

public class NewOrder : IOrderStrategy
{
    public OrderType OrderType { get; } = OrderType.NewOrder;
}

public class OrderFactory
{
    private IEnumerable<IOrderStrategy> _strategies;

    public OrderFactory(IEnumerable<IOrderStrategy> strategies) // Injected by IoC container
    {
        _strategies = strategies;
    }

    public IOrderStrategy Create(OrderType orderType)
    {
        IOrderStrategy strategy = _strategies.FirstOrDefault(s => s.OrderType == orderType);

        if (strategy == null)
            throw new ArgumentException("Invalid order type.", nameof(orderType));

        return strategy;
    }
}

1

আমি মনে করি কতগুলি শাখা গ্রহণযোগ্য তা নিয়ে একটি সীমা থাকা উচিত।

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

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

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