Merge branch 'master' of https://github.com/iluwatar/java-design-patterns into refactor-dao

This commit is contained in:
Narendra Pathai 2016-03-28 11:06:25 +05:30
commit f32a3892a3
87 changed files with 535 additions and 37 deletions

View File

@ -29,6 +29,7 @@ package com.iluwatar.decorator;
*/
public class Troll implements Hostile {
@Override
public void attack() {
System.out.println("The troll swings at you with a club!");
}
@ -38,6 +39,7 @@ public class Troll implements Hostile {
return 10;
}
@Override
public void fleeBattle() {
System.out.println("The troll shrieks in horror and runs away!");
}

View File

@ -1,35 +1,35 @@
---
layout: pattern
title: Monad
folder: monad
permalink: /patterns/monad/
categories: Other
tags:
- Java
- Difficulty-Advanced
- Functional
---
## Intent
Monad pattern based on monad from linear algebra represents the way of chaining operations
together step by step. Binding functions can be described as passing one's output to another's input
basing on the 'same type' contract. Formally, monad consists of a type constructor M and two
operations:
bind - that takes monadic object and a function from plain object to monadic value and returns monadic value
return - that takes plain type object and returns this object wrapped in a monadic value.
![alt text](./etc/monad.png "Monad")
## Applicability
Use the Monad in any of the following situations
* when you want to chain operations easily
* when you want to apply each function regardless of the result of any of them
## Credits
* [Design Pattern Reloaded by Remi Forax](https://youtu.be/-k2X7guaArU)
* [Brian Beckman: Don't fear the Monad](https://channel9.msdn.com/Shows/Going+Deep/Brian-Beckman-Dont-fear-the-Monads)
---
layout: pattern
title: Monad
folder: monad
permalink: /patterns/monad/
categories: Other
tags:
- Java
- Difficulty-Advanced
- Functional
---
## Intent
Monad pattern based on monad from linear algebra represents the way of chaining operations
together step by step. Binding functions can be described as passing one's output to another's input
basing on the 'same type' contract. Formally, monad consists of a type constructor M and two
operations:
bind - that takes monadic object and a function from plain object to monadic value and returns monadic value
return - that takes plain type object and returns this object wrapped in a monadic value.
![alt text](./etc/monad.png "Monad")
## Applicability
Use the Monad in any of the following situations
* when you want to chain operations easily
* when you want to apply each function regardless of the result of any of them
## Credits
* [Design Pattern Reloaded by Remi Forax](https://youtu.be/-k2X7guaArU)
* [Brian Beckman: Don't fear the Monad](https://channel9.msdn.com/Shows/Going+Deep/Brian-Beckman-Dont-fear-the-Monads)
* [Monad on Wikipedia](https://en.wikipedia.org/wiki/Monad_(functional_programming))

28
mute-idiom/README.md Normal file
View File

@ -0,0 +1,28 @@
---
layout: pattern
title: Mute Idiom
folder: mute-idiom
permalink: /patterns/mute-idiom/
categories: Other
tags:
- Java
- Difficulty-Beginner
- Idiom
---
## Intent
Provide a template to supress any exceptions that either are declared but cannot occur or should only be logged;
while executing some business logic. The template removes the need to write repeated `try-catch` blocks.
![alt text](./etc/mute-idiom.png "Mute Idiom")
## Applicability
Use this idiom when
* an API declares some exception but can never throw that exception. Eg. ByteArrayOutputStream bulk write method.
* you need to suppress some exception just by logging it, such as closing a resource.
## Credits
* [JOOQ: Mute Design Pattern](http://blog.jooq.org/2016/02/18/the-mute-design-pattern/)

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
realizations="true" associations="true" dependencies="true" nesting-relationships="true">
<class id="1" language="java" name="com.iluwatar.mute.App" project="mute-idiom"
file="/mute-idiom/src/main/java/com/iluwatar/mute/App.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="168" y="234"/>
<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="false" static="true"/>
<operations public="true" package="true" protected="true" private="false" static="true"/>
</display>
</class>
<class id="2" language="java" name="com.iluwatar.mute.Mute" project="mute-idiom"
file="/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java" binary="false" corner="BOTTOM_RIGHT">
<position height="115" width="203" x="70" y="375"/>
<display autosize="false" 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="false" static="true"/>
</display>
</class>
<interface id="3" language="java" name="com.iluwatar.mute.CheckedRunnable" project="mute-idiom"
file="/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="407" y="432"/>
<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>
</interface>
<interface id="4" language="java" name="com.iluwatar.mute.Resource" project="mute-idiom"
file="/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="383" y="235"/>
<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>
</interface>
<interface id="5" language="java" name="java.io.Closeable" project="dao"
file="/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="384" y="109"/>
<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>
</interface>
<dependency id="6">
<end type="SOURCE" refId="1"/>
<end type="TARGET" refId="4"/>
</dependency>
<dependency id="7">
<end type="SOURCE" refId="1"/>
<end type="TARGET" refId="2"/>
</dependency>
<dependency id="8">
<end type="SOURCE" refId="2"/>
<end type="TARGET" refId="3"/>
</dependency>
<generalization id="9">
<end type="SOURCE" refId="4"/>
<end type="TARGET" refId="5"/>
</generalization>
<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>

34
mute-idiom/pom.xml Normal file
View File

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<!-- The MIT License Copyright (c) 2014 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. -->
<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.11.0-SNAPSHOT</version>
</parent>
<artifactId>mute-idiom</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,103 @@
/**
* The MIT License
* Copyright (c) 2014 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 com.iluwatar.mute;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.SQLException;
/**
* Mute pattern is utilized when we need to suppress an exception due to an API flaw or in
* situation when all we can do to handle the exception is to log it.
* This pattern should not be used everywhere. It is very important to logically handle the
* exceptions in a system, but some situations like the ones described above require this pattern,
* so that we don't need to repeat
* <pre>
* <code>
* try {
* // code that may throwing exception we need to ignore or may never be thrown
* } catch (Exception ex) {
* // ignore by logging or throw error if unexpected exception occurs
* }
* </code>
* </pre> every time we need to ignore an exception.
*
*/
public class App {
/**
* Program entry point.
*
* @param args command line args.
* @throws Exception if any exception occurs
*/
public static void main(String[] args) throws Exception {
useOfLoggedMute();
useOfMute();
}
/*
* Typically used when the API declares some exception but cannot do so. Usually a
* signature mistake.In this example out is not supposed to throw exception as it is a
* ByteArrayOutputStream. So we utilize mute, which will throw AssertionError if unexpected
* exception occurs.
*/
private static void useOfMute() {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Mute.mute(() -> out.write("Hello".getBytes()));
}
private static void useOfLoggedMute() throws SQLException {
Resource resource = null;
try {
resource = acquireResource();
utilizeResource(resource);
} finally {
closeResource(resource);
}
}
/*
* All we can do while failed close of a resource is to log it.
*/
private static void closeResource(Resource resource) {
Mute.loggedMute(() -> resource.close());
}
private static void utilizeResource(Resource resource) throws SQLException {
System.out.println("Utilizing acquired resource: " + resource);
}
private static Resource acquireResource() throws SQLException {
return new Resource() {
@Override
public void close() throws IOException {
throw new IOException("Error in closing resource: " + this);
}
};
}
}

View File

@ -0,0 +1,37 @@
/**
* The MIT License
* Copyright (c) 2014 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 com.iluwatar.mute;
/**
* A runnable which may throw exception on execution.
*
*/
@FunctionalInterface
public interface CheckedRunnable {
/**
* Same as {@link Runnable#run()} with a possibility of exception in execution.
* @throws Exception if any exception occurs.
*/
void run() throws Exception;
}

View File

@ -0,0 +1,68 @@
/**
* The MIT License
* Copyright (c) 2014 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 com.iluwatar.mute;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* A utility class that allows you to utilize mute idiom.
*/
public final class Mute {
// The constructor is never meant to be called.
private Mute() {}
/**
* Executes the <code>runnable</code> and throws the exception occurred within a {@link AssertionError}.
* This method should be utilized to mute the operations that are guaranteed not to throw an exception.
* For instance {@link ByteArrayOutputStream#write(byte[])} declares in it's signature that it can throw
* an {@link IOException}, but in reality it cannot. This is because the bulk write method is not overridden
* in {@link ByteArrayOutputStream}.
*
* @param runnable a runnable that should never throw an exception on execution.
*/
public static void mute(CheckedRunnable runnable) {
try {
runnable.run();
} catch (Exception e) {
throw new AssertionError(e);
}
}
/**
* Executes the <code>runnable</code> and logs the exception occurred on {@link System#err}.
* This method should be utilized to mute the operations about which most you can do is log.
* For instance while closing a connection to database, or cleaning up a resource,
* all you can do is log the exception occurred.
*
* @param runnable a runnable that may throw an exception on execution.
*/
public static void loggedMute(CheckedRunnable runnable) {
try {
runnable.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,35 @@
/**
* The MIT License
* Copyright (c) 2014 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 com.iluwatar.mute;
import java.io.Closeable;
/**
* Represents any resource that the application might acquire and that must be closed
* after it is utilized. Example of such resources can be a database connection, open
* files, sockets.
*/
public interface Resource extends Closeable {
}

View File

@ -0,0 +1,38 @@
/**
* The MIT License
* Copyright (c) 2014 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 com.iluwatar.mute;
import org.junit.Test;
/**
* Tests that Mute idiom example runs without errors.
*
*/
public class AppTest {
@Test
public void test() throws Exception {
App.main(null);
}
}

View File

@ -0,0 +1,78 @@
/**
* The MIT License
* Copyright (c) 2014 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 com.iluwatar.mute;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class MuteTest {
private static final String MESSAGE = "should not occur";
@Rule public ExpectedException exception = ExpectedException.none();
@Test
public void muteShouldRunTheCheckedRunnableAndNotThrowAnyExceptionIfCheckedRunnableDoesNotThrowAnyException() {
Mute.mute(() -> methodNotThrowingAnyException());
}
@Test
public void muteShouldRethrowUnexpectedExceptionAsAssertionError() throws Exception {
exception.expect(AssertionError.class);
exception.expectMessage(MESSAGE);
Mute.mute(() -> methodThrowingException());
}
@Test
public void loggedMuteShouldRunTheCheckedRunnableAndNotThrowAnyExceptionIfCheckedRunnableDoesNotThrowAnyException() {
Mute.loggedMute(() -> methodNotThrowingAnyException());
}
@Test
public void loggedMuteShouldLogExceptionTraceBeforeSwallowingIt() throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
System.setErr(new PrintStream(stream));
Mute.loggedMute(() -> methodThrowingException());
assertTrue(new String(stream.toByteArray()).contains(MESSAGE));
}
private void methodNotThrowingAnyException() {
System.out.println("Executed successfully");
}
private void methodThrowingException() throws Exception {
throw new Exception(MESSAGE);
}
}

View File

@ -124,6 +124,7 @@
<module>feature-toggle</module>
<module>value-object</module>
<module>monad</module>
<module>mute-idiom</module>
</modules>
<dependencyManagement>

View File

@ -100,6 +100,8 @@ public class App {
System.out.println(person);
}
repository.deleteAll();
context.close();
}

View File

@ -54,7 +54,8 @@
<property name="jpaProperties">
<map>
<entry key="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<entry key="hibernate.hbm2ddl.auto" value="create-drop" />
<entry key="hibernate.hbm2ddl.auto" value="create" />
<entry key="hibernate.show_sql" value="false" />
</map>
</property>
</bean>

View File

@ -31,6 +31,6 @@ public class MeleeStrategy implements DragonSlayingStrategy {
@Override
public void execute() {
System.out.println("With your Excalibur you severe the dragon's head!");
System.out.println("With your Excalibur you sever the dragon's head!");
}
}

View File

@ -52,7 +52,7 @@ public class DragonSlayingStrategyTest {
return Arrays.asList(
new Object[]{
new MeleeStrategy(),
"With your Excalibur you severe the dragon's head!"
"With your Excalibur you sever the dragon's head!"
},
new Object[]{
new ProjectileStrategy(),