জাভাতে সিঙ্গলটন প্যাটার্ন কার্যকর করার কার্যকর উপায় কী?
জাভাতে সিঙ্গলটন প্যাটার্ন কার্যকর করার কার্যকর উপায় কী?
উত্তর:
একটি এনাম ব্যবহার করুন:
public enum Foo {
INSTANCE;
}
জোশুয়া ব্লচ তার কার্যকর জাভা রিলোডেড আলাপে গুগল আই / ও ২০০৮: ভিডিওর লিঙ্কে এই পদ্ধতির ব্যাখ্যা করেছিলেন । এছাড়াও স্লাইড দেখতে তার উপস্থাপনা (এর 30-32 effective_java_reloaded.pdf ):
সিরিয়ালাইজেবল সিঙ্গলটনের প্রয়োগের সঠিক উপায়
public enum Elvis { INSTANCE; private final String[] favoriteSongs = { "Hound Dog", "Heartbreak Hotel" }; public void printFavorites() { System.out.println(Arrays.toString(favoriteSongs)); } }
সম্পাদনা: "কার্যকর জাভা" এর একটি অনলাইন অংশ বলেছেন:
"এই পদ্ধতির কার্যক্ষেত্রটি জনসাধারণের ক্ষেত্রের পদ্ধতির সমতুল্য, এটি আরও সংক্ষিপ্ততর ব্যতীত, সিরিয়ালাইজেশন যন্ত্রপাতি বিনামূল্যে সরবরাহ করে এবং পরিশীলিত সিরিয়ালাইজেশন বা প্রতিবিম্বের আক্রমণগুলির মধ্যেও একাধিক তাত্পর্য প্রতিরোধের গ্যারান্টি সরবরাহ করে While যদিও এই পদ্ধতির রয়েছে এখনও বহুলভাবে গ্রহণযোগ্য নয়, একটি একক উপাদানগুলির এনাম প্রকারটি সিঙ্গলটন বাস্তবায়নের সেরা উপায় ""
ব্যবহারের উপর নির্ভর করে বেশ কয়েকটি "সঠিক" উত্তর রয়েছে।
যেহেতু জাভা 5 এটি করার সর্বোত্তম উপায় হ'ল এনুম ব্যবহার করা:
public enum Foo {
INSTANCE;
}
পূর্ব জাভা ৫, সর্বাধিক সাধারণ কেসটি হ'ল:
public final class Foo {
private static final Foo INSTANCE = new Foo();
private Foo() {
if (INSTANCE != null) {
throw new IllegalStateException("Already instantiated");
}
}
public static Foo getInstance() {
return INSTANCE;
}
public Object clone() throws CloneNotSupportedException{
throw new CloneNotSupportedException("Cannot clone instance of this class");
}
}
কোডটির উপর দিয়ে যাওয়া যাক। প্রথমত, আপনি চান ক্লাসটি চূড়ান্ত হোক। এই ক্ষেত্রে, আমি final
ব্যবহারকারীদের এটি চূড়ান্ত জানাতে কীওয়ার্ডটি ব্যবহার করেছি । তারপরে ব্যবহারকারীদের নিজস্ব ফু তৈরি করতে বাধা দেওয়ার জন্য আপনাকে কনস্ট্রাক্টরটিকে ব্যক্তিগত করতে হবে। কনস্ট্রাক্টর থেকে একটি ব্যতিক্রম ছুঁড়ে ফেলা ব্যবহারকারীদের একটি দ্বিতীয় ফু তৈরি করতে প্রতিবিম্ব ব্যবহার করতে বাধা দেয়। তারপরে আপনি private static final Foo
একমাত্র উদাহরণটি ধরে রাখার জন্য একটি ক্ষেত্র এবং public static Foo getInstance()
এটিকে ফেরত দেওয়ার জন্য একটি পদ্ধতি তৈরি করেন। জাভা স্পেসিফিকেশন নিশ্চিত করে যে ক্লাসটি প্রথম ব্যবহৃত হবে তখনই কনস্ট্রাক্টরকে ডাকা হবে।
যখন আপনার কাছে খুব বড় কোনও অবজেক্ট বা ভারী নির্মাণ কোড রয়েছে এবং আপনার অন্যান্য অ্যাক্সেসযোগ্য স্থিতিশীল পদ্ধতি বা ক্ষেত্রগুলিও ব্যবহার করতে পারেন যা কোনও উদাহরণ প্রয়োজন হওয়ার আগে, তারপরে এবং কেবল তখনই আপনাকে অলস প্রারম্ভিককরণটি ব্যবহার করতে হবে।
private static class
উদাহরণটি লোড করতে আপনি একটি ব্যবহার করতে পারেন । কোডটি এর পরে দেখতে হবে:
public final class Foo {
private static class FooLoader {
private static final Foo INSTANCE = new Foo();
}
private Foo() {
if (FooLoader.INSTANCE != null) {
throw new IllegalStateException("Already instantiated");
}
}
public static Foo getInstance() {
return FooLoader.INSTANCE;
}
}
যেহেতু লাইনটি private static final Foo INSTANCE = new Foo();
কেবল কার্যকর করা হয় যখন FooLoader ক্লাসটি প্রকৃতপক্ষে ব্যবহৃত হয়, এটি অলস তাত্ক্ষণিকতার যত্ন নেয় এবং এটি থ্রেড নিরাপদে থাকার নিশ্চয়তা দেওয়া হয়।
আপনি যখন নিজের অবজেক্টটি ক্রমিকায়িত করতে সক্ষম হতে চান তখন আপনাকে নিশ্চিত করতে হবে যে ডিসেরায়ালাইজেশন কোনও অনুলিপি তৈরি করবে না।
public final class Foo implements Serializable {
private static final long serialVersionUID = 1L;
private static class FooLoader {
private static final Foo INSTANCE = new Foo();
}
private Foo() {
if (FooLoader.INSTANCE != null) {
throw new IllegalStateException("Already instantiated");
}
}
public static Foo getInstance() {
return FooLoader.INSTANCE;
}
@SuppressWarnings("unused")
private Foo readResolve() {
return FooLoader.INSTANCE;
}
}
পদ্ধতিটি readResolve()
নিশ্চিত করবে যে একমাত্র উদাহরণটি ফিরে আসবে, এমনকি যখন আপনার প্রোগ্রামটির আগের রানটিতে theজেক্টটি সিরিয়ালযুক্ত হয়েছিল।
দাবি অস্বীকার: আমি সবে মাত্র দুর্দান্ত উত্তরগুলির সংক্ষিপ্তসার করেছি এবং তা আমার কথায় লিখেছি।
সিঙ্গেলন প্রয়োগ করার সময় আমাদের কাছে দুটি বিকল্প রয়েছে
1. অলস লোডিং
2. প্রারম্ভিক লোডিং
অলস লোডিং বিট ওভারহেড যুক্ত করে (অনেক সত্য বলতে হবে) সুতরাং এটি তখনই ব্যবহার করুন যখন আপনার খুব বড় অবজেক্ট বা ভারী নির্মাণ কোড থাকে এবং অন্যান্য অ্যাক্সেসযোগ্য স্থিতিশীল পদ্ধতি বা ক্ষেত্রগুলিও উদাহরণস্বরূপ প্রয়োজন হওয়ার আগে ব্যবহার করা যেতে পারে এবং কেবল তখনই আপনার অলস সূচনাটি ব্যবহার করা দরকার ther অন্যদিকে তাড়াতাড়ি লোড করা ভাল পছন্দ।
একক বাস্তবায়নের সর্বাধিক সহজ উপায় হ'ল
public class Foo {
// It will be our sole hero
private static final Foo INSTANCE = new Foo();
private Foo() {
if (INSTANCE != null) {
// SHOUT
throw new IllegalStateException("Already instantiated");
}
}
public static Foo getInstance() {
return INSTANCE;
}
}
প্রারম্ভিক লোডযুক্ত সিঙ্গলটন বাদে সবকিছুই ভাল। আসুন অলস বোঝা সিঙ্গলটনের চেষ্টা করুন
class Foo {
// Our now_null_but_going_to_be sole hero
private static Foo INSTANCE = null;
private Foo() {
if (INSTANCE != null) {
// SHOUT
throw new IllegalStateException("Already instantiated");
}
}
public static Foo getInstance() {
// Creating only when required.
if (INSTANCE == null) {
INSTANCE = new Foo();
}
return INSTANCE;
}
}
এতক্ষণ ভাল তবে আমাদের নায়ক একাই একাধিক অশুভ থ্রেডের সাথে লড়াই করতে পারবেন না যারা আমাদের নায়কের অনেক উদাহরণ চায়। সুতরাং এটি এটিকে অশুভ মাল্টি থ্রেডিং থেকে রক্ষা দেয়
class Foo {
private static Foo INSTANCE = null;
// TODO Add private shouting constructor
public static Foo getInstance() {
// No more tension of threads
synchronized (Foo.class) {
if (INSTANCE == null) {
INSTANCE = new Foo();
}
}
return INSTANCE;
}
}
তবে নায়ককে রক্ষা করার পক্ষে এটি যথেষ্ট নয়, সত্যিই !!! এটি আমাদের নায়ককে সহায়তা করার জন্য সবচেয়ে ভাল / করা উচিত
class Foo {
// Pay attention to volatile
private static volatile Foo INSTANCE = null;
// TODO Add private shouting constructor
public static Foo getInstance() {
if (INSTANCE == null) { // Check 1
synchronized (Foo.class) {
if (INSTANCE == null) { // Check 2
INSTANCE = new Foo();
}
}
}
return INSTANCE;
}
}
একে "ডাবল-চেকড লকিং আইডিয়াম" বলা হয়। অস্থির বিবৃতিটি ভুলে যাওয়া সহজ এবং কেন এটি প্রয়োজনীয় তা বোঝা মুশকিল।
বিশদের জন্য: http://www.cs.umd.edu/~pugh/java/mmoryModel/DoubleCheckedLocking.html
এখন আমরা খারাপ থ্রেড সম্পর্কে নিশ্চিত কিন্তু নিষ্ঠুর সিরিয়ালাইজেশন সম্পর্কে কী? ডি-সিরিয়ালিয়েশন করার সময় কোনও নতুন অবজেক্ট তৈরি না হওয়ার পরেও আমাদের তা নিশ্চিত করতে হবে
class Foo implements Serializable {
private static final long serialVersionUID = 1L;
private static volatile Foo INSTANCE = null;
// Rest of the things are same as above
// No more fear of serialization
@SuppressWarnings("unused")
private Object readResolve() {
return INSTANCE;
}
}
পদ্ধতিটি readResolve()
নিশ্চিত করবে যে একমাত্র উদাহরণটি ফিরে আসবে, এমনকি যখন আমাদের প্রোগ্রামটির আগের রানটিতে বস্তুটি সিরিয়ালযুক্ত হয়েছিল।
অবশেষে আমরা থ্রেড এবং সিরিয়ালাইজেশনের বিরুদ্ধে যথেষ্ট সুরক্ষা যোগ করেছি তবে আমাদের কোডটি ভারী এবং কুশ্রী দেখাচ্ছে। আমাদের নায়ককে একটি মেক আপ দিন
public final class Foo implements Serializable {
private static final long serialVersionUID = 1L;
// Wrapped in a inner static class so that loaded only when required
private static class FooLoader {
// And no more fear of threads
private static final Foo INSTANCE = new Foo();
}
// TODO add private shouting construcor
public static Foo getInstance() {
return FooLoader.INSTANCE;
}
// Damn you serialization
@SuppressWarnings("unused")
private Foo readResolve() {
return FooLoader.INSTANCE;
}
}
হ্যাঁ এটি আমাদের খুব একই নায়ক :)
যেহেতু private static final Foo INSTANCE = new Foo();
ক্লাসটি FooLoader
আসলে ব্যবহৃত হয় তখনই লাইনটি কার্যকর করা হয়, এটি অলস তাত্ক্ষণিকতার যত্ন নেয়,
এবং এটি থ্রেড নিরাপদ থাকার গ্যারান্টিযুক্ত।
এবং আমরা এতদূর এসেছি, আমরা যা কিছু করেছি তা অর্জনের সর্বোত্তম উপায় হ'ল সর্বোত্তম উপায়
public enum Foo {
INSTANCE;
}
যা অভ্যন্তরীণভাবে এমন আচরণ করা হবে
public class Foo {
// It will be our sole hero
private static final Foo INSTANCE = new Foo();
}
এটাই! সিরিয়ালাইজেশন, থ্রেড এবং কুৎসিত কোডের আর ভয় নেই। এছাড়াও ENUMS সিঙ্গেলটন অলসভাবে শুরু করা হয়েছে ।
এই পদ্ধতির কার্যক্ষমতা জনসাধারণের ক্ষেত্রের পদ্ধতির সমতুল্য, এটি আরও সংক্ষিপ্ততর ব্যতীত, সিরিয়ালাইজেশন যন্ত্রপাতি বিনামূল্যে সরবরাহ করে এবং পরিশীলিত সিরিয়ালাইজেশন বা প্রতিবিম্বের আক্রমণগুলির মধ্যেও একাধিক তাত্পর্য বিরুদ্ধে আইরনক্ল্যাড গ্যারান্টি সরবরাহ করে। যদিও এই পদ্ধতির এখনও ব্যাপকভাবে গ্রহণ করা সম্ভব হয়নি, তবে একটি একক উপাদান এনাম প্রকারটি সিঙ্গলটন বাস্তবায়নের সর্বোত্তম উপায়।
-জশুয়া ব্লচ "কার্যকর জাভা" তে
এখন আপনি বুঝতে পেরেছেন কেন ENUMS কে সিঙ্গেলটন বাস্তবায়নের সর্বোত্তম উপায় হিসাবে বিবেচনা করা হয় এবং আপনার ধৈর্যের জন্য ধন্যবাদ :)
এটি আমার ব্লগে আপডেট হয়েছে ।
serialVersionUID
থাকে 0L
। তৃতীয় সমস্যা: কোনও কাস্টমাইজেশন নেই: কোনও শ্রেণি-নির্দিষ্ট রাইটওজেক্ট, রিডবজেক্ট, রিডঅবজেক্ট নোডাটা, রাইটরপ্লেস এবং রিড রেজোলিউজ পদ্ধতিগুলি এনাম টাইপের দ্বারা সংজ্ঞায়িত করা সিরিয়ালাইজেশন এবং ডেসারিয়ালাইজেশনের সময় উপেক্ষা করা হয়।
স্টু থম্পসন পোস্ট পোস্টটি জাভা 5.0 এবং তার পরে বৈধ। তবে আমি এটি ব্যবহার না করা পছন্দ করব কারণ আমার ধারণা এটি ত্রুটিযুক্ত pr
অস্থির বিবৃতিটি ভুলে যাওয়া সহজ এবং কেন এটি প্রয়োজনীয় তা বোঝা মুশকিল। অস্থিরতা ছাড়া এই কোডটি ডাবল-চেকড লকিং অ্যান্টিপ্যাটার্নের কারণে আর থ্রেড নিরাপদ হবে না। অনুশীলনে জাভা কনকুরেন্সির অনুচ্ছেদ 16.2.4 এ সম্পর্কে আরও দেখুন । সংক্ষেপে: এই প্যাটার্নটি (জাভা ৫.০ এর পূর্বে বা অস্থির বিবৃতি ব্যতীত) বার অবজেক্টের একটি রেফারেন্স দিতে পারে যা (এখনও) একটি ভুল অবস্থায় রয়েছে state
এই প্যাটার্নটি পারফরম্যান্স অপ্টিমাইজেশনের জন্য উদ্ভাবিত হয়েছিল। তবে এটি সত্যিই আর উদ্বেগ নয়। নিম্নলিখিত অলস সূচনা কোডটি দ্রুত এবং -ও গুরুত্বপূর্ণভাবে পড়া সহজ।
class Bar {
private static class BarHolder {
public static Bar bar = new Bar();
}
public static Bar getBar() {
return BarHolder.bar;
}
}
getBar()
। (এবং যদি getBar
"খুব তাড়াতাড়ি" নামে অভিহিত হয় তবে এককভাবে কীভাবে প্রয়োগ করা হয় তা বিবেচনা না করেই আপনি একই সমস্যার মুখোমুখি হবেন।) আপনি উপরের কোডটির অলস ক্লাস লোড দেখতে পাচ্ছেন: পেস্টবিন
থ্রেড জাভা 5+ এ নিরাপদ:
class Foo {
private static volatile Bar bar = null;
public static Bar getBar() {
if (bar == null) {
synchronized(Foo.class) {
if (bar == null)
bar = new Bar();
}
}
return bar;
}
}
সম্পাদনা : এখানে সংশোধকটির দিকে মনোযোগ দিন volatile
। :) এটি গুরুত্বপূর্ণ কারণ এটি ছাড়া, অন্যান্য থ্রেডের জেএমএম (জাভা মেমোরি মডেল) এর মান পরিবর্তন করে দেখার নিশ্চয়তা দেয় না। সিঙ্ক্রোনাইজেশন এটির যত্ন নেয় না - এটি কেবল কোডের সেই ব্লকের অ্যাক্সেসকে সিরিয়ালাইজ করে।
2 সম্পাদনা করুন : @NNO এর উত্তর বিল পুগ (ফাইন্ডব্যাগস) দ্বারা প্রস্তাবিত পদ্ধতির বিবরণ এবং তর্কযোগ্য আরও ভাল। পড়ুন এবং তার উত্তরও ভোট দিন।
অলস সূচনা ভুলে যান , এটি খুব সমস্যাযুক্ত। এটি সহজ সমাধান:
public class A {
private static final A INSTANCE = new A();
private A() {}
public static A getInstance() {
return INSTANCE;
}
}
আপনার সত্যই এটি প্রয়োজন তা নিশ্চিত করুন। এর বিরুদ্ধে কিছু যুক্তি দেখতে "সিঙ্গেলটন অ্যান্টি-প্যাটার্ন" এর জন্য একটি গুগল করুন। আমি মনে করি এটিতে অন্তর্নিহিত কোনও ভুল নেই তবে আমি মনে করি এটি কিছু বৈশ্বিক উত্স / তথ্য প্রকাশের জন্য কেবল একটি প্রক্রিয়া যাতে নিশ্চিত হয়ে নিন যে এটিই সেরা উপায়। বিশেষত আমি নির্ভরশীলতা ইঞ্জেকশনটি আরও দরকারী বলে খুঁজে পেয়েছি বিশেষত আপনি যদি ইউনিট পরীক্ষাও ব্যবহার করছেন কারণ ডিআই আপনাকে পরীক্ষার উদ্দেশ্যে বিদ্রূপিত সংস্থানগুলি ব্যবহার করতে দেয়।
আমি সিলেটলেট ব্যবহারের বিকল্প হিসাবে ডিআই-কে প্রস্তাব দেওয়া এমন কয়েকটি জবাব দ্বারা সন্তুষ্ট; এগুলি সম্পর্কযুক্ত ধারণা। আপনি সিঙ্গলটন বা নন-সিঙ্গলটন (যেমন প্রতি থ্রেড) উদাহরণগুলি ইনজেক্ট করতে ডিআই ব্যবহার করতে পারেন। কমপক্ষে এটি সত্য যদি আপনি স্প্রিং ২.x ব্যবহার করেন তবে আমি অন্যান্য ডিআই ফ্রেমওয়ার্কের পক্ষে কথা বলতে পারি না।
সুতরাং ওপিতে আমার উত্তরটি (সবচেয়ে তুচ্ছ নমুনা কোড ব্যতীত সকলের মধ্যে) হতে হবে:
এই পদ্ধতির সাহায্যে আপনাকে একটি দুর্দান্ত ডিকপলড (এবং সেইজন্য নমনীয় এবং পরীক্ষামূলক) আর্কিটেকচার দেওয়া হয় যেখানে সিঙ্গলটন ব্যবহার করা উচিত তা সহজেই প্রত্যাবর্তনযোগ্য বাস্তবায়ন বিশদ (আপনি যে কোনও সিঙ্গলটনের ব্যবহার করেন থ্রেডসেফ অবশ্যই প্রদান করুন)।
TicketNumberer
একটি একক বিশ্বব্যাপী দৃষ্টান্ত প্রয়োজন যা বিবেচনা করুন , এবং যেখানে আপনি একটি ক্লাস লিখতে চান যেখানে TicketIssuer
কোডের একটি লাইন রয়েছে int ticketNumber = ticketNumberer.nextTicketNumber();
। Traditionalতিহ্যবাহী সিঙ্গলটন চিন্তাভাবনায়, আগের কোডের লাইনটি এমন কিছু হতে হবে TicketNumberer ticketNumberer = TicketNumberer.INSTANCE;
। ডিআই ভাবাতে, ক্লাসের মতো কনস্ট্রাক্টর থাকত public TicketIssuer(TicketNumberer ticketNumberer) { this.ticketNumberer = ticketNumberer; }
।
main
পদ্ধতি (বা এর কোনও মাইনইস) নির্ভরতা তৈরি করবে এবং তারপরে কনস্ট্রাক্টরকে কল করবে। মূলত, গ্লোবাল ভেরিয়েবল (বা একটি বৈশ্বিক পদ্ধতি) এর ব্যবহার হ'ল ভয়ঙ্কর পরিষেবা লোকেটার প্যাটার্নের কেবল একটি সহজ রূপ , এবং সেই প্যাটার্নের অন্যান্য ব্যবহারের মতো নির্ভরতা ইনজেকশন দ্বারা প্রতিস্থাপন করা যেতে পারে।
সত্যই বিবেচনা করুন কেন এটি লেখার আগে আপনার একটি সিঙ্গলটন প্রয়োজন। এগুলি ব্যবহারের জন্য একটি দ্বি-ধর্মীয় বিতর্ক রয়েছে যা আপনি জাভাতে সিঙ্গেলন গুগল করলে আপনি সহজেই হোঁচট খেতে পারেন।
ব্যক্তিগতভাবে আমি বহু কারণে যতবার সম্ভব সিলেটলেটগুলি এড়াতে চেষ্টা করি, এর মধ্যে বেশিরভাগ বেশিরভাগই গুগলিং সিঙ্গেলটনের মাধ্যমে পাওয়া যেতে পারে। আমি মনে করি যে প্রায়শই সিঙ্গেলনগুলি অপব্যবহার করা হয় কারণ তারা প্রত্যেকে সহজেই বুঝতে পারে, তারা ওও ডিজাইনে "গ্লোবাল" ডেটা পাওয়ার জন্য একটি প্রক্রিয়া হিসাবে ব্যবহৃত হয় এবং সেগুলি ব্যবহার করা হয় কারণ অবজেক্ট লাইফাইসাইকেল পরিচালনা (অথবা আপনি কীভাবে খ এর ভিতর থেকে A করতে পারেন তা নিয়ে ভাবছেন)। একটি দুর্দান্ত মিডগ্রাউন্ডের জন্য ইনভার্শন অফ কন্ট্রোল (আইওসি) বা ডিপেন্ডেন্সি ইনজেকশন (ডিআই) এর মতো জিনিসগুলি দেখুন।
আপনার যদি সত্যই প্রয়োজন হয় তবে উইকিপিডিয়ায় একটি সিঙ্গলটনের যথাযথ প্রয়োগের একটি ভাল উদাহরণ রয়েছে।
নিম্নলিখিত 3 পৃথক পদ্ধতির হয়
1) এনুম
/**
* Singleton pattern example using Java Enumj
*/
public enum EasySingleton{
INSTANCE;
}
2) ডাবল চেকড লকিং / অলস লোডিং
/**
* Singleton pattern example with Double checked Locking
*/
public class DoubleCheckedLockingSingleton{
private static volatile DoubleCheckedLockingSingleton INSTANCE;
private DoubleCheckedLockingSingleton(){}
public static DoubleCheckedLockingSingleton getInstance(){
if(INSTANCE == null){
synchronized(DoubleCheckedLockingSingleton.class){
//double checking Singleton instance
if(INSTANCE == null){
INSTANCE = new DoubleCheckedLockingSingleton();
}
}
}
return INSTANCE;
}
}
3) স্ট্যাটিক কারখানা পদ্ধতি
/**
* Singleton pattern example with static factory method
*/
public class Singleton{
//initailzed during class loading
private static final Singleton INSTANCE = new Singleton();
//to prevent creating another instance of Singleton
private Singleton(){}
public static Singleton getSingleton(){
return INSTANCE;
}
}
আমি আমার সিলেটলেটগুলি পরিচালনা করতে স্প্রিং ফ্রেমওয়ার্ক ব্যবহার করি। এটি শ্রেণীর "সিঙ্গেলন-নেস" প্রয়োগ করে না (একাধিক শ্রেণীর লোডার জড়িত থাকলে আপনি যা সত্যিই করতে পারেন না) তবে বিভিন্ন ধরণের অবজেক্ট তৈরির জন্য বিভিন্ন কারখানাগুলি তৈরি এবং কনফিগার করার সত্যিই সহজ উপায় সরবরাহ করে।
সংস্করণ 1:
public class MySingleton {
private static MySingleton instance = null;
private MySingleton() {}
public static synchronized MySingleton getInstance() {
if(instance == null) {
instance = new MySingleton();
}
return instance;
}
}
অলস লোডিং, ব্লকিংয়ের সাথে থ্রেড নিরাপদ, এর কারণে কম পারফরম্যান্স synchronized
।
সংস্করণ 2:
public class MySingleton {
private MySingleton() {}
private static class MySingletonHolder {
public final static MySingleton instance = new MySingleton();
}
public static MySingleton getInstance() {
return MySingletonHolder.instance;
}
}
অলস লোডিং, নন-ব্লকিং, উচ্চ কার্যকারিতা সহ নিরাপদ থ্রেড।
আপনার যদি অলস লোডিংয়ের প্রয়োজন না হয় তবে কেবল চেষ্টা করুন
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() { return Singleton.INSTANCE; }
protected Object clone() {
throw new CloneNotSupportedException();
}
}
আপনি যদি অলস লোডিং চান এবং আপনি চান যে আপনার সিঙ্গলটন থ্রেড-নিরাপদ হোক, ডাবল-চেকিং প্যাটার্নটি চেষ্টা করুন
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if(null == instance) {
synchronized(Singleton.class) {
if(null == instance) {
instance = new Singleton();
}
}
}
return instance;
}
protected Object clone() {
throw new CloneNotSupportedException();
}
}
যেহেতু ডাবল চেকিং প্যাটার্নটি কাজ করার গ্যারান্টিযুক্ত নয় (সংকলকগুলির সাথে কিছু সমস্যার কারণে, আমি সে সম্পর্কে আরও কিছু জানি না)), আপনি সম্পূর্ণ getInstance- পদ্ধতিটি সিঙ্ক্রোনাইজ করতে বা আপনার সমস্ত সিলেটলেটের জন্য একটি রেজিস্ট্রি তৈরি করতে চেষ্টা করতে পারেন।
volatile
আমি বলব এনাম সিঙ্গলটন
জাভাতে এনাম ব্যবহার করে সিঙ্গেলটন সাধারণত এনাম সিঙ্গলটন ঘোষণার উপায়। এনাম সিঙ্গলটনে উদাহরণ পরিবর্তনশীল এবং উদাহরণ পদ্ধতি থাকতে পারে। সরলতার স্বার্থে, এও নোট করুন যে আপনি যদি সেই পদ্ধতির থ্রেড সুরক্ষা নিশ্চিত করার প্রয়োজনের চেয়ে কোনও উদাহরণ পদ্ধতি ব্যবহার করেন তবে তা যদি কোনওভাবে অবজেক্টের অবস্থাকে প্রভাবিত করে।
এনামের ব্যবহার কার্যকর করা খুব সহজ এবং সিরিয়ালাইজযোগ্য অবজেক্টগুলির বিষয়ে কোনও ত্রুটি নেই, যা অন্যান্য উপায়ে ছড়িয়ে দিতে হয়।
/**
* Singleton pattern example using Java Enum
*/
public enum Singleton {
INSTANCE;
public void execute (String arg) {
//perform operation here
}
}
আপনি এটি অ্যাক্সেস করতে পারেন Singleton.INSTANCE
, getInstance()
সিঙ্গলটনে কল করার পদ্ধতির চেয়ে অনেক সহজ ।
1.12 এনাম কনস্ট্যান্টগুলির সিরিয়ালকরণ ization
এনাম ধ্রুবকগুলি সাধারণ সিরিয়ালাইজযোগ্য বা বহিরাগতযোগ্য বস্তুর চেয়ে আলাদাভাবে সিরিয়ালযুক্ত হয়। এনাম ধ্রুবকের ক্রমিক রূপটি সম্পূর্ণরূপে এর নাম নিয়ে থাকে; ধ্রুবকের ক্ষেত্রের মানগুলি ফর্মটিতে উপস্থিত নেই। একটি এনাম ধ্রুবককে ক্রমিকায়িত করতে
ObjectOutputStream
এনাম ধ্রুবকের নাম পদ্ধতি দ্বারা ফেরত মানটি লিখুন। একটি এনাম ধ্রুবককে deserialize করতে,ObjectInputStream
স্ট্রিম থেকে ধ্রুবক নামটি পড়ে; ডিসরিয়ালাইজড ধ্রুবকটি পরেjava.lang.Enum.valueOf
পদ্ধতিটি কল করে ধ্রুবকের এনাম টাইপটি আর্গুমেন্ট হিসাবে প্রাপ্ত ধ্রুবক নামটি দিয়ে পাস করা হয়। অন্যান্য সিরিয়ালাইজযোগ্য বা বহির্গমনযোগ্য বস্তুর মতো, এনাম ধ্রুবকগুলি পরবর্তীকালে সিরিয়ালাইজেশন স্ট্রিমের পিছনে উল্লেখের লক্ষ্য হিসাবে কাজ করতে পারে।প্রক্রিয়া যার মাধ্যমে enum ধ্রুবক ধারাবাহিকভাবে হয় কাস্টমাইজড করা যাবে না: কোনো বর্গ-নির্দিষ্ট
writeObject
,readObject
,readObjectNoData
,writeReplace
, এবংreadResolve
পদ্ধতি enum ধরনের দ্বারা সংজ্ঞায়িত ধারাবাহিকতাতে এবং deserialization সময় উপেক্ষা করা হয়। একইভাবে, যে কোনওserialPersistentFields
বাserialVersionUID
ক্ষেত্রের ঘোষণাগুলিও উপেক্ষা করা হয় - সমস্ত এনাম ধরণের একটি নির্দিষ্টserialVersionUID
থাকে0L
। এনাম প্রকারের জন্য সিরিয়ালযোগ্য ক্ষেত্র এবং ডেটা নথিভুক্ত করা অপ্রয়োজনীয়, যেহেতু প্রেরিত ডেটার ধরণের কোনও প্রকারভেদ নেই।
প্রচলিত সিঙ্গলটনের সাথে আর একটি সমস্যা হ'ল একবার আপনি Serializable
ইন্টারফেস প্রয়োগ করার পরে সেগুলি আর সিঙ্গেলটন থেকে যায় না কারণ readObject()
পদ্ধতিটি সর্বদা জাভাতে কনস্ট্রাক্টরের মতো একটি নতুন উদাহরণ দেয়। readResolve()
নীচের মত সিঙ্গলটন দিয়ে প্রতিস্থাপন করে নতুন তৈরি করা দৃষ্টান্তটি ব্যবহার করে এবং বাতিল করে এড়ানো যায়
// readResolve to prevent another instance of Singleton
private Object readResolve(){
return INSTANCE;
}
আপনার সিঙ্গলটন ক্লাসটি রাষ্ট্রের বজায় রাখলে এটি আরও জটিল হয়ে উঠতে পারে, যেমন আপনি এগুলিকে ক্ষণস্থায়ী করে তোলা দরকার তবে এনাম সিঙ্গলটনে জেভিএম দ্বারা সিরিয়ালাইজেশন নিশ্চিত করা হয়েছে।
ভাল পড়ুন
There are 4 ways to create a singleton in java.
1- eager initialization singleton
public class Test{
private static final Test test = new Test();
private Test(){}
public static Test getTest(){
return test;
}
}
2- lazy initialization singleton (thread safe)
public class Test {
private static volatile Test test;
private Test(){}
public static Test getTest() {
if(test == null) {
synchronized(Test.class) {
if(test == null){test = new Test();
}
}
}
return test;
}
3- Bill Pugh Singleton with Holder Pattern (Preferably the best one)
public class Test {
private Test(){}
private static class TestHolder{
private static final Test test = new Test();
}
public static Test getInstance(){
return TestHolder.test;
}
}
4- enum singleton
public enum MySingleton {
INSTANCE;
private MySingleton() {
System.out.println("Here");
}
}
এটিতে খেলায় কিছুটা দেরি হতে পারে তবে একটি সিঙ্গলটন বাস্তবায়নের আশেপাশে প্রচুর উপদ্রব রয়েছে। ধারক প্যাটার্নটি অনেক পরিস্থিতিতে ব্যবহার করা যায় না। অস্থির ব্যবহার করার সময় এবং আইএমও - আপনার একটি স্থানীয় ভেরিয়েবল ব্যবহার করা উচিত। শুরুতে শুরু করুন এবং সমস্যার উপর পুনরাবৃত্তি করা যাক। আপনি যা বলতে চাইছেন তা আপনি দেখতে পাবেন।
প্রথম প্রচেষ্টাটি এরকম কিছু দেখতে পাবে:
public class MySingleton {
private static MySingleton INSTANCE;
public static MySingleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new MySingleton();
}
return INSTANCE;
}
...
}
এখানে আমাদের মাইসিংলেটন ক্লাস রয়েছে যার একটি বেসরকারী স্ট্যাটিক সদস্য রয়েছে যার নাম ইনস্ট্যান্সেনসি, এবং পাবলিক স্ট্যাটিক পদ্ধতি যা গেটইন্সট্যান্স () বলে। প্রথমবার getInstance () বলা হয়, ইনস্ট্যান্টের সদস্যটি শূন্য। প্রবাহটি তারপরে সৃষ্টি অবস্থায় পড়বে এবং মাইসিংটন ক্লাসের একটি নতুন উদাহরণ তৈরি করবে। GetInstance () -এর পরবর্তী কলগুলি দেখতে পাবে যে ইনস্ট্যান্স ভেরিয়েবলটি ইতিমধ্যে সেট করা আছে, এবং অন্য কোনও মাইসিংলেটনের উদাহরণ তৈরি করে না। এটি নিশ্চিত করে যে মাইসিংলেটনের কেবলমাত্র একটি উদাহরণ রয়েছে যা getInstance () এর সমস্ত কলকারীদের মধ্যে ভাগ করা আছে।
তবে এই বাস্তবায়নে সমস্যা আছে। একক দৃষ্টান্ত তৈরির জন্য মাল্টি-থ্রেডযুক্ত অ্যাপ্লিকেশনগুলির একটি রেসের শর্ত থাকবে। যদি মৃত্যুর একাধিক থ্রেড একই সময়ে (বা তার আশেপাশে) getInstance () পদ্ধতিতে আঘাত করে, তারা প্রত্যেকে ইনস্ট্যান্সের সদস্যকে শূন্য হিসাবে দেখবে। এর ফলে প্রতিটি থ্রেড একটি নতুন মাইসিংলেটন ইনস্ট্যান্স তৈরি করবে এবং পরবর্তীকালে ইনস্ট্যান্টের সদস্য নির্ধারণ করবে।
private static MySingleton INSTANCE;
public static synchronized MySingleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new MySingleton();
}
return INSTANCE;
}
এখানে আমরা getInstance () পদ্ধতিটি সিঙ্ক্রোনাইজ করতে পদ্ধতি স্বাক্ষরে সিঙ্ক্রোনাইজড কীওয়ার্ডটি ব্যবহার করেছি। এটি অবশ্যই আমাদের জাতির অবস্থা ঠিক করবে। থ্রেডগুলি এখন একবারে একবারে পদ্ধতিটি প্রবেশ করে প্রবেশ করবে। তবে এটি একটি পারফরম্যান্স সমস্যা তৈরি করে। এই প্রয়োগটি কেবলমাত্র একক দৃষ্টান্ত তৈরির ক্ষেত্রে সিঙ্ক্রোনাইজ করে না, এটি রিড সহ সমস্ত কলকে getInstance () এ সিঙ্ক্রোনাইজ করে। পাঠাগুলি সিঙ্ক্রোনাইজ করার দরকার নেই কারণ তারা কেবল ইনস্ট্যান্সের মান দেয়। যেহেতু পাঠাগুলি আমাদের কলগুলির সিংহভাগ তৈরি করবে (মনে রাখবেন, ইনস্ট্যান্টেশন কেবলমাত্র প্রথম কলেই ঘটে), তাই পুরো পদ্ধতিটি সিঙ্ক্রোনাইজ করে আমরা একটি অপ্রয়োজনীয় পারফরম্যান্স হ'ব।
private static MySingleton INSTANCE;
public static MySingleton getInstance() {
if (INSTANCE == null) {
synchronize(MySingleton.class) {
INSTANCE = new MySingleton();
}
}
return INSTANCE;
}
এখানে আমরা পদ্ধতির স্বাক্ষর থেকে একটি সিঙ্ক্রোনাইজড ব্লকে সিঙ্ক্রোনাইজেশন স্থানান্তরিত করেছি যা মাইসিংলেটনের উদাহরণটি তৈরি করে। কিন্তু এটি কি আমাদের সমস্যার সমাধান করে? ঠিক আছে, আমরা আর পড়তে বাধা দিচ্ছি না, তবে আমরা পিছনেও একটি পদক্ষেপ নিয়েছি। একাধিক থ্রেড একই সময়ে বা তার কাছাকাছি getInstance () পদ্ধতিতে আঘাত করবে এবং তারা সকলেই ইনস্ট্যান্সের সদস্যকে শূন্য হিসাবে দেখবে। তারপরে তারা সিঙ্ক্রোনাইজড ব্লকে আঘাত করবে যেখানে কোনওটি লকটি গ্রহণ করবে এবং উদাহরণটি তৈরি করবে। যখন সেই থ্রেডটি ব্লক থেকে প্রস্থান করে, অন্যান্য থ্রেডগুলি লকের পক্ষে লড়াই করবে এবং প্রতিটি থ্রেড একে একে ব্লকের মধ্যে পড়ে আমাদের শ্রেণীর একটি নতুন উদাহরণ তৈরি করবে। সুতরাং আমরা ঠিক যেখানে ফিরে এসেছি।
private static MySingleton INSTANCE;
public static MySingleton getInstance() {
if (INSTANCE == null) {
synchronized(MySingleton.class) {
if (INSTANCE == null) {
INSTANCE = createInstance();
}
}
}
return INSTANCE;
}
এখানে আমরা ব্লকটি ভিতরে রেখে আরও একটি চেক জারি করি। যদি ইনস্ট্যান্সের সদস্যটি ইতিমধ্যে সেট করা থাকে তবে আমরা সূচনাটি এড়িয়ে যাব। একে ডাবল-চেকড লকিং বলা হয়।
এটি আমাদের একাধিক তাত্ক্ষণিক সমস্যার সমাধান করে। তবে আরও একবার, আমাদের সমাধান আরও একটি চ্যালেঞ্জ উপস্থাপন করেছে। অন্যান্য থ্রেডগুলি হয়ত "দেখতে" পাবে না যে ইনস্ট্যান্সের সদস্য আপডেট হয়েছে। এটি জাভা কীভাবে মেমরি অপারেশনগুলিকে অনুকূল করে তোলে। থ্রেডগুলি মূল মেমরি থেকে ভেরিয়েবলের মূল মানগুলি সিপিইউয়ের ক্যাশে অনুলিপি করে। মানগুলিতে পরিবর্তনগুলি তখন সেই ক্যাশে লিখিত হয় এবং পড়ে থাকে read এটি জাভাটির একটি বৈশিষ্ট্য যা পারফরম্যান্স অনুকূল করতে তৈরি করা হয়েছে। তবে এটি আমাদের সিঙ্গলটন বাস্তবায়নের জন্য সমস্যা তৈরি করে। একটি দ্বিতীয় থ্রেড - একটি আলাদা সিপিইউ বা কোর দ্বারা প্রক্রিয়াজাত করা হচ্ছে, একটি পৃথক ক্যাশে ব্যবহার করে - প্রথমটি করা পরিবর্তনগুলি দেখতে পাবে না। এটি দ্বিতীয় থ্রেডটিকে ইনস্টলস সদস্যটিকে নকল হিসাবে দেখতে পাবে যা আমাদের সিঙ্গলটনের একটি নতুন উদাহরণ তৈরি করতে বাধ্য করছে।
private static volatile MySingleton INSTANCE;
public static MySingleton getInstance() {
if (INSTANCE == null) {
synchronized(MySingleton.class) {
if (INSTANCE == null) {
INSTANCE = createInstance();
}
}
}
return INSTANCE;
}
আমরা এটি ইনস্ট্যান্সের সদস্য ঘোষণার ক্ষেত্রে অস্থির কীওয়ার্ড ব্যবহার করে সমাধান করি। এটি সংকলককে সর্বদা প্রধান মেমরি থেকে পড়তে এবং লিখতে বলবে, এবং সিপিইউ ক্যাশে নয়।
তবে এই সাধারণ পরিবর্তনটি ব্যয় করে আসে। যেহেতু আমরা সিপিইউ ক্যাশেকে বাইপাস করছি, আমরা প্রতিবার অস্থির ইনস্ট্যান্স সদস্যের উপর পরিচালিত হলে একটি পারফরম্যান্স হিট করব - যা আমরা 4 বার করি। আমরা অস্তিত্বকে ডাবল-চেক করি (1 এবং 2), মান (3) নির্ধারণ করি এবং তারপরে মানটি (4) ফিরিয়ে আনি। যে কেউ তর্ক করতে পারে যে এই পথটি হ'ল ফ্রিঞ্জ কেস কারণ আমরা কেবল পদ্ধতির প্রথম কল করার সময় উদাহরণটি তৈরি করি। সম্ভবত সৃষ্টিতে আঘাত করা একটি পারফরম্যান্স সহনীয়। এমনকি আমাদের মূল ব্যবহারের ক্ষেত্রেও পড়েন, অস্থির সদস্যের উপর দু'বার কাজ করবে। একবার অস্তিত্ব যাচাই করার জন্য, এবং তার মানটি ফেরত দিতে।
private static volatile MySingleton INSTANCE;
public static MySingleton getInstance() {
MySingleton result = INSTANCE;
if (result == null) {
synchronized(MySingleton.class) {
result = INSTANCE;
if (result == null) {
INSTANCE = result = createInstance();
}
}
}
return result;
}
যেহেতু পারফরম্যান্স হিটটি অস্থির সদস্যের সরাসরি অপারেটিংয়ের কারণে, তাই আসুন অস্থিরতার মানের জন্য একটি স্থানীয় ভেরিয়েবল সেট করি এবং পরিবর্তে স্থানীয় ভেরিয়েবলটিতে কাজ করি। এটি আমাদের অস্থির উপর চালিয়ে যাওয়ার সংখ্যা হ্রাস পাবে এবং এর ফলে আমাদের হারিয়ে যাওয়া কিছু পারফরম্যান্স দাবি করে। মনে রাখবেন যে আমরা যখন সিঙ্ক্রোনাইজড ব্লকে প্রবেশ করি তখন আমাদের স্থানীয় ভেরিয়েবলটি আবার সেট করতে হবে। এটি নিশ্চিত করে যে আমরা লকটির জন্য অপেক্ষা করতে থাকাকালীন যে কোনও পরিবর্তন ঘটেছিল তা আপডেট রয়েছে।
আমি সম্প্রতি এই সম্পর্কে একটি নিবন্ধ লিখেছিলাম। দ্য সিঙ্গলটন ডেকনস্ট্রাকচারিং । আপনি এই উদাহরণগুলিতে আরও তথ্যের এবং সেখানে "ধারক" প্যাটার্নের উদাহরণ খুঁজে পেতে পারেন। ডাবল-চেকড অস্থির পদ্ধতির প্রদর্শন করে এমন একটি বাস্তব-জগতের উদাহরণও রয়েছে। আশাকরি এটা সাহায্য করবে.
BearerToken instance
আপনার নিবন্ধে না static
? এবং এটা কি result.hasExpired()
?
class MySingleton
- সম্ভবত এটি করা উচিত final
?
BearerToken
উদাহরণটি স্থির নয় কারণ এটি এর অংশ BearerTokenFactory
- যা একটি নির্দিষ্ট অনুমোদন সার্ভারের সাথে কনফিগার করা হয়েছে। অনেকগুলি BearerTokenFactory
অবজেক্ট থাকতে পারে - প্রত্যেকের নিজস্ব নিজস্ব "ক্যাশেড" রয়েছে BearerToken
যা এটির মেয়াদ শেষ না হওয়া অবধি এটি আউট হয়ে যায়। hasExpired()
উপর পদ্ধতি BeraerToken
কারখানা এর বলা হয় get()
পদ্ধতি নিশ্চিত করার এটা ঠিক মতো করতে না একটি টোকেনটি মেয়াদউত্তীর্ণ হয়েছে। যদি মেয়াদ উত্তীর্ণ হয় তবে একটি নতুন টোকেনের অনুমোদন সার্ভারের অনুরোধ করা হবে। কোড ব্লকের নিম্নলিখিত অনুচ্ছেদে এটি আরও বিশদে ব্যাখ্যা করে।
এটি একটি সহজ বাস্তবায়ন কিভাবে singleton
:
public class Singleton {
// It must be static and final to prevent later modification
private static final Singleton INSTANCE = new Singleton();
/** The constructor must be private to prevent external instantiation */
private Singleton(){}
/** The public static method allowing to get the instance */
public static Singleton getInstance() {
return INSTANCE;
}
}
এইভাবে সঠিকভাবে অলস করতে কিভাবে আপনার singleton
:
public class Singleton {
// The constructor must be private to prevent external instantiation
private Singleton(){}
/** The public static method allowing to get the instance */
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
/**
* The static inner class responsible for creating your instance only on demand,
* because the static fields of a class are only initialized when the class
* is explicitly called and a class initialization is synchronized such that only
* one thread can perform it, this rule is also applicable to inner static class
* So here INSTANCE will be created only when SingletonHolder.INSTANCE
* will be called
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
}
getInstance()
। তবে প্রকৃতপক্ষে যদি আপনার ক্লাসে অন্য কোনও স্থিতিশীল পদ্ধতি না থাকে Singleton
এবং আপনি কেবল কল getInstance()
করেন তবে কোনও বাস্তব পার্থক্য নেই।
আপনার যদি ক্লাসের উদাহরণ ভেরিয়েবলটি অলসভাবে লোড করতে হয় তবে আপনার ডাবল-চেকিং আইডিয়াম প্রয়োজন। আপনার যদি কোনও স্ট্যাটিক ভেরিয়েবল বা একটি সিঙ্গলটন অলসভাবে লোড করতে হয় তবে আপনার চাহিদা হোল্ডার আইডিয়োমের উদ্যোগ নেওয়া দরকার ।
এছাড়াও, যদি সিঙ্গেলটনকে সিরিলাইজ করার প্রয়োজন হয়, তবে সিঙ্গলটন অবজেক্ট ইনগ্রেন্টটি বজায় রাখার জন্য অন্যান্য সমস্ত ক্ষেত্রের ক্ষণস্থায়ী এবং রিড রিসলভ () পদ্ধতিটি প্রয়োগ করা দরকার। অন্যথায়, প্রতিবার অবজেক্টটি ডিসিরিয়ালাইজ করা হলে, অবজেক্টের একটি নতুন উদাহরণ তৈরি করা হবে। রিডরসলভ () যা করে তা হ'ল রিডবজেক্ট () দ্বারা পঠিত নতুন বস্তুর প্রতিস্থাপন, যা সেই নতুন অবজেক্টটিকে আবর্জনা সংগ্রহ করতে বাধ্য করেছিল কারণ সেখানে কোনও পরিবর্তনশীল উল্লেখ নেই ring
public static final INSTANCE == ....
private Object readResolve() {
return INSTANCE; // original singleton instance.
}
সিঙ্গলটন অবজেক্ট তৈরির বিভিন্ন উপায়:
জোশুয়া ব্লচ অনুসারে - এনাম সেরা হবে।
আপনি ডাবল চেক লকিং ব্যবহার করতে পারেন।
এমনকি অভ্যন্তরীণ স্ট্যাটিক বর্গ ব্যবহার করা যেতে পারে।
এনাম সিঙ্গলটন
থ্রেড-সেফ একটি সিঙ্গেলটন কার্যকর করার সহজ উপায় হ'ল এনুম ব্যবহার করা
public enum SingletonEnum {
INSTANCE;
public void doSomething(){
System.out.println("This is a singleton");
}
}
এই কোডটি জাভা 1.5 তে এনামের প্রবর্তনের পর থেকে কাজ করে
ডাবল চেক লক করা
আপনি যদি একটি "ক্লাসিক" সিঙ্গলটন কোড করতে চান যা বহুবিবাহিত পরিবেশে কাজ করে (জাভা 1.5 থেকে শুরু করে) আপনার এটি ব্যবহার করা উচিত।
public class Singleton {
private static volatile Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class){
if (instance == null) {
instance = new Singleton();
}
}
}
return instance ;
}
}
এটি 1.5 এর আগে থ্রেড-নিরাপদ নয় কারণ উদ্বায়ী কীওয়ার্ডের প্রয়োগটি ভিন্ন ছিল।
প্রারম্ভিক লোডিং সিঙ্গলটন (জাভা 1.5 এর আগেও কাজ করে)
ক্লাসটি লোড হয়ে গেলে এবং থ্রেড সুরক্ষা সরবরাহ করে যখন এই বাস্তবায়নটি সিঙ্গেলটন তাত্ক্ষণিক করে।
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
public void doSomething(){
System.out.println("This is a singleton");
}
}
সিঙ্গেলটনের বিরুদ্ধে প্রায়শই ব্যবহৃত অন্য যুক্তি হ'ল তাদের পরীক্ষারযোগ্যতা সমস্যা। সিলেটলেটগুলি পরীক্ষার উদ্দেশ্যে সহজেই উপহাসযোগ্য হয় না। যদি এটি কোনও সমস্যা হিসাবে দেখা দেয় তবে আমি নিম্নলিখিতটি সামান্য পরিবর্তন করতে চাই:
public class SingletonImpl {
private static SingletonImpl instance;
public static SingletonImpl getInstance() {
if (instance == null) {
instance = new SingletonImpl();
}
return instance;
}
public static void setInstance(SingletonImpl impl) {
instance = impl;
}
public void a() {
System.out.println("Default Method");
}
}
যুক্ত setInstance
পদ্ধতিটি পরীক্ষার সময় সিঙ্গলটন ক্লাসের একটি মকআপ বাস্তবায়ন সেট করতে দেয়:
public class SingletonMock extends SingletonImpl {
@Override
public void a() {
System.out.println("Mock Method");
}
}
এটি প্রাথমিক সূচনা পদ্ধতির সাথেও কাজ করে:
public class SingletonImpl {
private static final SingletonImpl instance = new SingletonImpl();
private static SingletonImpl alt;
public static void setInstance(SingletonImpl inst) {
alt = inst;
}
public static SingletonImpl getInstance() {
if (alt != null) {
return alt;
}
return instance;
}
public void a() {
System.out.println("Default Method");
}
}
public class SingletonMock extends SingletonImpl {
@Override
public void a() {
System.out.println("Mock Method");
}
}
এটিরও সাধারণ প্রয়োগে এই কার্যকারিতাটি প্রকাশ করার ত্রুটি রয়েছে। এই কোডটিতে কাজ করা অন্যান্য বিকাশকারীদের নির্দিষ্ট ফাংশন পরিবর্তন করতে এবং এইভাবে পুরো প্রয়োগের আচরণটি পরিবর্তন করতে ´setInstance´ পদ্ধতিটি ব্যবহার করার প্রলোভন দেখাতে পারে, সুতরাং এই পদ্ধতিটি জাভাদোকটিতে কমপক্ষে একটি ভাল সতর্কতা থাকা উচিত।
তবুও, মকআপ-টেস্টিংয়ের সম্ভাবনার জন্য (যখন প্রয়োজন হবে), এই কোড এক্সপোজারটি প্রদানের জন্য একটি গ্রহণযোগ্য মূল্য হতে পারে।
সিম্পল সিঙ্গলটন ক্লাস
public class Singleton {
private static Singleton singleInstance = new Singleton();
private Singleton() {}
public static Singleton getSingleInstance() {
return singleInstance;
}
}
আমি এখনও জাভা 1.5 এর পরেও মনে করি, এনাম হ'ল সহজলভ্য সিঙ্গলটন বাস্তবায়ন যা এটি একাধিক থ্রেডযুক্ত পরিবেশেও নিশ্চিত করে - কেবলমাত্র একটি উদাহরণ তৈরি করা হয়েছে।
public enum Singleton{
INSTANCE;
}
এবং আপনি সম্পন্ন !!!
এই পোস্টে একবার দেখুন।
জাভা কোর লাইব্রেরিতে GoF ডিজাইন প্যাটার্নগুলির উদাহরণ
সেরা উত্তরের "সিঙ্গেলটন" বিভাগ থেকে,
সিঙ্গেলটন (ক্রিয়েটিভ পদ্ধতি দ্বারা একই সময়ে ফিরে আসা (সাধারণত নিজেরাই) প্রত্যক্ষযোগ্য)
- java.lang.Runtime # getRuntime ()
- java.awt.Desktop # getDesktop ()
- java.lang.System # getSecurityManager ()
আপনি নিজেরাই জাভা নেটিভ ক্লাস থেকে সিঙ্গলটনের উদাহরণ শিখতে পারেন।
আমি যে সেরা সিঙ্গলটন প্যাটার্নটি দেখেছি সেগুলি সরবরাহকারী ইন্টারফেসটি ব্যবহার করে।
নিচে দেখ:
public class Singleton<T> implements Supplier<T> {
private boolean initialized;
private Supplier<T> singletonSupplier;
public Singleton(T singletonValue) {
this.singletonSupplier = () -> singletonValue;
}
public Singleton(Supplier<T> supplier) {
this.singletonSupplier = () -> {
// The initial supplier is temporary; it will be replaced after initialization
synchronized (supplier) {
if (!initialized) {
T singletonValue = supplier.get();
// Now that the singleton value has been initialized,
// replace the blocking supplier with a non-blocking supplier
singletonSupplier = () -> singletonValue;
initialized = true;
}
return singletonSupplier.get();
}
};
}
@Override
public T get() {
return singletonSupplier.get();
}
}
কখনও কখনও একটি সাধারণ " static Foo foo = new Foo();
" যথেষ্ট নয়। আপনি যে কিছু বেসিক ডেটা সন্নিবেশ করতে চান তা কেবল ভাবেন।
অন্যদিকে আপনাকে এমন কোনও পদ্ধতি সিঙ্ক্রোনাইজ করতে হবে যা সিঙ্গলটন ভেরিয়েবলকে তত্ক্ষণিত করে। সিঙ্ক্রোনাইজেশন যেমন খারাপ হয় না তবে এটি কার্য সম্পাদন সমস্যা বা লক করতে পারে (উদাহরণটি ব্যবহার করে খুব বিরল পরিস্থিতিতে। সমাধানটি হ'ল)
public class Singleton {
private static Singleton instance = null;
static {
instance = new Singleton();
// do some of your instantiation stuff here
}
private Singleton() {
if(instance!=null) {
throw new ErrorYouWant("Singleton double-instantiation, should never happen!");
}
}
public static getSingleton() {
return instance;
}
}
এখন কি হয়? ক্লাসটি ক্লাস লোডার মাধ্যমে লোড করা হয়। বাইট অ্যারে থেকে ক্লাসটি ব্যাখ্যা করার পরে, ভিএম স্ট্যাটিক block } ব্লক কার্যকর করে। এটি পুরো গোপনীয়তা: স্থির-ব্লকটি কেবল একবার ডাকা হয়, যে সময় প্রদত্ত প্যাকেজের প্রদত্ত শ্রেণি (নাম) এই এক শ্রেণির লোডার দ্বারা লোড করা হয়।
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton(){
if (INSTANCE != null)
throw new IllegalStateException (“Already instantiated...”);
}
public synchronized static Singleton getInstance() {
return INSTANCE;
}
}
যেহেতু আমরা getInstance এর আগে সিঙ্ক্রোনাইজড কীওয়ার্ডটি যুক্ত করেছি, আমরা যখন দুটি থ্রেড একই সাথে getInstance বলি তখন ক্ষেত্রে রেসের শর্তটি এড়িয়ে চলেছি।