Repository: iluwatar/java-design-patterns
Issue: Dirty Flag pattern
Labels: epic: pattern

http://gameprogrammingpatterns.com/dirty-flag.html

Issue comments:
I am working on this.
Ok @abhi-agr 
@abhi-agr I implemented something similar in my scene graph code without knowing this pattern. If you need collaborator in this pattern please let me know. 
@abhi-agr  are you still implementing this?
Sorry I am not working on this, I got busy with my work. 
This issue is free for taking again
@iluwatar 

Hello. I would like to work on this particular pattern. I'll be drawing up inspiration from https://www.takeupcode.com/podcast/89-design-patterns-dirty-flag/ . 

Is that alright?
@waisuan ok
Kindly take a look at my pull request and lemme know if I've missed out on something. Thanks! @iluwatar 
Closing this issue. PR successfully merged.

Pull request review comments:
I am not sure if DataFetcher should be returning `null` to indicate no change in data. Any other options for this?
Suggestion: Just document a warning that this is not a thread safe way to implement Singleton. Refer to Singleton for more information.
Question: I don't understand the intent to keep `World` and `DataFetcher` singleton here. Any particular reason you chose this way?
This singleton reset thing won't be needed if we avoid `getInstance`. Hence my question about Singletonness.
The class diagram should be made with ObjectAid eclipse plugin. More about it in wiki 
Done.
Use `assertFalse()` in place of `assertTrue(!condition)`

Patch that resolved the issue:
diff --git a/dirty-flag/README.md b/dirty-flag/README.md
new file mode 100644
index 000000000000..36c92f0e28b8
--- /dev/null
+++ b/dirty-flag/README.md
@@ -0,0 +1,26 @@
+---
+layout: pattern
+title: Dirty Flag
+folder: dirty-flag
+permalink: /patterns/dirty-flag/
+categories: Other
+tags:
+ - Java
+ - Difficulty-Easy
+ - Performance
+---
+
+## Intent
+To avoid expensive re-acquisition of resources. The resources retain their identity, are kept in some
+fast-access storage, and are re-used to avoid having to acquire them again.
+
+![alt text](./etc/dirty-flag.png "Dirty Flag")
+
+## Applicability
+Use the Dirty Flag pattern when
+
+* Repetitious acquisition, initialization, and release of the same resource causes unnecessary performance overhead.
+
+## Credits
+
+* [Design Patterns: Dirty Flag](https://www.takeupcode.com/podcast/89-design-patterns-dirty-flag/)
diff --git a/dirty-flag/etc/dirty-flag.ucls b/dirty-flag/etc/dirty-flag.ucls
new file mode 100644
index 000000000000..760d456f731d
--- /dev/null
+++ b/dirty-flag/etc/dirty-flag.ucls
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<class-diagram version="1.2.2" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true" 
+  realizations="true" associations="true" dependencies="false" nesting-relationships="true" router="FAN">  
+  <class id="1" language="java" name="com.iluwatar.dirtyflag.App" project="dirty-flag" 
+    file="/dirty-flag/src/main/java/com/iluwatar/dirtyflag/App.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="-1" width="-1" x="266" y="188"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </class>  
+  <class id="2" language="java" name="com.iluwatar.dirtyflag.DataFetcher" project="dirty-flag" 
+    file="/dirty-flag/src/main/java/com/iluwatar/dirtyflag/DataFetcher.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="153" width="125" x="66" y="291"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </class>  
+  <class id="3" language="java" name="com.iluwatar.dirtyflag.World" project="dirty-flag" 
+    file="/dirty-flag/src/main/java/com/iluwatar/dirtyflag/World.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="-1" width="-1" x="379" y="366"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </class>  
+  <association id="4">    
+    <end type="SOURCE" refId="3" navigable="false">      
+      <attribute id="5" name="df"/>      
+      <multiplicity id="6" minimum="0" maximum="1"/>    
+    </end>    
+    <end type="TARGET" refId="2" navigable="true"/>    
+    <display labels="true" multiplicity="true"/>  
+  </association>  
+  <classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+    sort-features="false" accessors="true" visibility="true">    
+    <attributes public="true" package="true" protected="true" private="true" static="true"/>    
+    <operations public="true" package="true" protected="true" private="true" static="true"/>  
+  </classifier-display>  
+  <association-display labels="true" multiplicity="true"/>
+</class-diagram>
\ No newline at end of file
diff --git a/dirty-flag/pom.xml b/dirty-flag/pom.xml
new file mode 100644
index 000000000000..a50381a56d72
--- /dev/null
+++ b/dirty-flag/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.iluwatar</groupId>
+    <artifactId>java-design-patterns</artifactId>
+    <version>1.20.0-SNAPSHOT</version>
+  </parent>
+  <groupId>com.iluwatar</groupId>
+  <artifactId>dirty-flag</artifactId>
+  <version>1.20.0-SNAPSHOT</version>
+  <name>dirty-flag</name>
+  <url>http://maven.apache.org</url>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+  <dependencies>
+	<dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/dirty-flag/src/main/java/com/iluwatar/dirtyflag/App.java b/dirty-flag/src/main/java/com/iluwatar/dirtyflag/App.java
new file mode 100644
index 000000000000..4d72b34da249
--- /dev/null
+++ b/dirty-flag/src/main/java/com/iluwatar/dirtyflag/App.java
@@ -0,0 +1,82 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ * <p>
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.dirtyflag;
+
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ *
+ * This application demonstrates the <b>Dirty Flag</b> pattern. The dirty flag behavioral pattern allows you to avoid
+ * expensive operations that would just need to be done again anyway. This is a simple pattern that really just explains
+ * how to add a bool value to your class that you can set anytime a property changes. This will let your class know that
+ * any results it may have previously calculated will need to be calculated again when they’re requested. Once the
+ * results are re-calculated, then the bool value can be cleared.
+ * 
+ * There are some points that need to be considered before diving into using this pattern:- there are some things you’ll
+ * need to consider:- (1) Do you need it? This design pattern works well when the results to be calculated are difficult
+ * or resource intensive to compute. You want to save them. You also don’t want to be calculating them several times in
+ * a row when only the last one counts. (2) When do you set the dirty flag? Make sure that you set the dirty flag within
+ * the class itself whenever an important property changes. This property should affect the result of the calculated
+ * result and by changing the property, that makes the last result invalid. (3) When do you clear the dirty flag? It
+ * might seem obvious that the dirty flag should be cleared whenever the result is calculated with up-to-date
+ * information but there are other times when you might want to clear the flag.
+ *
+ * In this example, the {@link DataFetcher} holds the <i>dirty flag</i>. It fetches and re-fetches from <i>world.txt</i>
+ * when needed. {@link World} mainly serves the data to the front-end.
+ */
+public class App {
+  /**
+   * Program execution point
+   */
+  public void run() {
+
+    final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
+    executorService.scheduleAtFixedRate(new Runnable() {
+      @Override
+      public void run() {
+        World world = new World();
+        List<String> countries = world.fetch();
+        System.out.println("Our world currently has the following countries:-");
+        for (String country : countries) {
+          System.out.println("\t" + country);
+        }
+      }
+    }, 0, 15, TimeUnit.SECONDS); // Run at every 15 seconds.
+  }
+
+  /**
+   * Program entry point
+   *
+   * @param args
+   *          command line args
+   */
+  public static void main(String[] args) {
+    App app = new App();
+
+    app.run();
+  }
+
+}
diff --git a/dirty-flag/src/main/java/com/iluwatar/dirtyflag/DataFetcher.java b/dirty-flag/src/main/java/com/iluwatar/dirtyflag/DataFetcher.java
new file mode 100644
index 000000000000..9123bf32db3f
--- /dev/null
+++ b/dirty-flag/src/main/java/com/iluwatar/dirtyflag/DataFetcher.java
@@ -0,0 +1,59 @@
+package com.iluwatar.dirtyflag;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A mock database manager -- Fetches data from a raw file.
+ * 
+ * @author swaisuan
+ *
+ */
+public class DataFetcher {
+
+  private final String filename = "world.txt";
+  private long lastFetched;
+
+  public DataFetcher() {
+    this.lastFetched = -1;
+  }
+
+  private boolean isDirty(long fileLastModified) {
+    if (lastFetched != fileLastModified) {
+      lastFetched = fileLastModified;
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Fetches data/content from raw file.
+   * 
+   * @return List of strings
+   */
+  public List<String> fetch() {
+    ClassLoader classLoader = getClass().getClassLoader();
+    File file = new File(classLoader.getResource(filename).getFile());
+
+    if (isDirty(file.lastModified())) {
+      System.out.println(filename + " is dirty! Re-fetching file content...");
+
+      List<String> data = new ArrayList<String>();
+      try (BufferedReader br = new BufferedReader(new FileReader(file))) {
+        String line;
+        while ((line = br.readLine()) != null) {
+          data.add(line);
+        }
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+      return data;
+    }
+
+    return new ArrayList<String>();
+  }
+}
diff --git a/dirty-flag/src/main/java/com/iluwatar/dirtyflag/World.java b/dirty-flag/src/main/java/com/iluwatar/dirtyflag/World.java
new file mode 100644
index 000000000000..d356e6581798
--- /dev/null
+++ b/dirty-flag/src/main/java/com/iluwatar/dirtyflag/World.java
@@ -0,0 +1,36 @@
+package com.iluwatar.dirtyflag;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 
+ * A middle-layer app that calls/passes along data from the back-end.
+ * 
+ * @author swaisuan
+ *
+ */
+public class World {
+
+  private List<String> countries;
+  private DataFetcher df;
+
+  public World() {
+    this.countries = new ArrayList<String>();
+    this.df = new DataFetcher();
+  }
+
+  /**
+   * 
+   * Calls {@link DataFetcher} to fetch data from back-end.
+   * 
+   * @return List of strings
+   */
+  public List<String> fetch() {
+    List<String> data = df.fetch();
+
+    countries = data.isEmpty() ? countries : data;
+
+    return countries;
+  }
+}
diff --git a/dirty-flag/src/main/resources/world.txt b/dirty-flag/src/main/resources/world.txt
new file mode 100644
index 000000000000..280ea370239c
--- /dev/null
+++ b/dirty-flag/src/main/resources/world.txt
@@ -0,0 +1,3 @@
+UNITED_KINGDOM
+MALAYSIA
+UNITED_STATES
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 965c8f37c483..e1d025c13bc1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -158,7 +158,8 @@
         <module>eip-splitter</module>
         <module>eip-aggregator</module>
         <module>retry</module>
-		<module>trampoline</module>
+        <module>dirty-flag</module>
+        <module>trampoline</module>
         <module>serverless</module>
     </modules>
 


Test patch:
diff --git a/dirty-flag/src/test/java/org/dirty/flag/AppTest.java b/dirty-flag/src/test/java/org/dirty/flag/AppTest.java
new file mode 100644
index 000000000000..50f107cd58c0
--- /dev/null
+++ b/dirty-flag/src/test/java/org/dirty/flag/AppTest.java
@@ -0,0 +1,40 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package org.dirty.flag;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.Test;
+
+import com.iluwatar.dirtyflag.App;
+
+/**
+ * Tests that Dirty-Flag example runs without errors.
+ */
+public class AppTest {
+  @Test
+  public void test() throws IOException {
+    String[] args = {};
+    App.main(args);
+  }
+}
diff --git a/dirty-flag/src/test/java/org/dirty/flag/DirtyFlagTest.java b/dirty-flag/src/test/java/org/dirty/flag/DirtyFlagTest.java
new file mode 100644
index 000000000000..8f651b2678bb
--- /dev/null
+++ b/dirty-flag/src/test/java/org/dirty/flag/DirtyFlagTest.java
@@ -0,0 +1,54 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package org.dirty.flag;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import com.iluwatar.dirtyflag.DataFetcher;
+
+/**
+ *
+ * Application test
+ *
+ */
+public class DirtyFlagTest {
+
+  @Test
+  public void testIsDirty() {
+    DataFetcher df = new DataFetcher();
+    List<String> countries = df.fetch();
+    assertTrue(!countries.isEmpty());
+  }
+
+  @Test
+  public void testIsNotDirty() {
+    DataFetcher df = new DataFetcher();
+    df.fetch();
+    List<String> countries = df.fetch();
+    assertTrue(countries.isEmpty());
+  }
+}