Showing posts with label Singleton. Show all posts
Showing posts with label Singleton. Show all posts

Saturday, 29 May 2021

Php: Implement singleton design pattern

Singleton pattern restricts the instantiation of a class to one object. That is you can't create more than one object to this class. This is useful when exactly one object is needed to coordinate actions across the system.

 

Example

Database connection object is single across your application.

 

How to design a singleton class?

 

a.   Make __construct method private

b.   Make __clone method private

c.    Make __wakeup method private

d.   Create get_instance method, which return existing object, if it is already exist, else create new one.

 

Find the below working application.

 

singleton_class_demo_1.php

#!/usr/bin/php

<?php
    class MyClass{
        public static $instance;

        public static function get_instance(){
            if(null == static::$instance){
                static::$instance = new static();
            }
            return static::$instance;
        }

        // Prevent creation of object using constructor
        private function __construct(){

        }

        // Prevent cloning of object
        private function __clone(){

        }

        // Prevent unserializing of singleton
        private function __wakeup(){

        }

        public function about_me(){
            echo "\nI am MyClass instance\n";
        }
    }

    $my_instance_1 = MyClass::get_instance();
    $my_instance_2 = MyClass::get_instance();

    var_dump($my_instance_1 === $my_instance_2);

    $my_instance_1->about_me();
    $my_instance_2->about_me();

    // Since constructor is private, below statement throws an error.
    //$my_instance_3 = new MyClass();

    // Since clone method is private, following statement throws an error.
    //$my_instance_4 = clone $my_instance_2;
    
?>

 

Output

$./singleton_class_demo_1.php 

bool(true)

 

How can I make sure that all the subclasses also singleton?

a.   Define __construct method using protected access specifier

b.   Define __clone method using private access specifier

c.    Define __wakeup method using private access specifier

d.   Define a static protected variable to hold the instance of class, and define get_instance method that return existing object, else it create one.

e.   Define new class that extend the existing singleton and redeclare the static variable in child class again.

 

Find the below working application.

 

singleton_class_demo_2.php

#!/usr/bin/php

<?php
    class MyClass{
        protected static $instance;

        public static function get_instance(){
            if(null === static::$instance){
                static::$instance = new static();
            }
            return static::$instance;
        }

        // Prevent creation of object using constructor
        protected function __construct(){

        }

        // Prevent cloning of object
        private function __clone(){

        }

        // Prevent unserializing of singleton
        private function __wakeup(){

        }

        public function about_me(){
            echo "\nI am MyClass instance\n";
        }
    }

    class MySubClass extends MyClass{
        protected static $instance;

        public function about_me(){
            echo "\nI am MySubClass instance\n";
        }
    }

    $my_instance_1 = MyClass::get_instance();
    $my_instance_2 = MyClass::get_instance();

    $my_instance_1->about_me();
    var_dump($my_instance_1 === $my_instance_2);

    $my_instance_3 = MySubClass::get_instance();
    $my_instance_4 = MySubClass::get_instance();

    $my_instance_3->about_me();

    var_dump($my_instance_3 === $my_instance_4);

    // Since constructor is private, below statement throws an error.
    //$my_instance_3 = new MySubClass();

    // Since clone method is private, following statement throws an error.
    //$my_instance_4 = clone $my_instance_2;
    
?>

 

Output

$./singleton_class_demo_2.php 


I am MyClass instance
bool(true)

I am MySubClass instance
bool(true)

 

 

 

 

 

 

 

 

Previous                                                    Next                                                    Home

Friday, 21 February 2020

Is Collections.emptyList() singleton?

Collections.emptyList return an immutable singleton list. One advantage of this method is, it is singleton. You can call this method any number of times, but it always return the same instance.
public static List<Integer> getEvenIndexElements(List<Integer> list) {
  if (list == null || list.isEmpty()) {
    return Collections.EMPTY_LIST;
  }

  List<Integer> result = new ArrayList<>();

  for (int i = 0; i < list.size(); i += 2) {
    result.add(list.get(i));
  }

  return result;
}

As you see above snippet, ‘getEvenIndexElements’ method return all the elements at even index (0, 2, 4, ….) when the list is non empty. But when the list is empty it returns  ‘Collections.EMPTY_LIST’.

What if you return new ArrayList, when the list null or empty condition?
if (list == null || list.isEmpty()) {
 return new ArrayList<Integer> ();
}

It unnecessary to create new empty ArrayList object, which is not a an efficient solution. If ‘getEvenIndexElements’ method is called ‘N’ times with empty list, then ‘N’ new ArrayList objects get created.

Is Collections.emptyList is singleton
Yes, Collections.emptyList return an immutable singleton list.

App.java
package com.sample.app;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class App {

 public static List<Integer> getEvenIndexElements(List<Integer> list) {
  if (list == null || list.isEmpty()) {
   return Collections.EMPTY_LIST;
  }

  List<Integer> result = new ArrayList<>();

  for (int i = 0; i < list.size(); i += 2) {
   result.add(list.get(i));
  }

  return result;
 }

 public static void main(String[] args) {
  List emptyList = Collections.EMPTY_LIST;

  boolean flag = true;
  for (int i = 0; i < 100; i++) {
   List result = getEvenIndexElements(null);

   if (emptyList != result) {
    System.out.println("EMPTY_LIST is not singleton");
    flag = false;
    break;
   }

  }

  if (flag) {
   System.out.println("EMPTY_LIST is singleton");
  }
 }

}

Output
EMPTY_LIST is singleton

Is Collections.emptyList is immutable?
Yes, Collections.emptyList return an immutable singleton list. You can’t perform any CRUD operation on immutable list once it is created.

EmptyListTest.java
package com.sample.app;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.junit.Test;

public class EmptyListTest {

 private static final List EMPTY_LIST = Collections.emptyList();

 @Test(expected = UnsupportedOperationException.class)
 public void EMPTY_LIST_add_UnsupportedOperationException() {
  EMPTY_LIST.add(1);
 }

 @Test(expected = UnsupportedOperationException.class)
 public void EMPTY_LIST_remove_UnsupportedOperationException() {
  EMPTY_LIST.remove(1);
 }

 @Test(expected = UnsupportedOperationException.class)
 public void EMPTY_LIST_addAll_UnsupportedOperationException() {
  EMPTY_LIST.addAll(Arrays.asList(1, 2));
 }

 @Test(expected = UnsupportedOperationException.class)
 public void EMPTY_LIST_addAtIndex_UnsupportedOperationException() {
  EMPTY_LIST.add(1, 10);
 }

 @Test(expected = UnsupportedOperationException.class)
 public void EMPTY_LIST_addAllAtIndex_UnsupportedOperationException() {
  EMPTY_LIST.addAll(0, Arrays.asList(1, 2, 3));
 }

}

Why should I use Collections.emptyList?
a.   To avoid NullPointer exceptions
b.   We can reuse immutable objects
c.    We can cache the result of the operation that performed in immutable object and reuse.
d.   Since it is singleton, no duplicate lists created.


You may like

What is the use of Collections.emptyList in Java?

Collections.emptyList return an immutable singleton list. One advantage of this method is, it is singleton. You can call this method any number of times, but it always return the same instance.
public static List<Integer> getEvenIndexElements(List<Integer> list) {
  if (list == null || list.isEmpty()) {
    return Collections.EMPTY_LIST;
  }

  List<Integer> result = new ArrayList<>();

  for (int i = 0; i < list.size(); i += 2) {
    result.add(list.get(i));
  }

  return result;
}

As you see above snippet, ‘getEvenIndexElements’ method return all the elements at even index (0, 2, 4, ….) when the list is non empty. But when the list is empty it returns  ‘Collections.EMPTY_LIST’.

What if you return new ArrayList, when the list null or empty condition?
if (list == null || list.isEmpty()) {
 return new ArrayList<Integer> ();
}

It unnecessary to create new empty ArrayList object, which is not a an efficient solution. If ‘getEvenIndexElements’ method is called ‘N’ times with empty list, then ‘N’ new ArrayList objects get created.

Is Collections.emptyList is singleton
Yes, Collections.emptyList return an immutable singleton list.

App.java
package com.sample.app;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class App {

 public static List<Integer> getEvenIndexElements(List<Integer> list) {
  if (list == null || list.isEmpty()) {
   return Collections.EMPTY_LIST;
  }

  List<Integer> result = new ArrayList<>();

  for (int i = 0; i < list.size(); i += 2) {
   result.add(list.get(i));
  }

  return result;
 }

 public static void main(String[] args) {
  List emptyList = Collections.EMPTY_LIST;

  boolean flag = true;
  for (int i = 0; i < 100; i++) {
   List result = getEvenIndexElements(null);

   if (emptyList != result) {
    System.out.println("EMPTY_LIST is not singleton");
    flag = false;
    break;
   }

  }

  if (flag) {
   System.out.println("EMPTY_LIST is singleton");
  }
 }

}

Output
EMPTY_LIST is singleton

Is Collections.emptyList is immutable?
Yes, Collections.emptyList return an immutable singleton list. You can’t perform any CRUD operation on immutable list once it is created.

EmptyListTest.java
package com.sample.app;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.junit.Test;

public class EmptyListTest {

 private static final List EMPTY_LIST = Collections.emptyList();

 @Test(expected = UnsupportedOperationException.class)
 public void EMPTY_LIST_add_UnsupportedOperationException() {
  EMPTY_LIST.add(1);
 }

 @Test(expected = UnsupportedOperationException.class)
 public void EMPTY_LIST_remove_UnsupportedOperationException() {
  EMPTY_LIST.remove(1);
 }

 @Test(expected = UnsupportedOperationException.class)
 public void EMPTY_LIST_addAll_UnsupportedOperationException() {
  EMPTY_LIST.addAll(Arrays.asList(1, 2));
 }

 @Test(expected = UnsupportedOperationException.class)
 public void EMPTY_LIST_addAtIndex_UnsupportedOperationException() {
  EMPTY_LIST.add(1, 10);
 }

 @Test(expected = UnsupportedOperationException.class)
 public void EMPTY_LIST_addAllAtIndex_UnsupportedOperationException() {
  EMPTY_LIST.addAll(0, Arrays.asList(1, 2, 3));
 }

}

Why should I use Collections.emptyList?
a.   To avoid NullPointer exceptions
b.   We can reuse immutable objects
c.    We can cache the result of the operation that performed in immutable object and reuse.
d.   Since it is singleton, no duplicate lists created.


You may like