Skip to main content

Immutable object example

After reading some chapters of  the book "Design patterns" (Navrhove vzory) from czech author Rudolf Pecinovsky, I decided to test my own examples of usage of the design patterns mentioned in this book. In this first post I will publish here a code that is an example of usage of the immutable objects.

As you maybe already know - the immutable objects cannot be changed after their creation. That can be very useful in some situation. In this particular example (which is kind of a english copy of the czech example mentioned in the book "Navrhove vzory") the object, which represents fraction and its operations is created. The main thing here is, that during every operation (method) new instance of class Fraction is created instead of modifying the existing Fraction instance.

Immutable objects can be very useful in concurrent applications - their state cannot be changed, so there is no way they could be corrupted by other threads.

Code example:

 
package com.shimon.immutable;

import com.shimon.immutable.common.Functions;

/**
 * This class defines fractions and needed operations with fractions - addition, subtraction, multiplication and division.
 * @author shimon
 *
 */
public class Fraction extends Number{
 /**
  * 
  */
 private static final long serialVersionUID = 2522259263216154175L;
 private final int numerator;
 private final int denominator;
 
 /**
  * Creates new instance of class Fraction with numerator and denominator passed as parameters.
  * @param n - numerator of new fraction
  * @param d - denominator of new fraction
  */
 public Fraction (int n, int d){
  if (d == 0){
   throw new IllegalArgumentException("Denominator cannot be zero.");
  }
  int divisor = Functions.gcd(n, d);
  if (d < 0){
   n = -n;
   d = -d;
  }
  
  numerator = n / divisor;
  denominator = d / divisor;
 }
 
 public Fraction(Fraction f){
  numerator = f.numerator;
  denominator = f.denominator;
 }
 
 public Fraction(int number){
  numerator = number;
  denominator = 1;
 }
 
 /**
  * Adds a fraction passed as parameter to the Fraction instance.
  * @param f- fraction to add
  * @return
  */
 public Fraction plus(Fraction f){
  return new Fraction(numerator * f.denominator + f.numerator * denominator, denominator * f.denominator);
 }
 
 public Fraction plus (int number){
  return new Fraction(numerator + number * denominator, denominator);
 }
 
 /**
  * Substracts fraction passed as parameter from the Fraction instance
  * @param f - fraction to substract
  * @return
  */
 public Fraction minus(Fraction f){
  return new Fraction(numerator * f.denominator - f.numerator * denominator, denominator * f.denominator);
 }
 
 public Fraction minus(int number){
  return new Fraction(numerator - number * denominator, denominator);
 }
 
 /**
  * Subtracts the fraction from the number, which is passed to the method as a parameter.
  * @param number - number to subtract from
  * @return
  */
 public Fraction subtractFrom(int number){
  return new Fraction(number * denominator - numerator, denominator);
 }
 
 /**
  * Multiplies the fraction with fraction passed as parameter
  * @param f - fraction to multiply with
  * @return
  */
 public Fraction multiply(Fraction f){
  return new Fraction(numerator * f.numerator,denominator * f.denominator);
 }
 
 public Fraction multiply(int number){
  return new Fraction(number * numerator, denominator);
 }
 
 /**
  * Divides the fraction with the fraction passed as a parameter
  * @param f - fraction to divide by
  * @return
  */
 public Fraction devide(Fraction f){
  return new Fraction(numerator * f.denominator, denominator * f.numerator);
 }
 
 public Fraction devide(int number){
  return new Fraction (numerator, denominator * number);
 }
 
 /**
  * Divides the number with a fraction
  * @param number - number to be divided
  * @return
  */
 public Fraction devideNumber(int number){
  return new Fraction(denominator * number, numerator);
 }
 
 @Override
 public int intValue() {
  return numerator / denominator;
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + denominator;
  result = prime * result + numerator;
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Fraction other = (Fraction) obj;
  if (denominator != other.denominator)
   return false;
  if (numerator != other.numerator)
   return false;
  return true;
 }

 @Override
 public long longValue() {
  return (long) numerator / denominator;
 }

 @Override
 public float floatValue() {
  return (float) numerator / denominator;
 }

 @Override
 public double doubleValue() {
  return (double) numerator / denominator;
 }
 
 public int getNumerator() {
  return numerator;
 }

 public int getDenominator() {
  return denominator;
 }

}

}
}
Functions class:
 
package com.shimon.immutable.common;

/**
 * This class is a library class, its methods solve the calculation of greatest common divisor and least common multiple.
 * @author shimon
 *
 */
public final class Functions {
 
 /**
  * Private constructor.
  */
 private Functions(){}
 
 /**
  * Returns greatest common divisor of two numbers.
  * @param i1 - First number
  * @param i2 - Second number
  * @return - gcd
  */
 public static int gcd(int i1, int i2){
  i1 = Math.abs(i1);
  i2 = Math.abs(i2);
  
  while (i2 > 0){
   int pom = i1 % i2;
   i1 = i2;
   i2 = pom;
  }
  return i1;
 }
 
 /**
  * Least common multiple of two numbers.
  * @param i1 - First number
  * @param i2 - Second number
  * @return lcm
  */
 public static int lcm(int i1, int i2){
  if ((i1 == 0) || (i2 == 0))
   return 0;
  return i2 * Math.abs(i1) / gcd(i1,i2);
 }
}
Test class:
 
package com.shimon.immutable;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

public class FractionTest {
 
 private Fraction f;

 @Before
 public void setUp() throws Exception {
  f = new Fraction(3, 5);
 }
 
 @Test
 public void testPlus(){
  Fraction result = f.plus(new Fraction(1,2));
  assertEquals(new Fraction(11,10), result);
 }
 
 @Test
 public void testMinus(){
  Fraction result = f.minus(new Fraction(2,10));
  assertEquals(new Fraction(2,5), result);
 }
 
 @Test
 public void testDivision(){
  Fraction result = f.devide(new Fraction(6,4));
  assertEquals(new Fraction(6,15), result);
 }
 
 @Test
 public void testMutliplication(){
  Fraction result = f.multiply(new Fraction(5,6));
  assertEquals(new Fraction(1,2), result);
 }

}

Comments

Popular posts from this blog

Thajsko 2018 - Ko Lanta (opičky a rybičky)

Aby sme v Thajsku nevynechali čistokrvné dovolenkové rezorty s plážami, vydali sme sa z Krabi (príspevok o Krabi nájdete tu ) na ostrov Lanta, ktorý sa nachádza asi 2 hodiny každý vanom od Krabi smerom na juh. Už cesta samotná bola zaujímavá. Prekvapil nás najmä "systém", akým tu verejná doprava funguje. Van vás väčšinou vyzdvihne u konkrétneho hotelu a pokračuje vyzdvihnúť ďalších spolucestujúcich. Nakoniec sme sa ešte zastavili na miestnej autobusovej stanici, kde šofér od nejakého pána prevzal zásielku pre nejakú pizzeriu po ceste (podľa krabice asi ingrediencie na pizzu). Cestou sme ešte párkrát rôzne zastavili a vyložili nejaký tovar. Takže taxíky tu v podstate fungujú aj ako kuriéri. Nikto žiadne meškanke príliš nerieši, väčšinou zastavia a s úsmevom vám to vysvetlia "Five minute, ok?". Okrem týchto zastávok sa nám cesta predĺžila o čakanie na kompu na Koh Lanta, takže to čo malo trvať asi 2 hodiny, trvalo viac než 3. Až tak nám to zase nevadilo, pretože t...

proste pohoda

minuly vikend som sa uz po druhykrat zucastnil festivalu pohoda. o najkrajsie zazitky sa teda podelim aj s vami. ako to vsetko prebiehalo? na zaciatku sme si uz pocas cesty stanovili presne pravidla, ako napriklad :"do not talk with french girl on the back seat..." a podobne. hned po prichode na trencianske letisko sme sa co najrychlejsie zorientovali v programe festivalu a coskoro sme uz skumali areal festivalu z bezprostrednej blizkosti. no a nieco k programu. den prvy - piatok: pocas poobedia sme sa zucastnili na lekcii balkanskych tancov (celkom dobre na zahriatie; spolu s dzusom riedenym vodkou:) neskor sme sa isli napapat naspat k nasmu autu a po neuspesnom cakani na nasich kamaratov sme sa vecer vybrali na koncert 'dana bartu' ... , kvoli ktoremu som vlastne na pohodu isiel. no co povedat na jeho vykon, ani sa to neda popisat... treba vidiet. zbytok vecera a noci sme pobehovali medzi stageami a stankami so suvenirmi. pekny zazitok mam aj z koncertu ...

Pohoda 2010

Už sa to stáva pomaly pravidlom že v polovici júla každý rok pribudne na môj blog článok s nadpisom začinajúcim slovom Pohoda. I tento rok som si tento festival nenechal ujsť a i tento rok som neoľutoval ani jeden cent z ceny lístka. Tento rok som na festivale Bažant Pohoda bol už po piaty raz a pomaly sa stáva neodmysliteľnou súčasťou môjho leta. Na tento ročník som sa pripravoval poctivejšie ako na ten minulý. Dopredu som počúval rádio na stránke festivalu, aby som sa vedel aspoň približne rozhodnúť, ktorý z množstva koncertov si mám ísť pozrieť. Nakoniec sa mi samozrejme viaceré koncerty, ktoré som chcel vidieť kryli, niektoré boli zase v časoch okolo tretej nad ránom, takže pre mňa nebolo reálne ich vidieť po celodennom chodení po areáli (v teplotách okolo 30 stupňov Celzia). Tu a teraz by som chcel vyzdvihnúť niektoré kapely, ktorých vystúpenia sa mi tento rok páčili najviac. V prvom rade by to bola kapela " Sparrow and the Workshop ", ktorú by som jednoznačne zaradil...