জাভাতে আর্গুমেন্ট সহ সিঙ্গলটন


142

আমি উইকিপিডিয়ায় সিঙ্গলটন নিবন্ধটি পড়ছিলাম এবং আমি এই উদাহরণটি পেয়েছিলাম:

public class Singleton {
    // Private constructor prevents instantiation from other classes
    private Singleton() {}

    /**
     * SingletonHolder is loaded on the first execution of Singleton.getInstance() 
     * or the first access to SingletonHolder.INSTANCE, not before.
     */
    private static class SingletonHolder { 
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

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

public class Singleton
{
    private static Singleton singleton = null;  
    private final int x;

    private Singleton(int x) {
        this.x = x;
    }

    public synchronized static Singleton getInstance(int x) {
        if(singleton == null) singleton = new Singleton(x);
        return singleton;
    }
}

ধন্যবাদ!


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

// AbstractTask implements Serializable
public class Task extends AbstractTask
{
    private final ReferenceToReallyBigObject object;

    public Task(ReferenceToReallyBigObject object)
    {
        this.object = object;
    }

    public void run()
    {
        // Do some stuff with the object (which is immutable).
    }
}

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

// AbstractTask implements Serializable
public class Task extends AbstractTask
{
    private static ReferenceToReallyBigObject object = null;

    private final String filePath;

    public Task(String filePath)
    {
        this.filePath = filePath;
    }

    public void run()
    {
        synchronized(this)
        {
            if(object == null)
            {
                ObjectReader reader = new ObjectReader(filePath);
                object = reader.read();
            }
        }

        // Do some stuff with the object (which is immutable).
    }
}

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


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

2
এটি অত্যন্ত দুর্ভাগ্যজনক যে আপনি সিঙ্গেলটন শব্দটি ব্যবহার করেছিলেন যা এই জাতীয় ব্যাগ সহ আসে। এই প্যাটার্নের জন্য উপযুক্ত শব্দটি আসলে ইন্টার্নিং। অন্তর্নিহিত এমন একটি পদ্ধতি যা নিশ্চিত করা যায় যে বিমূর্ত মানগুলি কেবলমাত্র একটি উদাহরণ দ্বারা প্রতিনিধিত্ব করা হয়। স্ট্রিং ইন্টার্নিং সর্বাধিক সাধারণ ব্যবহার: en.wikedia.org/wiki/String_intern_pool।
অপরিচিত

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

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

2
"প্যারামিটার সহ সিঙ্গলটন" এর জন্য আরেকটি দৃশ্য: একটি ওয়েব অ্যাপ্লিকেশন যা একেবারে আগত অনুরোধের (থ্রেড) সাথে আগত তথ্যের উপর ভিত্তি করে তার অনন্য অপরিবর্তনীয় সিঙ্গলটন তৈরি করবে। অনুরোধটির ডোমেন কিছু
সিঙ্গেলনের

উত্তর:


171

আমি আমার বক্তব্যটি খুব পরিষ্কার করব: পরামিতিগুলির সাথে একটি সিঙ্গলটন কোনও সিঙ্গলটন নয়

সংজ্ঞা অনুসারে একটি সিঙ্গলটন হ'ল এমন একটি বস্তু যা আপনি একবারের চেয়ে আরও একবার ইনস্ট্যান্ট করতে চান। আপনি যদি কনস্ট্রাক্টরকে প্যারামিটারগুলি খাওয়ানোর চেষ্টা করছেন, তবে সিঙ্গেলনের কী লাভ?

আপনার কাছে দুটি বিকল্প রয়েছে। আপনি যদি চান যে আপনার সিঙ্গলটনটি কিছু ডেটা দিয়ে শুরু করা যেতে পারে তবে আপনি ইনস্ট্যান্টেশনের পরে ডেটা দিয়ে এটি লোড করতে পারেন:

SingletonObj singleton = SingletonObj.getInstance();
singleton.init(paramA, paramB); // init the object with data

আপনার সিঙ্গলটন যে অপারেশনটি করছে তা পুনরাবৃত্তি হতে চলেছে এবং প্রতিবার বিভিন্ন পরামিতি সহ আপনি যদি প্যারামিটারগুলি মূল পদ্ধতিতে কার্যকর করতে পারেন তবে:

SingletonObj singleton = SingletonObj.getInstance();
singleton.doSomething(paramA, paramB); // pass parameters on execution

যাইহোক, ইনস্ট্যান্টেশন সর্বদা পরামিতি-কম হবে। অন্যথায় আপনার সিঙ্গলটন কোনও সিঙ্গলটন নয়।


1
+1 কোডিং করার সময় আমি সম্ভবত এটি করব। সি # তে, আমি যদিও বৈশিষ্ট্যগুলি ব্যবহার করব। জাভা, সম্ভবত এই মত।
জ্যাক

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

1
@ মসি, লেখক হিসাবে বলেছেন - এটি কোনও সিঙ্গলটন নয়। আপনার যদি ধ্রুবক গতিবেগ পাস করতে হয় তবে আপনার বিভিন্ন ধ্রুবক সহ প্রচুর ক্লাস তৈরি করতে হতে পারে। সুতরাং, সিঙ্গলটনের কোনও মানে নেই।
দিমিত্রি জায়েতসেভ

53
আপনার যদি কোনও অ্যাপ্লিকেশনটির পুরো জীবদ্দশায় কেবল ক্লাসের একটি উদাহরণ প্রয়োজন তবে লঞ্চের সময় আপনাকে সেই দৃষ্টান্তটি সরবরাহ করতে হবে তবে কেন এটি আর সিঙ্গলটন নয়?
অস্কার

4
"আপনি যদি কনস্ট্রাক্টরকে প্যারামিটারগুলি খাওয়ানোর চেষ্টা করছেন, তবে সিঙ্গেলনের কী লাভ?" - কেউ এটিও বলতে পারে: "আপনি যদি পুরো অ্যাপ্লিকেশনটিকে একক দৃষ্টান্ত তৈরি করেন, কমান্ড লাইন আর্গুমেন্টের মূল বিষয়টি কী?" এবং উত্তরটি হ'ল এটি প্রচুর অর্থবোধ করে। এখন কেউ বলতে পারে যে এটি একটি সিঙ্গলটন শ্রেণীর চেয়ে মোটামুটি আলাদা, যদি শ্রেণিটি মূল মেইন থেকে মূল পদ্ধতি থেকে অর্গগুলি প্রাপ্ত করে তবেই মূল শ্রেণি হয় - তবে এটি এমনকি একই জিনিস। চূড়ান্ত যুক্তি, যা কেবল দাঁড়াতে পারে, এটি হ'ল এটি বেশ ব্যতিক্রমী পরিস্থিতি situation
ড্রিমস্পেসের রাষ্ট্রপতি

41

আমি মনে করি বিভিন্ন পরামিতি ইনস্ট্যান্টিয়েটেড এবং পুনঃব্যবহারের সাথে অবজেক্টগুলি রাখতে আপনার কারখানার মতো কিছু দরকার । এটি একটি সিঙ্ক্রোনাইজড ব্যবহার করে HashMapবা ConcurrentHashMapএকটি প্যারামিটার মানচিত্র প্রয়োগ করা যেতে পারে (একটি)Integer আপনার সিঙ্গেলটন 'প্যারামিটারাইজেবল শ্রেণিতে উদাহরণস্বরূপ) ।

যদিও আপনি সেই জায়গায় পৌঁছে যেতে পারেন যেখানে পরিবর্তে আপনার নিয়মিত, নন-সিঙ্গলটন ক্লাস ব্যবহার করা উচিত (উদাহরণস্বরূপ, 10.000 আলাদাভাবে প্যারামেট্রাইজড সিঙ্গলটন প্রয়োজন)।

এই জাতীয় স্টোরের জন্য এখানে একটি উদাহরণ দেওয়া হয়েছে:

public final class UsefulObjFactory {

    private static Map<Integer, UsefulObj> store =
        new HashMap<Integer, UsefulObj>();

    public static final class UsefulObj {
        private UsefulObj(int parameter) {
            // init
        }
        public void someUsefulMethod() {
            // some useful operation
        }
    }

    public static UsefulObj get(int parameter) {
        synchronized (store) {
            UsefulObj result = store.get(parameter);
            if (result == null) {
                result = new UsefulObj(parameter);
                store.put(parameter, result);
            }
            return result;
        }
    }
}

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

তবে, যদি আপনার বিতরণ করা 1 টি সমাধানের প্রয়োজন হয় তবে কিছু পার্শ্বীয় ক্যাশিং সমাধান বিবেচনা করুন। উদাহরণস্বরূপ: EHCache, টেরাকোটা ইত্যাদি

একাধিক কম্পিউটারে একাধিক ভিএম বিস্তৃত করার অর্থে 1


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

1
এটি কোনও সিঙ্গলটন নয় ; আপনার এখন তাদের মধ্যে একটিরও বেশি রয়েছে। উচ্চহাস্য
oxbow_lakes

@ স্কট: আমি ইউভাল নীচে যা বলেছিলাম তার মতো কিছু প্রস্তাব দেব। এটি আরও কিছুটা অর্থবোধ করে এবং আপনার একটি 'সত্য' সিঙ্গলটন রয়েছে। সম্পাদনা করুন
জ্যাক

আমি আশা করি কোডে নামগুলি সম্পাদনা করার বিষয়ে কেউ আমাকে মনে করবে না; আমি ভাবতে পারি এটি নবজাতকের জন্য সত্যই বিভ্রান্তিকর। রোলব্যাক যদি আপনি একমত না হন
অক্সবো_লাক

হ্যাঁ, আমরা তাদের মাল্টিট্রন বলতে পারি এবং এখনও ওপি প্রথম স্থান আইএমএইচওতে চেয়েছিল একই লক্ষ্য অর্জন করতে পারে।
আকনারোকদ

22

প্রাপ্তি থেকে ইনস্ট্যান্টেশন পৃথক করতে আপনি একটি কনফিগারযোগ্য সূচনা পদ্ধতি যুক্ত করতে পারেন।

public class Singleton {
    private static Singleton singleton = null;
    private final int x;

    private Singleton(int x) {
        this.x = x;
    }

    public static Singleton getInstance() {
        if(singleton == null) {
            throw new AssertionError("You have to call init first");
        }

        return singleton;
    }

    public synchronized static Singleton init(int x) {
        if (singleton != null)
        {
            // in my opinion this is optional, but for the purists it ensures
            // that you only ever get the same instance when you call getInstance
            throw new AssertionError("You already initialized me");
        }

        singleton = new Singleton(x);
        return singleton;
    }

}

তারপরে আপনি Singleton.init(123)এটিটি কনফিগার করতে একবার কল করতে পারেন , উদাহরণস্বরূপ আপনার অ্যাপ্লিকেশন প্রারম্ভকালে।


13

আপনি যদি কিছু প্যারামিটার বাধ্যতামূলক হয় তা দেখাতে চান তবে আপনি বিল্ডার প্যাটার্নটিও ব্যবহার করতে পারেন।

    public enum EnumSingleton {

    INSTANCE;

    private String name; // Mandatory
    private Double age = null; // Not Mandatory

    private void build(SingletonBuilder builder) {
        this.name = builder.name;
        this.age = builder.age;
    }

    // Static getter
    public static EnumSingleton getSingleton() {
        return INSTANCE;
    }

    public void print() {
        System.out.println("Name "+name + ", age: "+age);
    }


    public static class SingletonBuilder {

        private final String name; // Mandatory
        private Double age = null; // Not Mandatory

        private SingletonBuilder(){
          name = null;
        }

        SingletonBuilder(String name) {
            this.name = name;
        }

        public SingletonBuilder age(double age) {
            this.age = age;
            return this;
        }

        public void build(){
            EnumSingleton.INSTANCE.build(this);
        }

    }


}

তারপরে আপনি এটিকে নিম্নরূপে তৈরি / ইনস্ট্যান্টিয়েট / প্যারামাইট্রাইজ করতে পারলেন :

public static void main(String[] args) {
    new EnumSingleton.SingletonBuilder("nico").age(41).build();
    EnumSingleton.getSingleton().print();
}

6

" প্যারামিটার সহ একটি সিঙ্গলটন সিঙ্গলটন নয় " বিবৃতিটি সম্পূর্ণ সঠিক নয় । কোড দৃষ্টিকোণ না হয়ে আমাদের অ্যাপ্লিকেশন দৃষ্টিকোণ থেকে এটি বিশ্লেষণ করা দরকার।

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

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


12
এটি ওপি প্রশ্নের উত্তর নয়, এটি একটি মন্তব্য হওয়া উচিত।
থিয়েরি জে

5

ভেরিয়েবল সেট করতে ডিফল্ট কনস্ট্রাক্টরকে বেসরকারী করতে গিটার এবং সেটটার ব্যবহার করুন। তারপরে ব্যবহার করুন:

Singleton.getInstance().setX(value);

1
কেন এটিকে নিম্ন-ভোট দেওয়া হয়েছে তা পাবেন না .. এটি একটি বৈধ উত্তর tbh। : /
জ্যাক

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

5

অবাক করে দিয়েছিলেন যে কোনও লগার কীভাবে তৈরি / পুনরুদ্ধার করা হয় তা কেউ উল্লেখ করেনি। উদাহরণস্বরূপ, নীচে লগ 4 জে লগার কীভাবে পুনরুদ্ধার করা হয় তা দেখায় ।

// Retrieve a logger named according to the value of the name parameter. If the named logger already exists, then the existing instance will be returned. Otherwise, a new instance is created.
public static Logger getLogger(String name)

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

69   Hashtable ht;
...
258  public
259  Logger getLogger(String name, LoggerFactory factory) {
260    //System.out.println("getInstance("+name+") called.");
261    CategoryKey key = new CategoryKey(name);
262    // Synchronize to prevent write conflicts. Read conflicts (in
263    // getChainedLevel method) are possible only if variable
264    // assignments are non-atomic.
265    Logger logger;
266
267    synchronized(ht) {
268      Object o = ht.get(key);
269      if(o == null) {
270        logger = factory.makeNewLoggerInstance(name);
271        logger.setHierarchy(this);
272        ht.put(key, logger);
273        updateParents(logger);
274        return logger;
275      } else if(o instanceof Logger) {
276        return (Logger) o;
277      } 
...

4

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

public final class RInterfaceHL {

    /**
     * Private constructor prevents instantiation from other classes.
     */
    private RInterfaceHL() { }

    /**
     * R REPL (read-evaluate-parse loop) handler.
     */
    private static RMainLoopCallbacks rloopHandler = null;

    /**
     * SingletonHolder is loaded, and the static initializer executed, 
     * on the first execution of Singleton.getInstance() or the first 
     * access to SingletonHolder.INSTANCE, not before.
     */
    private static final class SingletonHolder {

        /**
         * Singleton instance, with static initializer.
         */
        private static final RInterfaceHL INSTANCE = initRInterfaceHL();

        /**
         * Initialize RInterfaceHL singleton instance using rLoopHandler from
         * outer class.
         * 
         * @return RInterfaceHL instance
         */
        private static RInterfaceHL initRInterfaceHL() {
            try {
                return new RInterfaceHL(rloopHandler);
            } catch (REngineException e) {
                // a static initializer cannot throw exceptions
                // but it can throw an ExceptionInInitializerError
                throw new ExceptionInInitializerError(e);
            }
        }

        /**
         * Prevent instantiation.
         */
        private SingletonHolder() {
        }

        /**
         * Get singleton RInterfaceHL.
         * 
         * @return RInterfaceHL singleton.
         */
        public static RInterfaceHL getInstance() {
            return SingletonHolder.INSTANCE;
        }

    }

    /**
     * Return the singleton instance of RInterfaceHL. Only the first call to
     * this will establish the rloopHandler.
     * 
     * @param rloopHandler
     *            R REPL handler supplied by client.
     * @return RInterfaceHL singleton instance
     * @throws REngineException
     *             if REngine cannot be created
     */
    public static RInterfaceHL getInstance(RMainLoopCallbacks rloopHandler)
            throws REngineException {
        RInterfaceHL.rloopHandler = rloopHandler;

        RInterfaceHL instance = null;

        try {
            instance = SingletonHolder.getInstance();
        } catch (ExceptionInInitializerError e) {

            // rethrow exception that occurred in the initializer
            // so our caller can deal with it
            Throwable exceptionInInit = e.getCause();
            throw new REngineException(null, exceptionInInit.getMessage());
        }

        return instance;
    }

    /**
     * org.rosuda.REngine.REngine high level R interface.
     */
    private REngine rosudaEngine = null;

    /**
     * Construct new RInterfaceHL. Only ever gets called once by
     * {@link SingletonHolder.initRInterfaceHL}.
     * 
     * @param rloopHandler
     *            R REPL handler supplied by client.
     * @throws REngineException
     *             if R cannot be loaded.
     */
    private RInterfaceHL(RMainLoopCallbacks rloopHandler)
            throws REngineException {

        // tell Rengine code not to die if it can't
        // load the JRI native DLLs. This allows
        // us to catch the UnsatisfiedLinkError
        // ourselves
        System.setProperty("jri.ignore.ule", "yes");

        rosudaEngine = new JRIEngine(new String[] { "--no-save" }, rloopHandler);
    }
}

আমার মনে হয় এটা এটি একটি ভাল ধারণা হবে finally { RInterfaceHL.rloopHandler = null; }যে getInstance, কারণ যে স্ট্যাটিক উল্লেখকে একটি মেমরি লিক হতে পারে যদি আমরা সতর্ক না। আপনার ক্ষেত্রে এটি দেখে মনে হচ্ছে এটি কোনও সমস্যা নয়, তবে আমি এমন একটি দৃশ্য কল্পনা করতে পারি যেখানে পাস-ইন করা অবজেক্টটি বড় এবং কেবলমাত্র RInterfaceHLকিছু মূল্যবোধ পেতে ctor দ্বারা ব্যবহৃত হয় , এবং এটিতে কোনও উল্লেখ রাখতে না পারে।
TWiStErRob

আইডিয়া: return SingletonHolder.INSTANCEঠিক ঠিক হিসাবে কাজ করবে getInstance। আমি মনে করি না এখানে এখানে এনক্যাপসুলেশন প্রয়োজন, কারণ বাইরের শ্রেণি ইতিমধ্যে অভ্যন্তর শ্রেণীর অভ্যন্তরীণ স্থানগুলি জানে, তারা দৃly়ভাবে একত্রিত হয়: rloopHandlerকল করার আগে এটি প্রাথমিকভাবে জানে । এছাড়াও বেসরকারী নির্মাণকারীর কোনও প্রভাব নেই, কারণ অভ্যন্তরীণ শ্রেণীর 'ব্যক্তিগত জিনিসগুলি কেবল বহিরাগত শ্রেণীর জন্য উপলব্ধ to
TWiStErRob

1
লিঙ্কটি নষ্ট হয়ে গেছে। আপনি কি en.wikedia.org/wiki/Initialization-on-demand_holder_idiom- কে উল্লেখ করছেন ?
জোর্হে ল্যাভন

3

আপনি যা করার চেষ্টা করছেন তা কীভাবে সম্পাদন করবেন তা আপনি বোধগম্য করতে না পারার কারণ সম্ভবত আপনি যা করার চেষ্টা করছেন তা বাস্তবে অর্থবোধ করে না। আপনি getInstance(x)বিভিন্ন যুক্তি দিয়ে কল করতে চান , কিন্তু সর্বদা একই বস্তুটি ফেরত চান? কি আচরণ এটাকে যদি আপনি চান যখন আপনি কল getInstance(2)এবং তারপরgetInstance(5) ?

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

অন্যদিকে, যদি আপনি চান getInstance(2)এবং getInstance(5)বিভিন্ন জিনিসগুলি ফিরিয়ে আনতে চান তবে আপনি সিঙ্গলটন প্যাটার্নটি ব্যবহার করছেন না, আপনি কারখানার প্যাটার্নটি ব্যবহার করছেন।


3

আপনার উদাহরণে আপনি একটি সিঙ্গলটন ব্যবহার করছেন না। লক্ষ্য করুন যে আপনি যদি নিম্নলিখিতটি করেন তবে (ধরে নিই যে সিঙ্গলটন.সেটইনস্ট্যান্সটি আসলে স্থিতিশীল ছিল):

Singleton obj1 = Singleton.getInstance(3);
Singleton obj2 = Singleton.getInstance(4);

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

আপনি এই নিবন্ধটি পড়তে চাইতে পারেন কারণ সিলেটলেটগুলি খুব সহজেই অতিরিক্ত ব্যবহার করা যায়।


3

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


3

যদি আপনি প্রসঙ্গ হিসাবে পরিবেশন করা সিঙ্গলটন ক্লাস তৈরি করতে চান, তবে একটি ভাল উপায় হ'ল একটি কনফিগারেশন ফাইল থাকা উচিত এবং ফাইলের অভ্যন্তর হিসাবে প্যারামিটারগুলি পড়া উচিত () read

আপনার প্রোগ্রামটি চলাকালীন যদি সিঙ্গেলটন ক্লাসকে খাওয়ানো প্যারামিটারগুলি গতিশীলভাবে পাওয়া যায় তবে প্রতিটি প্যারামিটার (গুলি) এর জন্য কেবলমাত্র একটি উদাহরণ তৈরি হয়েছে তা নিশ্চিত করার জন্য কেবল আপনার সিঙ্গলটন ক্লাসে বিভিন্ন ঘটনা সংরক্ষণ করে একটি স্ট্যাটিক হ্যাশম্যাপ ব্যবহার করুন।


1

এটি বেশ কয়েকটি সিঙ্গলটন নয়, তবে এমন কিছু হতে পারে যা আপনার সমস্যার সমাধান করতে পারে।

public class KamilManager {

  private static KamilManager sharedInstance;

  /**
   * This method cannot be called before calling KamilManager constructor or else
   * it will bomb out.
   * @return
   */
  public static KamilManager getInstanceAfterInitialized() {
    if(sharedInstance == null)
        throw new RuntimeException("You must instantiate KamilManager once, before calling this method");

    return sharedInstance;
}

  public KamilManager(Context context, KamilConfig KamilConfig) {
    //Set whatever you need to set here then call:
  s  haredInstance = this;
  }
}

1

যদি আমরা "রাষ্ট্রের সাথে সিঙ্গেলটন কীভাবে তৈরি করতে পারি" হিসাবে সমস্যাটি গ্রহণ করি তবে রাষ্ট্রটি কনস্ট্রাক্টর প্যারামিটার হিসাবে পাস করার প্রয়োজন নেই। আমি যে পোস্টগুলিতে রাজ্যগুলির সূচনা করে বা সিঙ্গলটন উদাহরণ পাওয়ার পরে সেট পদ্ধতি ব্যবহার করে সেগুলির সাথে আমি একমত।

আর একটি প্রশ্ন হ'ল রাজ্যের সাথে সিঙ্গলটন থাকা ভাল?


1

আমরা এর মতো কিছু করতে পারি না:

public class Singleton {

    private int x;

    // Private constructor prevents instantiation from other classes
    private Singleton() {}

    /**
     * SingletonHolder is loaded on the first execution of Singleton.getInstance() 
     * or the first access to SingletonHolder.INSTANCE, not before.
     */
    private static class SingletonHolder { 
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance(int x) {
        Singleton instance = SingletonHolder.INSTANCE;
        instance.x = x;
        return instance;
    }
}

1

কিছু কিছু দাবি করতে পারে তা সত্ত্বেও, এখানে কনস্ট্রাক্টরের পরামিতিগুলির সাথে একটি সিঙ্গলটন

public class Singleton {

    private static String aParameterStored;

    private static final Singleton instance = new Singleton("Param to set");

    private Singleton() {
        // do nothing
    }

    private Singleton(String param) {
        aParameterStored = param;
    }

    public static Singleton getInstance() {
        return instance;
    }

    /*
     * ... stuff you would like the singleton do
     */
}

একক প্যাটার্ন বলে:

  • সিঙ্গলটন শ্রেণীর কেবলমাত্র একটি উদাহরণ উপস্থিত রয়েছে তা নিশ্চিত করুন
  • এই দৃষ্টিতে বিশ্বব্যাপী অ্যাক্সেস সরবরাহ করুন।

যা এই উদাহরণ দিয়ে সম্মানিত হয়।

কেন সরাসরি সম্পত্তি সেট করবেন না? এটি পরামিতি সহ কনস্ট্রাক্টর থাকা একটি সিঙ্গলটন পেতে পারি তবে এটি কিছু পরিস্থিতিতে কার্যকর হতে পারে তা দেখানোর জন্য এটি পাঠ্যপুস্তকের ক্ষেত্রে। উদাহরণস্বরূপ উত্তরাধিকারের ক্ষেত্রে সিঙ্গলটনকে কিছু সুপারক্লাস বৈশিষ্ট্য সেট করতে বাধ্য করা।


0

আমি এটি উত্তর হিসাবে পোস্ট করতে ভয় পেয়েছি, কিন্তু কেন কেউ এ সম্পর্কে চিন্তা করে না আমি বুঝতে পারি না, সম্ভবত এই উত্তরটি ইতিমধ্যে দেওয়া হয়েছিল আমি কেবল এটি বুঝতে পারি নি।

public class example  {
    private volatile static example instance;

    private String string;
    private int iInt = -1; //any number you know you don't want to use here

  private example() {

    //In case someone uses the private method to create a new Instance
    if (instance != null){
      throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
    }
  }

  public synchronized static example getIsntance(){
    if(instance == null){
      instance = new example();
    }
    return instance;
  }

public void methodDoingWork(){
    if(checkInit()){
      //DoSome
    }
  }

  private boolean checkInit(){
    boolean filled = (this.string != null) && (this.iInt != -1);
    return filled;
  }

  public void setString(String string) {
    if(this.string == null){
      this.string = string;
    }else{
      throw new RuntimeException("You try to override an already setValue"); 
    }
  }

  public void setiInt(int iInt) {
    if(this.iInt == -1){
      this.iInt = iInt;
    }else{
      throw new RuntimeException("You try to override an already setValue");
    }
  }
}

যেহেতু getInstance()প্রতিবার একই ইনস্ট্যান্সটি ফেরত আসে তাই আমি মনে করি এটি কাজ করতে পারে। যদি এটি খুব বেশি ভুল হয় তবে আমি এটি মুছে ফেলব, আমি কেবল এই বিষয়ে আগ্রহী।


-1

আমি মনে করি এটি একটি সাধারণ সমস্যা। সিঙ্গলটনের "গেট" থেকে সিঙ্গলটনের "ইনিশিয়ালাইজেশন" আলাদা করা কাজ করতে পারে (এই উদাহরণটি ডাবল চেকড লকিংয়ের বিভিন্নতা ব্যবহার করে)।

public class MySingleton {

    private static volatile MySingleton INSTANCE;

    @SuppressWarnings("UnusedAssignment")
    public static void initialize(
            final SomeDependency someDependency) {

        MySingleton result = INSTANCE;

        if (result != null) {
            throw new IllegalStateException("The singleton has already "
                    + "been initialized.");
        }

        synchronized (MySingleton.class) {
            result = INSTANCE;

            if (result == null) {
                INSTANCE = result = new MySingleton(someDependency);
            } 
        }
    }

    public static MySingleton get() {
        MySingleton  result = INSTANCE;

        if (result == null) {
            throw new IllegalStateException("The singleton has not been "
                    + "initialized. You must call initialize(...) before "
                    + "calling get()");
        }

       return result;
    }

    ...
}

প্রাথমিক পদ্ধতিতে সর্বদা "ফলাফল" ফিরিয়ে দিতে পারে পাশাপাশি আমি মনে করি।
মাইকেল অ্যান্ড্রুজ

-2

সিঙ্গলটন অবশ্যই একটি "অ্যান্টি-প্যাটার্ন" (পরিবর্তনশীল রাষ্ট্রের সাথে একটি স্ট্যাটিকের সংজ্ঞা গ্রহণ করে)।

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


4
কেবলমাত্র একটি অ্যান্টি-প্যাটার্ন যদি ভুলভাবে ব্যবহার করা হয় তবে এটি অ্যান্টি-প্যাটার্নের সংজ্ঞা। কেবলমাত্র আপনি তাদের দেখেছেন যেখানে তারা অতীতে ছিল না তার অর্থ এই নয় যে তাদের কোনও স্থান নেই।
geowa4

একটি সিঙ্গলটনের সঠিক ব্যবহার হ'ল অক্ষম কোড প্রদর্শন করা।
টম হাটিন -

-6

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

একটি যুক্তিযুক্ত একটি সিঙ্গলটন যেভাবেই কোনও ধারণা দেয় না - আপনি যদি লিখে থাকেন তবে কি হবে:

Singleton s = SingletonHolder.getInstance(1);
Singleton t = SingletonHolder.getInstance(2); //should probably throw IllegalStateException

আপনার সিঙ্গলটনও থ্রেড-নিরাপদ নয় কারণ একাধিক থ্রেড একসাথে কল করতে পারে getInstanceযার ফলে একাধিক উদাহরণ তৈরি হতে পারে (সম্ভবত বিভিন্ন মানের সাথে x)।


এটি মোটামুটি বিতর্কযোগ্য।
আলবার্তোপিএল

1
হ্যাঁ এটি বিতর্কযোগ্য; সুতরাং আমার "সাধারণভাবে" শব্দটির ব্যবহার। আমি মনে করি এটি ন্যায়সঙ্গত যে এগুলি সাধারণত একটি খারাপ ধারণা হিসাবে বিবেচিত হয়
অক্সবো_লাক

এটি বিতর্কযোগ্য - কিছু লোক দাবি করেন যে "অ্যান্টি-প্যাটার্ন" যাকে বলা হয় তা নিদর্শনগুলির সংজ্ঞা অনুসারে ফিট করে, এটি কেবলমাত্র তারা খারাপ নিদর্শন।
টম হাটিন -

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

আমি মনে করি আপনি "বিতরণ" এর অর্থ কী ভুল বুঝবেন? আপনি যা চান তা অর্জনের অন্যান্য উপায় রয়েছে: আপনি কি নির্ভরতা ইনজেকশন বিবেচনা করেছেন? নাকি জেএনডিআই?
অক্সবো_লাক্স 26:25
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.