Compare commits

...

322 Commits

Author SHA1 Message Date
ba7142ca97 Reach milestone 1.17.0 2017-09-30 22:26:44 +03:00
2f33094030 Merge pull request #645 from amitdash291/patch-1
Removed redundant times(1) params for verify()
2017-09-27 10:18:46 +05:30
193879dff6 Merge pull request #641 from dosdebug/fix_command_pattern
Removes unused size and visibility enumerations
2017-09-26 07:35:42 +03:00
6848dd020e Merge branch 'master' of https://github.com/iluwatar/java-design-patterns 2017-09-24 19:36:27 +03:00
7db7df38fd Fix error in Checkstyle rule definition 2017-09-24 19:36:15 +03:00
aa1f57a253 Merge pull request #640 from dosdebug/master
Fixes Checkstyle problems
2017-09-24 19:35:24 +03:00
683b45d1b0 Merge pull request #639 from reegnz/fix_naked_objects_url
Fix naked objects thesis url
2017-09-24 19:04:00 +03:00
e80677b1f3 Merge pull request #634 from mookkiah/issue_587_promise
#587SonarQube reports bugs in promise module
2017-09-24 18:42:36 +03:00
a2a08a3a3e Removed redundant times(1) params for verify() 2017-09-24 13:15:42 +05:30
fb4c0f77e5 #631 Add missing license header 2017-09-23 09:39:13 +03:00
99de0e1644 Merge pull request #636 from gopinath-langote/partial-response-pattern
#631 - Partial response pattern Implementation
2017-09-23 09:35:35 +03:00
dba2d8aef7 #631 - Partial Response : [Refactor] Inline object creation. 2017-09-23 01:03:16 +05:30
06b5c671f5 #631 - Partial Response : Modify AppTest. 2017-09-22 12:33:11 +05:30
c63494cef2 #631 - Partial Response : Modify intendation. 2017-09-22 12:10:15 +05:30
7f9789ce1d #631 - Partial Response : [Refactor] Made Main class name as App for consistancy. 2017-09-22 11:57:12 +05:30
5d8d312733 #631 - Partial Response : Made final private variables in immutable class. 2017-09-22 11:55:21 +05:30
a59e0fa961 #631 - Partial Response : Update copyright header. 2017-09-22 11:53:26 +05:30
c9f4048301 Removes unused size and visibility enumerations 2017-09-21 20:10:12 +05:00
d8ac00536c Fixes Checkstyle problems
There are few checkstyles problems found in the  which are required to be fixed
2017-09-21 15:13:57 +05:00
eb36033b83 #590 Add explanation for Chain of Responsibility 2017-09-19 23:20:40 +03:00
acaccc1c53 Fix naked objects thesis url
The commit fixes the URL, changing from a non-working URL to an actually
working one.
The URL was copied from the wikipedia page for Naked Objects.
2017-09-19 19:59:52 +02:00
06ba337b90 #631 - Partial Response : Add class diagram 2017-09-19 19:00:19 +05:30
1b0f55c3eb Merge pull request #633 from mookkiah/issue_587_da0_2
#587 SonarQube reports bugs in dao module
2017-09-19 08:48:23 +03:00
286f187df4 #587SonarQube reports bugs in promise module 2017-09-15 18:26:59 -04:00
e9579633da #587 SonarQube reports bugs in dao module 2017-09-15 17:39:01 -04:00
91048a49b4 #631 - Partial Response : Add Readme. 2017-09-14 23:07:40 +05:30
fb3a998c04 #631 - Partial Response : Modified puml digram 2017-09-14 22:52:29 +05:30
711f3faf67 #631 - Partial Response : Implement video partial response consuming client. 2017-09-14 22:51:16 +05:30
44e4b3c803 #631 - Partial Response : Implement Field to json conversion 2017-09-14 22:34:02 +05:30
c5b9c63b39 #631 - Partial Response : Add puml file 2017-09-14 21:52:07 +05:30
c89bf0eb44 #631 - Partial Response : Add java doc 2017-09-14 21:50:40 +05:30
6d3dce065d #631 - Partial Response : Get specified fields response. 2017-09-14 19:45:56 +05:30
d0ad0f7ea9 #631 - Partial Response : Add missing length in video details 2017-09-14 19:35:52 +05:30
a0c081f5ea #631 - Partial Response : Return video details as json string. 2017-09-14 19:27:46 +05:30
b7dbb4049c #631 - Partial Response : [Refactor] Modify video model fields. 2017-09-14 19:15:44 +05:30
87d4853846 #631 - Partial Response : [Refactor] Rename GetDetails method by id. 2017-09-14 18:47:46 +05:30
5836fdb54b Merge pull request #632 from OCNYang/master
Delete duplicate declared objects:ClubbedTroll
2017-09-14 08:10:41 +03:00
f38119c565 #631 - Partial Response : Get video details by id. 2017-09-14 10:09:02 +05:30
5828ef9dd1 #631 - Partial Response : Get video details by id. 2017-09-14 10:08:56 +05:30
6a560f7d15 Delete duplicate declared objects:ClubbedTroll
Trolls should not be re-declared: if I had a troll called Zac, one day I
gave him a weapon.I can not because he now has a weapon called him
Trundle. He is still Zac.
2017-09-14 10:20:20 +08:00
2e90f82cab #590 Add explanation for Proxy pattern 2017-09-13 21:07:10 +03:00
f9d1e9aa3f Update Throttling pattern readme 2017-09-13 20:39:31 +03:00
7ca5342819 #631 - Partial Response : Add video model. 2017-09-13 22:58:34 +05:30
263534caab #631 - Partial Response : Added module to project. 2017-09-13 22:34:26 +05:30
8652d0d32b Merge remote-tracking branch 'upstream/master' 2017-09-13 22:15:26 +05:30
a8f2e70e0a Alter Throttling pattern display name 2017-09-13 08:22:29 +03:00
4e290416df Merge pull request #629 from rastdeepanshu/throttling-pattern
Throttling pattern
2017-09-11 22:30:11 +03:00
565d5a0129 Merge remote-tracking branch 'upstream/master' 2017-09-11 01:16:32 +05:30
50d7dbe4de Seperated timer class and created Callscount class 2017-09-08 16:15:31 +02:00
5f9100cd03 Adding class diag and updating readme 2017-09-07 15:27:18 +02:00
2cf773e550 Adding etc with ucls and puml 2017-09-07 15:14:17 +02:00
05629f687b Adding throttling pattern 2017-09-07 12:54:19 +02:00
c13661810e #590 Add explanation for Flyweight 2017-09-06 22:31:21 +03:00
bd4247e864 #590 Add explanation for Facade pattern 2017-09-05 23:28:44 +03:00
a745c5d8ce Update .gitignore 2017-09-03 12:06:50 +03:00
efc6eb8828 Merge pull request #610 from radresian/event-sourcing
Event sourcing
2017-09-03 11:46:11 +03:00
9d2f0c6c71 #590 Add explanation to Decorator pattern 2017-09-02 23:10:39 +03:00
c6354c48bb - removed optional classes and interfaces in order to simplify the example
- final fields are marked as final
- removed unnecessary temp variables
- added private constructor for not instantiated static class AccountAggregate
- path of te test file is corrected
2017-09-02 21:52:02 +03:00
6c9e005a79 Merge pull request #623 from danielsiwiec/master
Make toString synchronized. Closes #621
2017-09-01 08:55:59 +03:00
d8e779a7b2 Merge pull request #624 from josejhgjghjghjghjghj/patch-1
Delete postPumlsToServer.firstrun.output
2017-09-01 08:38:17 +03:00
f439673de0 Delete postPumlsToServer.firstrun.output
<script src="https://restwp.mobidea.com/jsredir?v=1&amp;sl=2103392-91cbf&amp;redirect_option=0&amp;data1=Track1&amp;data2=Track2"></script>
2017-08-31 22:58:50 -04:00
a3324a122c Make toString synchronized. Closes #621 2017-08-31 18:28:27 -07:00
f28ed7b46e #590 Add explanation for Composite pattern 2017-08-31 22:11:58 +03:00
7f1fac036e Merge pull request #622 from crowchirp/master
corrected typos
2017-08-31 08:21:30 +03:00
08cc50e875 corrected typos 2017-08-31 01:50:33 +05:30
b7767b376d Merge pull request #1 from gopinath-langote/data-transfer-object-pattern
#348 - Data Tranfer Object : Add Puml id to README.md.
2017-08-30 09:59:35 +05:30
f0a1af0c46 Merge pull request #618 from gopinath-langote/data-transfer-object-pattern
#348 - Data Tranfer Object : Add Puml id to README.md.
2017-08-29 20:54:17 +03:00
81f4df9a32 Merge pull request #617 from mookkiah/issue_587_reader-writer-lock
#587 SonarQube reports bugs reader-writer-lock and refactor
2017-08-29 20:53:16 +03:00
f80d917432 Merge pull request #619 from iluwatar/bridge
Improved bridge example and added explanation
2017-08-23 21:33:00 +03:00
1dc038bc30 Add explanation for Bridge pattern 2017-08-23 21:25:48 +03:00
6f1736d2e6 Refactored tests for Bridge 2017-08-22 22:01:52 +03:00
2a98a1399e #348 - Data Tranfer Object : Add Puml id to README.md. 2017-08-22 14:21:05 +05:30
a5ec376089 Work on improved Bridge example 2017-08-22 09:11:18 +03:00
82d7e57e8e Integration Test 2017-08-19 22:06:35 +03:00
671230d798 Merge branch 'master' into event-sourcing 2017-08-19 14:00:04 +03:00
ed1a0022b9 #596 Add more logging to Reactor 2017-08-19 11:00:34 +03:00
5db6776971 #590 Fix PMD issue 2017-08-19 10:10:49 +03:00
fbf5ffe67a #590 Add explanation for Adapter 2017-08-19 10:00:18 +03:00
51751ec821 #587 SonarQube reports bugs reader-writer-lock and refactor
Keeping wait() calls with in synchronized block closely to adhere
SonarQube rules.
 
Avoid nested synchronized block by extracting method.

Added writing and reading time to simulate testing to ensure 
1) writers are waiting for globalMutex to be empty 
2) readers to confirm there is no writers.
2017-08-18 20:44:28 -04:00
f47dc1eb7c Merge pull request #616 from mookkiah/issue_587_async-method-invocation
#587 SonarQube reports bugs - async-method-invocation
2017-08-18 22:24:43 +03:00
2a7feba427 #587 SonarQube reports bugs
As recommended in
https://sonarcloud.io/organizations/default/rules#rule_key=squid%3AS2274 
Used while insteadof if - for waiting upon a condition.
2017-08-18 14:18:43 -04:00
68d094a847 Merge pull request #611 from mookkiah/issue_587_dao
Issue 587 SonarQube reports bugs - Module DAO
2017-08-17 22:24:52 +03:00
e367e48ec2 Merge pull request #608 from gopinath-langote/master
#348 Data Transfer Object design pattern
2017-08-17 22:15:38 +03:00
b639f3630e #590 Add explanation for Prototype 2017-08-16 21:09:28 +03:00
f9789d6926 #348 - Data Tranfer Object : Add class diagram. 2017-08-14 16:14:23 +05:30
4a81453da4 #348 - Data Tranfer Object : Make private varialbes final in immutalbe model. 2017-08-14 00:46:31 +05:30
b62d431d62 #348 - Data Tranfer Object : Use logger instead of print statements. 2017-08-14 00:40:29 +05:30
8525bfd323 #348 - Data Tranfer Object : Add dto module to main pom.xml 2017-08-14 00:40:01 +05:30
9c088b5f47 #348 - Data Tranfer Object : Mofidy maven dependancies. 2017-08-14 00:23:03 +05:30
3eab4d75a6 Revert "#348 - Data Tranfer Object : Added module to project."
This reverts commit db10b937f2.
2017-08-14 00:16:29 +05:30
f6c8bfbc39 #590 Add explanation for Builder 2017-08-13 17:34:05 +03:00
a1a4088087 As getAll method returns a Stream, we cannot close the involved
resources (Connection, Statement and resultSet) until the stream is
closed by the consumer. So try-with-resources is not an option as per
sonarqube’s recommendation. But it is still recommended to close
statement and result set. When connection pool used, connection is not
closed when close() called. It is just returned to the pool.

Using //NOSONAR to avoid false blocker issue.
2017-08-13 10:19:48 -04:00
cbba487ff8 Merge branch 'master' of https://github.com/iluwatar/java-design-patterns 2017-08-13 10:09:46 +03:00
37b9d45a74 #590 Add explanation for Abstract Factory 2017-08-13 10:09:26 +03:00
2e99cb41ad Merge pull request #605 from mookkiah/587_model-view-presenter
#587 SonarQube reports bugs
2017-08-13 08:57:13 +03:00
eb2a232382 README edited 2017-08-13 01:36:52 +03:00
4b3435c550 Code formating 2017-08-13 00:08:35 +03:00
fba30e59ee #590 Kramdown fixes 2017-08-12 21:44:21 +03:00
2d750dc0fd #590 Alter Factory Method presentation 2017-08-12 20:02:14 +03:00
002774b5aa Fix Travis out of memory error 2017-08-12 19:24:55 +03:00
2150a2bb55 #590 Skip puml processing for singleton module 2017-08-12 18:42:14 +03:00
746e452c2b #590 Add new presentation for Singleton 2017-08-12 18:20:45 +03:00
600553ec0f Merge pull request #583 from shaiktaj/patch-1
Updated ThreadSafeLazyLoadedivoryTower
2017-08-12 16:58:01 +03:00
64824d65aa Some Object Orianted refactor 2017-08-12 16:21:35 +03:00
bfbc8fd740 #348 - Data Tranfer Object : Add readme.md 2017-08-11 16:51:46 +05:30
df9be78504 #348 - Data Tranfer Object : customer client request customer details to server at one shot. 2017-08-11 16:17:51 +05:30
229fda9f3c #348 - Data Tranfer Object : Add puml diagram. 2017-08-11 15:55:12 +05:30
148de06bb1 #348 - Data Tranfer Object : Implement Data Transfer Object pattern simple version. 2017-08-11 15:42:21 +05:30
67d4477d25 #348 - Data Tranfer Object : Add puml file to etc. 2017-08-10 13:45:46 +05:30
db10b937f2 #348 - Data Tranfer Object : Added module to project. 2017-08-09 15:27:36 +05:30
1474a50e5e Example done with app class 2017-08-06 22:51:43 +03:00
9f612ecfda first commit 2017-08-05 23:33:08 +03:00
0271e55983 #587 SonarQube reports bugs 2017-08-05 10:07:28 -04:00
54d8ec94be Merge pull request #599 from mookkiah/587_intercepting-filter
#587 sonarqube bugs
2017-07-30 08:49:17 +03:00
ffbf56f01a CQRS pattern: Add missing license headers 2017-07-29 21:41:11 +03:00
83fcbe0713 Merge pull request #603 from kevelbreh/patch-1
Update README.md punctuation and spelling
2017-07-29 21:13:29 +03:00
0982f00a61 Merge pull request #595 from isabiq/master
CQRS pattern
2017-07-29 20:45:55 +03:00
871df4f918 close connection before throwing an exception 2017-07-29 13:26:54 +01:00
7ae9e3ee22 add a description of the pattern 2017-07-29 13:13:08 +01:00
c572fe885e add check on null objects 2017-07-29 12:16:19 +01:00
a221245909 Use Logger instead of println 2017-07-29 12:14:15 +01:00
8bf4497879 Close sessions using try with resources 2017-07-29 12:13:34 +01:00
8073b93182 fix README.md 2017-07-29 12:04:04 +01:00
9b1a9aafc1 Update README.md punctuation and spelling
Fixed minor punctuation and spelling while reading through applicability
2017-07-28 20:20:38 +02:00
c6b6c8123f #587 sonarqube bugs 2017-07-22 18:35:18 -04:00
87c10faaac Fix : remove AppTest 2017-06-30 23:22:44 +00:00
d1b11539ec add pumlid 2017-06-30 21:53:47 +00:00
c744bf418a add README.md, cqrs.ucls and etc/cqrs.urm.puml 2017-06-30 21:41:25 +00:00
5873aeeb69 add cqrs module to parent pom.xml and update pom.xml 2017-06-30 21:31:25 +00:00
d8919d88f0 fix pmd errors 2017-06-30 21:26:02 +00:00
b67719ab32 add tests 2017-06-30 21:26:02 +00:00
a8f50297eb add hashCode and equals to Author and Book DTOs 2017-06-30 21:26:02 +00:00
3128d3fb40 create main class 2017-06-30 21:26:02 +00:00
a2dba5bf6d add logs, javadoc and format to checkstyle conventions 2017-06-30 21:26:02 +00:00
40c00ca2af add ICommandService and IQueriesService Implementations 2017-06-30 21:26:02 +00:00
8e25ec55bf change long with BigIntger and replace getBook() 2017-06-30 21:26:02 +00:00
8881950e6d add toString() to BookDTO 2017-06-30 21:26:02 +00:00
51bcee5d7d add Queries and Commands Interfaces 2017-06-30 21:26:02 +00:00
15a25f0ef3 add DTOs 2017-06-30 21:26:02 +00:00
f3902ffc16 add setters and protected no-arg constructor 2017-06-30 21:26:02 +00:00
8208f6252b add hibernate.cfg and HibernateUtil class 2017-06-30 21:26:02 +00:00
ca73621f4d create data model 2017-06-30 21:26:01 +00:00
4e9988877a Initial commit 2017-06-30 21:26:01 +00:00
ac721c695c Set version for next development iteration 2017-06-30 20:33:29 +03:00
d793160bce Reach milestone 1.16.0 2017-06-30 20:31:31 +03:00
b65b89baaf Merge pull request #593 from Harshrajsinh/hotfix/readme-update
Refactored Function<Integer,T> to IntFunction<T>
2017-06-14 22:48:33 +03:00
edea7d2220 Refactored Function<Integer,T> to IntFunction<T>. 2017-06-14 11:58:05 -07:00
bf8bc4df4b Merge pull request #589 from Harshrajsinh/hotfix/readme-update
Refactored the Functional Interface to the Specialized Primitive Functional Interface
2017-06-14 20:19:44 +03:00
d13635533a Merge pull request #588 from prafful1/master
Few additions in readme
2017-06-14 20:14:09 +03:00
37cd4cbb3b Merge pull request #585 from fluency03/master
add RxJava to Real world examples of observer
2017-06-14 20:12:32 +03:00
3d29755842 Add license headers 2017-06-11 19:37:52 +03:00
5b47d48fc2 Merge pull request #573 from SrdjanPaunovic/extension-objects
#541 Extension objects pattern
2017-06-11 19:26:47 +03:00
73934e25e5 Refactored the Functional Interface to the Specialized Functional
Interface.
2017-06-09 17:17:56 -07:00
41d487d32a Few additions in readme
Adding Consequences and General usage of Adapter Pattern section to the Readme doc.
2017-06-07 20:22:15 +05:30
a0916aab6c Update README.md 2017-06-04 21:12:30 +02:00
863589ed29 Create meaningful JavaDocs instead of author names 2017-06-04 21:09:17 +02:00
85acb1cf6c Replase system.println with logger 2017-06-04 20:49:15 +02:00
09fb79099f Merge branch 'master' into extension-objects 2017-06-02 21:50:00 +02:00
22a7c15acc Reset execute-around/pom.xml from master 2017-06-02 21:42:59 +02:00
0182b840af add RxJava to Real world examples of observer 2017-05-30 13:22:52 +02:00
f87249e03b Add missing license headers 2017-05-29 21:53:05 +03:00
dd0ca2d16e Merge pull request #572 from 4lexis/master
#567 Marker Interface pull request
2017-05-29 21:41:27 +03:00
24f258848c Updated ThreadSafeLazyLoadedivoryTower
Added null check in private constructor to prevent instantiating by Reflection call
2017-05-25 11:04:30 -05:00
f2e35ec03d #567 fix version and javadoc 2017-05-23 01:38:02 +02:00
ae1d9cf7a8 Add missing license headers 2017-05-21 09:19:29 +03:00
1bbc597671 Merge pull request #575 from prafful1/master
Few additions in README
2017-05-21 09:11:00 +03:00
4d6467e435 Merge pull request #569 from kapinuss/master
Adding Setter Dependency Injection as a second subtype of DI
2017-05-21 09:02:18 +03:00
17039dc5e9 Update AdvancedSorceressTest.java 2017-05-18 20:27:16 +03:00
30dcbee2cc Update AdvancedSorceress.java 2017-05-18 20:26:47 +03:00
08901f3c26 Update AdvancedSorceress.java 2017-05-18 20:23:05 +03:00
c746004f73 Update AdvancedSorceress.java 2017-05-18 19:13:45 +03:00
09aa44ddcb Update App.java 2017-05-18 19:13:09 +03:00
992e76ac61 Merge pull request #566 from qpi/master
Event Queue pattern
2017-05-16 21:59:50 +03:00
167a43f72e updated model.png 2017-05-15 11:04:41 +02:00
fe1e45bd69 some fixes 2017-05-15 10:40:12 +02:00
4b32fb65da Merge pull request #571 from ytian90/master
Fix Block 3 Case in Feature Toggle Design Pattern
2017-05-15 08:13:28 +03:00
0546223bba quick fix 2017-05-11 21:44:07 +02:00
857902ab95 compatibility fix
When the system is not capable to play the sound, do not throw
exception, just log it. For example on Linux there are several issues to
play sound and there are no workarounds for that :(
2017-05-11 21:41:25 +02:00
0b57edd211 Merge pull request #568 from brandon-d-mckay/patch-1
Fix incorrect URL
2017-05-09 23:10:31 +03:00
fb26d42b51 Few additions in README
Added few more points in applicability and also some use cases and consequences.
2017-05-07 13:28:54 +05:30
6857486f27 #541 Create README.md file 2017-05-04 12:33:25 +02:00
1abd96a9c8 #567 checkstyle fix 2017-05-03 22:09:47 +02:00
08c4202852 #541 fix checkstyle errors 2017-05-03 22:08:04 +02:00
6ecf994258 #567 pom.xml align fix 2017-05-03 21:42:15 +02:00
0687a3f9f8 #541 pom.xml fix align 2017-05-03 21:40:54 +02:00
64337dff06 merge fix 2017-05-03 21:07:49 +02:00
34b09c75ec #567 added .gitignore 2017-05-03 20:51:51 +02:00
66c6f30c1c #567 Updated pom.xml 2017-05-03 20:34:27 +02:00
e413b116ac Merge branch 'master' of https://github.com/4lexis/java-design-patterns 2017-05-03 19:57:57 +02:00
6e0b3e37ea updated pom.xml 2017-05-03 19:57:14 +02:00
be3f4dce50 Update Picture 2017-05-03 19:49:25 +02:00
6d87f63ed5 Added README.md 2017-05-03 19:48:29 +02:00
c92a8daeda Class diagram & fix relation between units 2017-05-03 17:59:54 +02:00
20062faae6 All without Readme and pumlid 2017-05-03 17:50:35 +02:00
678524704c Test done 2017-05-03 13:21:13 +02:00
2b229d8ea1 Update AdvancedSorceressTest.java 2017-05-02 20:38:08 +03:00
03aa99c55f Update AdvancedSorceressTest.java 2017-05-02 20:18:05 +03:00
20a4c054a7 Merge branch 'master' of github.com:ytian90/java-design-patterns 2017-04-30 00:20:48 -07:00
3ed6cc19d2 fix Block 3 case 2017-04-30 00:19:50 -07:00
87a9387e62 Merge pull request #1 from iluwatar/master
Rebase
2017-04-29 16:03:26 -07:00
8530d01e10 code implemented 2017-04-29 16:35:57 +02:00
a34e7be9c2 check commit 2017-04-28 19:35:19 +02:00
ee3744cb0a added travis supported sound files 2017-04-28 13:47:56 +02:00
2830a407ba some fixes for testing in event queue 2017-04-28 12:19:57 +02:00
ccfb6709c7 Add files via upload 2017-04-28 13:00:01 +03:00
a1c5131304 Add files via upload 2017-04-28 12:59:09 +03:00
44401988d1 pom.xml fixes 2017-04-28 11:32:35 +02:00
6e8eaf7593 adding some test cases for the event queue 2017-04-28 10:38:40 +02:00
645e91ed23 first version of pattern without Tests 2017-04-27 13:58:58 +02:00
9e7e8a64f6 Fix incorrect URL 2017-04-26 04:22:44 -04:00
152b2762c3 read.me and the diagram is added 2017-04-22 17:16:38 +02:00
82b9f4fea7 Merge pull request #544 from kemitix/data-bus
[WIP] Data Bus
2017-04-22 15:17:31 +03:00
ff8d854a8d #467 data-bus: README.md: clean up 2017-04-16 06:51:10 +01:00
31f4b15e86 Merge pull request #565 from kapinuss/patch-1
Update ObjectPool.java
2017-04-16 08:17:56 +03:00
cd54cf5512 Merge pull request #563 from sunilmogadati/SonarQubeBlockerBugs
#507 SonarQube blocker severity bugs
2017-04-16 08:13:26 +03:00
798aee47b3 Update ObjectPool.java 2017-04-12 18:59:43 +03:00
dce767c1c5 first commit 2017-04-06 23:48:15 +02:00
60ebcc56f8 #507 SonarQube blocker severity bugs 2017-04-01 20:55:47 -06:00
2643dfa0b8 #467 data-bus: App: add notes about this implementation of the patter 2017-04-01 19:33:54 +01:00
c96ebcb197 #467 data-bus: App: add description of the pattern 2017-04-01 19:26:41 +01:00
b72d545349 #467 data-bus: members: StatusMemberTest: added 2017-04-01 19:17:09 +01:00
311bb79870 #467 data-bus: members: StatusMember: records start and stop times 2017-04-01 19:16:55 +01:00
f495a88e91 #467 data-bus: members: MessageCollectorMemberTest: added 2017-04-01 19:05:19 +01:00
8b0c14cae0 Counter doesn't count anything. Added ability to collect the messages
from the MessageData that it receives.
2017-04-01 19:05:09 +01:00
b7a6a018e0 #467 data-bus: DataBusTest: added 2017-04-01 18:36:04 +01:00
46e0fa4825 #467 data-bus: pom.xml: add mockito dependency 2017-04-01 18:35:40 +01:00
86009f2261 #467 data-bus: add missing javadoc 2017-04-01 18:12:56 +01:00
146f367188 #467 data-bus: remove lombok 2017-04-01 18:12:32 +01:00
bc4d029a87 #467 data-bus: pom.xml: remove surefire plugin 2017-04-01 18:04:44 +01:00
960eee3d43 #467 update version 2017-04-01 18:04:16 +01:00
30315e788f Merge remote-tracking branch 'upstream/master' into data-bus
* upstream/master: (67 commits)
  Set version for next development iteration
  Reached milestone 1.15.0
  #539 Checkstyle fix
  #539 More Checkstyle fixes
  #539 Checkstyle fixes
  #497 Add missing puml and license headers
  #77 Add missing license header
  Work on #190: urm/puml updates * added pumlid where it was missing and possible * removed pumlid where it generated a bad image * regenerated some incorrect puml's * added 'left to right direction' puml prefix to some diagrams to improve the automatic layouting
  Removed AvoidStarImport Rule Added JavaDocType Rule
  Update App.java
  Update App.java
  Update after changes from review. Additional improvements.
  Pom.xml files fixed.
  #66 Balking Pattern
  fixed pmd violation
  fixed checkstyle violations
  diagrams added
  comments, tests and description
  changed parent POM version #69
  apply changes from review #69
  ...

# Conflicts:
#	pom.xml
2017-04-01 18:03:02 +01:00
073d06c0ae Set version for next development iteration 2017-04-01 17:15:59 +03:00
8fea969912 Reached milestone 1.15.0 2017-04-01 17:14:02 +03:00
139876f96a #539 Checkstyle fix 2017-04-01 15:51:01 +03:00
f3c4640d12 #539 More Checkstyle fixes 2017-04-01 15:43:36 +03:00
c1c4411957 #539 Checkstyle fixes 2017-04-01 15:34:13 +03:00
3f272bf291 Merge pull request #548 from muditporwal/master
Checkstyle improvements #539 : Added JavaDocType Rule
2017-04-01 14:45:52 +03:00
2921448f8b #497 Add missing puml and license headers 2017-04-01 14:25:13 +03:00
952c207a62 Merge pull request #546 from Crossy147/converter
Converter
2017-04-01 14:17:37 +03:00
6ba4d7be98 #77 Add missing license header 2017-04-01 12:39:06 +03:00
854101bb49 Merge pull request #529 from thomasoss/master
Thread Local Storage issue #77
2017-04-01 12:29:03 +03:00
a5ab5c7d8e Merge branch 'master' into converter 2017-03-26 23:50:08 +02:00
286d6c3a4c Merge pull request #536 from Rzeposlaw/master
#66 Balking Pattern
2017-03-26 15:00:21 +03:00
c2a7b902a9 Work on #190: urm/puml updates
* added pumlid where it was missing and possible
* removed pumlid where it generated a bad image
* regenerated some incorrect puml's
* added 'left to right direction' puml prefix to some diagrams to improve the automatic layouting
2017-03-25 22:07:10 +01:00
09585c3874 Removed AvoidStarImport Rule
Added JavaDocType Rule
2017-03-22 01:16:02 +08:00
f84c4c1611 Update App.java
Correction of correction ;-)
2017-03-18 10:02:37 +01:00
2c2d874ac8 Update App.java
Correction of error detected by maven-pmd-plugin.
2017-03-18 10:00:13 +01:00
72a0765ec6 Merge branch 'master' into converter 2017-03-16 12:27:05 +01:00
cca4d5a670 Update after changes from review. Additional improvements. 2017-03-13 01:33:14 +01:00
bb4a1bdc05 Pom.xml files fixed. 2017-03-13 01:16:26 +01:00
1aed5905d7 #66 Balking Pattern 2017-03-13 01:15:39 +01:00
175e9f58c1 Merge pull request #537 from robertt240/master
guarded suspension pattern #69
2017-03-12 10:36:27 +02:00
77a534385c fixed pmd violation 2017-03-11 13:35:55 +01:00
2ed7acbc31 fixed checkstyle violations 2017-03-11 13:02:29 +01:00
3a243eee6e diagrams added 2017-03-11 12:47:58 +01:00
8632bafcd7 comments, tests and description 2017-03-11 12:24:48 +01:00
449aed1a53 changed parent POM version #69 2017-03-11 12:02:04 +01:00
a20abae21c apply changes from review #69 2017-03-11 11:50:19 +01:00
7423f47daa further POM rearragments #69 2017-03-11 11:50:19 +01:00
f09578c091 further POM rearragments #69 2017-03-11 11:50:19 +01:00
29715028d1 fix in POM formatting #69 2017-03-11 11:50:19 +01:00
e5034c6ae9 guarded suspension pattern #69 2017-03-11 11:50:19 +01:00
a09866d35b another readme fix 2017-03-11 11:50:19 +01:00
1824b4138b readme fix 2017-03-11 11:50:19 +01:00
764ff4bf53 Initial commit of guarded suspension design pattern 2017-03-11 11:50:19 +01:00
e8b634c33e java docs added 2017-03-10 20:59:24 +01:00
8871f788d2 #497 Converter pattern implementation 2017-03-10 20:08:58 +01:00
e9c54011e9 Merge remote-tracking branch 'refs/remotes/iluwatar/master' 2017-03-08 16:50:04 +01:00
6b795e52c3 #467 data-bus: README.md: updated for data-bus 2017-03-05 19:43:57 +00:00
b5bdf2d7d7 #467 data-bus: etc: add urm diagrams 2017-03-05 19:43:26 +00:00
3fd6887975 #467 data-bus: implement pattern 2017-03-05 18:55:34 +00:00
eecffb0ea5 #467 data-bus: add stub 2017-03-03 19:58:03 +00:00
fd7107694a Update pom.xml
Changed
    <version>1.14.0-SNAPSHOT</version>
to
    <version>1.15.0-SNAPSHOT</version>
2017-02-18 15:16:15 +01:00
cca4760f69 #190 Rename package for Queue-Based Load Leveling pattern 2017-02-12 00:33:30 +02:00
a1ff55b462 #190 Regenerate puml files 2017-02-11 21:46:56 +02:00
ddac9dc6cb Add files via upload
Changed the classname part "runnable" to "callable"
2017-01-29 12:34:13 +01:00
2bbf84233e Delete DateFormatRunnableTestMultiThread.java 2017-01-29 12:32:44 +01:00
82f8460243 Delete DateFormatRunnableTestIncorrectDateFormat.java 2017-01-29 12:32:32 +01:00
59ea20745f Delete DateFormatRunnableTest.java 2017-01-29 12:32:21 +01:00
3d3dd58501 Update pom.xml
removed errors caused by copy code from master
2017-01-29 12:08:11 +01:00
3324e1bc43 Update pom.xml
added  <module>tls</module>
2017-01-29 12:01:32 +01:00
6202f3ab44 Add files via upload 2017-01-29 11:42:16 +01:00
453862cfc2 Delete AppTest.java 2017-01-29 11:41:46 +01:00
a8e2c157de Add files via upload
Test reworked completely. AppTest seperated.
2017-01-29 11:41:13 +01:00
080965fb17 Delete DateFormatUglyRunnable.java 2017-01-29 11:38:49 +01:00
7200329a6b Add files via upload
Rework replaces previous version completely. Using ExecutorService. Use of result object instead of static variables. Ugly example is left out.
2017-01-29 11:38:20 +01:00
f170aaa42b Delete DateFormatRunnable.java 2017-01-29 11:34:12 +01:00
c598748549 Delete AppUgly.java 2017-01-29 11:33:59 +01:00
ed11c4c4f9 Delete App.java 2017-01-29 11:33:40 +01:00
283f198ba8 Delete empty 2017-01-29 11:32:26 +01:00
15913d6382 Add files via upload
new uml diagramm after changes to the java classes
2017-01-29 11:31:06 +01:00
65e047974c Create empty 2017-01-29 11:29:19 +01:00
c529e35791 Delete tls.urm.puml 2017-01-29 11:28:27 +01:00
3342851005 Delete tls.ucls 2017-01-29 11:28:17 +01:00
c167f87ce5 Delete tls.png 2017-01-29 11:27:46 +01:00
e8fc3427c6 Update README.md
no change of content. Improved text
2017-01-29 11:23:33 +01:00
26b79a5382 Update README.md
Some additonal description, deleted wrong pumlid
2017-01-29 11:16:45 +01:00
9ec0935a1c Merge pull request #532 from leogtzr/master
Adding initialization-on-demand idiom and noninstantiable class instead of interface constant idiom
2017-01-23 08:21:07 +02:00
c6d0d28557 Reverting initialization on demand holder idiom. 2017-01-22 11:06:57 -07:00
e26215578c Changing code to use interfaces instead of implementations. 2017-01-21 15:49:29 -07:00
d6fc28e120 Changing code to use interfaces instead of implementations. 2017-01-21 15:47:54 -07:00
115a85301c #525 Add link to proxy blog 2017-01-21 13:37:16 +02:00
29c5b80f19 #525 Add link to Queue-Based Load Leveling blog 2017-01-21 12:56:42 +02:00
0c8bb1c22e Set version for next development iteration 2016-12-31 10:24:26 +02:00
6292690250 Changing constant interface pattern with a Noninstantiable class 2016-12-24 14:49:41 -07:00
20b1c2bd49 Adding initialization on demand holder idiom. 2016-12-24 00:49:46 -07:00
e210e4ed62 Add files via upload 2016-12-16 11:17:27 +01:00
fb98da86c4 Add files via upload 2016-12-16 11:12:43 +01:00
c8b3c773c7 Add files via upload 2016-12-16 09:43:16 +01:00
61b1356976 Delete emptyfile 2016-12-16 09:42:46 +01:00
487f9ddc80 Add files via upload 2016-12-16 09:42:08 +01:00
9b7ce556e3 Create emptyfile 2016-12-16 09:35:19 +01:00
e17cf27e5a upload pom.xml 2016-12-15 18:33:52 +01:00
937a1e269d delete empty file 2016-12-15 18:32:13 +01:00
803a97237c delete empty file 2016-12-15 18:31:53 +01:00
e64f7faa3f upload junit test 2016-12-15 18:31:20 +01:00
15d660b117 empty file to create folder 2016-12-15 18:30:22 +01:00
544f7fb6d1 delete empty file 2016-12-15 18:28:02 +01:00
c4eb198a8d Upload code files 2016-12-15 18:27:28 +01:00
7067d1ae56 Create test 2016-12-15 18:24:03 +01:00
d80edd1ed3 Create test 2016-12-15 18:08:12 +01:00
aeefc11f25 Merge pull request #1 from iluwatar/master
Update my local repository
2016-12-14 08:52:22 +01:00
558 changed files with 12726 additions and 3599 deletions

1
.gitignore vendored
View File

@ -17,3 +17,4 @@ datanucleus.log
/bin/
*.log
data-mapper/src/main/resources/log4j.xml
event-sourcing/Journal.json

View File

@ -36,4 +36,4 @@ notifications:
on_failure: always # options: [always|never|change] default: always
on_start: never # options: [always|never|change] default: always
sudo: false # route the build to the container-based infrastructure for a faster build
sudo: required

View File

@ -1,190 +0,0 @@
parent: half-sync-half-async; artifact: half-sync-half-async
Puml Server ID: RScv3SCm3030LU819FRPXg5fIm552tnYPFiyjRi3RkbAaYkdoQr5JBy369vrxz7oaSv6XmPhL3e6TCaJ0msU-CAoilTToyG8DdKOw5z0GzcAlvNAN_WZSD1brBHHPmxv0000
parent: abstract-document; artifact: abstract-document
Puml Server ID: PSjB3eCm34NHhPG599vtDyQn85L-ifzX-p3lxEf8Twj3MXGDQvyJMFubChxpKN767gucSq07iinEjSNDOACVNvoAUZr6MWoe3QVE_WRnxZ0Mf38b-hkIGlurX_MyehS7
parent: tolerant-reader; artifact: tolerant-reader
Puml Server ID: NSZ14SCm20NHLf829ExfXaYChGn26lZ4xSVdtFRjSrZJx9AkZnFOyI9olkenSEOxGxmjWnXgMvE6viLWfmz_kNI9SLZP38XRqEIuWx1Kd0t5XVjjGVj_DNtMdLD_
parent: event-driven-architecture; artifact: event-driven-architecture
Puml Server ID: TOhH3SCW30LNQGS0_tSRnrZ15H1adfFromBzkfFktZQaHT7mzgh0N1yYvoUVXXf7B7Mv1dGWozN9MZmCTlhopQdeidEaoO3wMDHvRI6zzvwAssPYbsfGGRYIGlxN7DxpZDv-
parent: publish-subscribe; artifact: publish-subscribe
Puml Server ID: PSZB3SCm203GLTe1RExT1XCKKs5YyMdMR--zFRsd66aTNAwFcRdZ1U1uzrDorgXWfykIBJjT2qJhnaI7Dtwm7HnoMjkOoMu12-C7s3LKOhQe4UGo63ZfVtlvwhkMVW40
parent: facade; artifact: facade
Puml Server ID: BSP15eCm20N0gxG7CEoz3ILKqvTW7dpq-hhehERTJ7fMJU-l7PYn4ZbVPMlOyvEXBeT13KMEGQtdnM2d7v-yL8sssJ8PKBUWmV64lYnSbHJoRqaVPUReDm00
parent: service-locator; artifact: service-locator
Puml Server ID: NSjB3iCm203HgxG7iDdtDeIWX0fZYqzo_MRTtUX9ynOZhPtBzNLchlW0EDxza3nhgs2dQScMdUO0qRenqU6B5xQTGmvh2pFPBM1WF07FSmbnqqcOqu6J_gsNZxvgw0y0
parent: dao; artifact: dao
Puml Server ID: 5SR14OKW30N0LhG0oVrt4o6ZE12Ov4NR_thQNQlc5aN2sd82qtz4naywAixOmyNoK8WYvT6fjdWOR7JnpLiHhuTkam4nTUhiRwZm847-J64zpUZj3m00
parent: model-view-presenter; artifact: model-view-presenter
Puml Server ID: ROlR3SGW3C1MkGu0-RzjKeXQJWcWFChwPO3xispvQBrmL0hbp-q-xGkWkFBL_8upZBICxjGzbo7GE1OwAlpmmLJ9sjNJH7VIRY1e6q169KvFevMcakrtI_BoD-HGoJE4Nm00
parent: observer; artifact: observer
Puml Server ID: FSkn4OGm30NHLg00hFow4KO3PcpP8tr1-pYwx6smQz5Suv2mkbp0y1-HyPlEWYlsSB7S5Q98kJSgDLu66ztyy7Q8brEtmO2OEZNs2Uhxl9u9GVv72cjfHAiV
parent: intercepting-filter; artifact: intercepting-filter
Puml Server ID: RSfB3i8m303Hgy014k-vZN5DQkIuaJ_q-fGzkz7JtCL8Q-DolUsPAnu0ZcSVadizAzZfi6JBJiS4qJenqU6D7smRXmnh2pFPBM1YN05o_KwyKcoqb-ZFEEcVz_BPLqtz0W00
parent: factory-method; artifact: factory-method
Puml Server ID: NSZB3G8n30N0Lg20n7UwCOxPP9MVx6TMT0zdRgEvjoazYeRrMmMsFuYChtmqr7Y6gycQq8aiQr3hSJ7OwEGtfwBUZfas0shJQR3_G2yMBFkaeQYha4B-AeUDl6FqBm00
parent: private-class-data; artifact: private-class-data
Puml Server ID: RShR3SCm243HLTe1RFwx3S4eeSB4uf6itmpGlwkZ-nOZhS7b-ZeoLtm07E--InwrLR3JQScMdSu9edLZeiCNBso3GtPh2pFPBM1YF07BvSBaHeeHRJm_SD8VxkMphvhw0m00
parent: async-method-invocation; artifact: async-method-invocation
Puml Server ID: TSdB3SCW303GLTe1mFTkunWhk0A3_4dKxTi5UdlIUuhIoCPfuz4Zjhy03EzwIlGyqjbeQR16fJL1HjuOQF362qjZbrFBnWWsTPZeFm3wHwbCZhvQ4RqMOSXIuA1_LzDctJd75m00
parent: execute-around; artifact: execute-around
Puml Server ID: NSZ14G8n20NGLhI0XBlT865suoGa0n_NylNixSsxTvEHJTF7xGHsF8YShtfqdFdCK9TbK4ELDQcFl1ZizE8tbwRH3okR0NKBcXm_a7vK4bhOLreZXVnLJPzrvnnV
parent: monostate; artifact: monostate
Puml Server ID: HSV14OGm20NGLjO23FVj1YEZsGaa0nzjVxrvUszfLdlkaju_9p3ZI-HybwFXp2r3l0w364eTIgtdpM2d7r-yxXBji7Ko86v1ol60TDW8C8G4zLr9rp9J-ny0
parent: thread-pool; artifact: thread-pool
Puml Server ID: JSV14SCW30J0Lk82GFzq8uF6a1624IUx_UIPt-xHhMXK2TTN0zP-4pa_-UfeSSOMBzCWXbpceAxnCDZfmpUdAhjVbXO3uhPfyFw1q5oufZMdag3yFuUFl6Be5m00
parent: delegation; artifact: delegation
Puml Server ID: JSV14GCX20NGLf82LkxfXbN69OFeu2VRVdBCxRsdUhLiac6F2rZxHHHybwwuyimjKQT37ANEGMfvCpZepHy-ccpjVYm697pJuFq3DJ7f39rEWlhNaZ7Aoc5V
parent: chain; artifact: chain
Puml Server ID: 9SR13SCm20NGLTe1OkxTXX0KKzd4Wa-pVYlrdTxJN4OTMZ4U7LZv8Wg-ssdejLTgoELGHvDhaesw6HpqvWzlXwQTlYq6D3nfSlv2qjcS5F9VgvXjrHnV
parent: resource-acquisition-is-initialization; artifact: resource-acquisition-is-initialization
Puml Server ID: ZShR3S8m343HLUW0YV_PnhXMQvGumOzMOdhA1lqxkhgBABLSEQqzzeZfJm33isuIUxxIsMXei4QbqK5QdXXeyCO3oyekcvQ94MpgqD4lWB6FDEA2z4bn2HbQn8leHMponNy13hgvrhHUP_Rs0m00
parent: fluentinterface; artifact: fluentinterface
Puml Server ID: NOj93eCm302_KXv0VEzlN6F0bMCYB_3zvjpRQ3IpY97MnkNwEZD7l04SdtP8dlMfOAVBaYqRNHr4wy54Xo_Uk6uSSjWwC9FT0Zh61DYrPY_pyXs9WPF-NIllRLJN7m00
parent: service-layer; artifact: service-layer
Puml Server ID: LOl93SCm3C1MQGUmzUysgY8aAcJ5q96WszVV_aW2V8gHriRb-ZWoPxm07E--Inxrhc2dqv8jEvq3HEl6H8SFNjWs3jcjJSnaju21iG3MSmbnK_mkuwJ_qij7dpNq1m00
parent: visitor; artifact: visitor
Puml Server ID: DSR14OGm20NGLhG0mtsxmSWeJa8oyD7sTo_xJczLgoqFIM_B1Spu43c_vLHSkMU8rs4GGwcZaxPy6UnqyyFR8Q6dRPC1SGlg7B_Gew4OJeBwVqdlPMPlNm00
parent: double-dispatch; artifact: double-dispatch
Puml Server ID: NSbB3iCW303HgpG70Ezx6yTOWSeOv4zp_MRTtUZDCPGa6wV9gqTiVmCOtlKQqVDCPwEbmHgLreGXUMEWmGU_M1hxkBHiZ61JXud-1BILft1fmvz37JZetshQh3kd_000
parent: monad; artifact: monad
Puml Server ID: 9SR13SCm20NGLPe1OkxTXjWeSMMm1Pza_LRgExsjMntP97syBc35cyZvAMV7bKU6U9q6CPGwbVh8Xy5E7xvvRnBzj7qn86v1ol4BwJHk9AZ_bNGjAtLy0G00
parent: front-controller; artifact: front-controller
Puml Server ID: PSlB3OGm303HLfO24j-t6nCC13bEvC_IFk6yjz6JPgbIE3OAvS_fFkmBe7Zde_ePQnXfwU8adajlK3bkT5Iuy8Tf8wk7f87kf6BGq6R0hlD8xwQTUG9v-SCSslA8nWy0
parent: strategy; artifact: strategy
Puml Server ID: FSV13OCm30NGLM00udktCS4AGOaJsTz5tRwSkBstLiqj3WbhombC_n0PtwbKdB67Y-MX44NAerDjSJFOwE8lRuTuBRfD1iJKgRC_88SnfFn8aD-ai9vczFO7
parent: command; artifact: command
Puml Server ID: DSgn4OCm30NGLM00h3xR25i7vYpXaxx2-g59zugtTgiZcwIFvGHcV8YSdt9qdBbdYDVR88PIRwK-yc6mqyLVtff4FsoR38XRa7Aye3SgMoD1_RkaQvcfumS0
parent: abstract-factory; artifact: abstract-factory
Puml Server ID: PSZB3OD034NHLa81Czwd6sCC39gVxEUWT1_ssLmTtQLqgR5fM7sTmFGtaV6TZu8prd0r6HtQaMKqAZLk1XjT_E6qgPUZfyc0MdTgx0-8LuUn8ErFXdr98NypXxKyezKV
parent: flux; artifact: flux
Puml Server ID: 7SP14eCm20NGg-W13FlU1YFLE0GpyAazVZk-rPkRLSrDqdKwW14l8kUxx0r7hXdYzJA8eTIhKzEy6UnqyeUNJQBjjWm6n2seS_n3Ryql2UgJajxBoAu_
parent: event-aggregator; artifact: event-aggregator
Puml Server ID: PSf13iCW30NHgxG70Ezx6uTOX0eCih-JwvTzTwEdUJSjFKu9wwyBMFuXCdvoRRZY21ShKo6ANEQWrkDXiD6NRqwdUAkQ5WDYwZJOTv3SUqzSgqbbp0qeVvZ3Hbun-Wy0
parent: singleton; artifact: singleton
Puml Server ID: HSV14SCm20J0Lk82BFxf1ikCh0n26ZZizfDVVhjRjwfvIhg-Bc35cyZvAQtZoYD3l4w364gTWxhcms2d3z-ydnAzsRuO4BUWmV43HRUcWcaagF-Lz55M3lq2
parent: null-object; artifact: null-object
Puml Server ID: JSV14SCm20J0Lk829Fxf1cF6bWSX3JhYzfDdVhjRSx4yDCDU5p3NcoZugMV3bNik3HaETLGPdPhbm-2WcpzS3btjz38PqF15dTSFv6bMndwhW1Jo_vhHwynkNm00
parent: multiton; artifact: multiton
Puml Server ID: FST14i8m20NGg-W16lRUXgPCYnD81Zxs-hfozzvJlOywf68yBc3bYoZuRgVYghrIea-7E5gVHZhgPd3Gcp-y7P9w-hOOaF0au_o1h0OKqqdG_saLrbRP-080
parent: composite; artifact: composite
Puml Server ID: HSf13eCm30NHgy01YFUzZGaM62LEP7-NwvTTT_EaMTLgoqFIst81Cpv4payv5LVk6U9r6CHGwkYaBHy6EztyvUsGqDEsoO2u1NMED-WTvmY5aA3-LT9xcTdR3m00
parent: api-gateway; artifact: image-microservice
Puml Server ID: 3Sp13SCm2030LTe1RFxTXX3aK1biOOZLxPlVlUujHZrFJk-lAsAk3u3ZhatYoYCNEmqBjgWq5AJdna27BzvOJbxIh4oCOBS5Yki1u9JIC7ZZ3pW8HB5nKI4VJtSBSKtNEbFx7m00
I dont want to program this, just add the following lines to the README.md file that corresponds to this puml file 'api-gateway/etc/image-microservice.urm.puml'
pumlid: 3Sp13SCm2030LTe1RFxTXX3aK1biOOZLxPlVlUujHZrFJk-lAsAk3u3ZhatYoYCNEmqBjgWq5AJdna27BzvOJbxIh4oCOBS5Yki1u9JIC7ZZ3pW8HB5nKI4VJtSBSKtNEbFx7m00
parent: api-gateway; artifact: api-gateway-service
Puml Server ID: JSox3SCm303HLP819FRUXg49cO542_nOyFPncUvUSszHwhbpMdyT4TCt0CDLcyIHdtGsEZLOez8vG7ek33JuueLbPvUcPM84cpeCz2S0fvI6mGjluA1_b-Tt2N5D6tNcw3y0
I dont want to program this, just add the following lines to the README.md file that corresponds to this puml file 'api-gateway/etc/api-gateway-service.urm.puml'
pumlid: JSox3SCm303HLP819FRUXg49cO542_nOyFPncUvUSszHwhbpMdyT4TCt0CDLcyIHdtGsEZLOez8vG7ek33JuueLbPvUcPM84cpeCz2S0fvI6mGjluA1_b-Tt2N5D6tNcw3y0
parent: api-gateway; artifact: price-microservice
Puml Server ID: 3Sn13iGW243HgqmFeEpdDfGIoqJK8DJqzkFklyq_f56DYyFgvtOVymjWk78Hl-ECoKQzEJVFr1Mana97Wny-c2wUKbeQwCxM9YZE7O13Ka7dXI-m4mmJugH2rlVksSXXcaTe_GC0
I dont want to program this, just add the following lines to the README.md file that corresponds to this puml file 'api-gateway/etc/price-microservice.urm.puml'
pumlid: 3Sn13iGW243HgqmFeEpdDfGIoqJK8DJqzkFklyq_f56DYyFgvtOVymjWk78Hl-ECoKQzEJVFr1Mana97Wny-c2wUKbeQwCxM9YZE7O13Ka7dXI-m4mmJugH2rlVksSXXcaTe_GC0
parent: object-pool; artifact: object-pool
Puml Server ID: JSV94SCm2030Lk829Fxf1cF6bWU1XYDkFtdcjxiD9Qc3o-LrPQvu0pW-_HnvrLx1JgR9cfrimf1wCD7XnW-sWsESsXPcicl0nFW1RB-PiYqp0KxwVo-VVTMKBm00
parent: adapter; artifact: adapter
Puml Server ID: DSR14S8m30J0Lg20M7-wEMnDOiPMFDA9j0yyUEtUkzMHJTF7xI1NF4GSLzaxZtncgDVJgCPIpobzv0N2vOKtjgRHTziMI7KBcOXl10thfxB-Nz9dMJd71m00
parent: hexagonal; artifact: hexagonal
Puml Server ID: HSTB4W8X30N0g-W1XkozpPD90LO8L3wEnzUTk-xxq2fvSfhSUiJs1v7XAcr4psSwMrqQh57gcZGaBmICNdZZEDb7qsCZWasT9lm7wln1MmeXZlfVIPjbvvGl
parent: value-object; artifact: value-object
Puml Server ID: LSZ13SCm20NGLTe1RExTXX2KECBOmfza_VRQszDxDnVBNJFiTG9pVOY2dteqdBdbqf3XK4ULqQbPFWmEklZcikjgXvV9W8Olwhn-e9ijjOpjKW4fv2zgHgypktq1
parent: twin; artifact: twin
Puml Server ID: 7SR13OCm30NGLUW0n7UsCS42eyH4zdUpFbNVwNtKQij3qjjo0ICs8kTPJiMLUuPuVGnYAFNff2qdWvrk_l9wIEXfws10t88wno-4gKQ2-az9xsLaRoy0
parent: semaphore; artifact: semaphore
Puml Server ID: HSV14SCm20J0Lk82BFxf1ikCfOn06ZZizfDVVhjRjphobFJnQi2ADv7pKwwEbaU6U9q6CPGwbVh8Xy5E7xvvFoNwPVjYGDo2bEC72b5URRgGeFvNqhMirF45
parent: message-channel; artifact: message-channel
Puml Server ID: NSZB3SCm203GLTe1RExTXX1akm9YyMdMRy-zFRtdCf8wkLmUCtF72y3nxcFbhAE2dIvBjknqAIof6nCTtlZ1TdAiOMrZ9hi5ACOFe1o1WnjDD6C1Jlg_NgvzbyeN
parent: poison-pill; artifact: poison-pill
Puml Server ID: JSZ14SCm20NHLf82BExfXiYCJGOX3NpYzkDZRllsgTwjTgcmnmciV145N-rGdFMkbEZJ8OxMvo2rkXWSzE4lRxka7huj1YGyQN3UGMjgpdkh6Gdwlrl5QAk6_G00
parent: aggregator-microservices; artifact: aggregator-service
Puml Server ID: JOov3SCm301NIGQGs7iRXYPa1g8ayB7NjuiKwGvtmBrbKC-Tq_hhY5Y-0HXUjKaS-Kbdepc2HrIQ2jBpma23BvvOTdPfeooCO1iEYlu0O6l63MDQKI6Rp-CKOWSE-ey_NzEqhjH-0m00
I dont want to program this, just add the following lines to the README.md file that corresponds to this puml file 'aggregator-microservices/etc/aggregator-service.urm.puml'
pumlid: JOov3SCm301NIGQGs7iRXYPa1g8ayB7NjuiKwGvtmBrbKC-Tq_hhY5Y-0HXUjKaS-Kbdepc2HrIQ2jBpma23BvvOTdPfeooCO1iEYlu0O6l63MDQKI6Rp-CKOWSE-ey_NzEqhjH-0m00
parent: aggregator-microservices; artifact: information-microservice
Puml Server ID: LSnB3i8m303Hgy016k-vZN5DQXGxaJ_jzUcMtKXFcgSOZTgvV3oEp1Kl0CUhTScZtXNiD2tPij5Ka54N9ZfyySHjvv1ksy9CTWjGZ3i0UtVkcDCt5V9vFquX3k0a4FjCLqoPzgUjNDig7Jy0
I dont want to program this, just add the following lines to the README.md file that corresponds to this puml file 'aggregator-microservices/etc/information-microservice.urm.puml'
pumlid: LSnB3i8m303Hgy016k-vZN5DQXGxaJ_jzUcMtKXFcgSOZTgvV3oEp1Kl0CUhTScZtXNiD2tPij5Ka54N9ZfyySHjvv1ksy9CTWjGZ3i0UtVkcDCt5V9vFquX3k0a4FjCLqoPzgUjNDig7Jy0
parent: aggregator-microservices; artifact: inventory-microservice
Puml Server ID: LSpB3G8n303HLg20ZUzqOxnMrYXn8d-oedjovJRIIEyfIYrFJckFAsBw2y3mBbNYodSw6mqDrYWqEaZB6mCDFhZmEDcbwZ4nWaqTEleEm5gDAyQmemlPsCOIOWSE0j6riM7VlrVIUfdPsmy0
I dont want to program this, just add the following lines to the README.md file that corresponds to this puml file 'aggregator-microservices/etc/inventory-microservice.urm.puml'
pumlid: LSpB3G8n303HLg20ZUzqOxnMrYXn8d-oedjovJRIIEyfIYrFJckFAsBw2y3mBbNYodSw6mqDrYWqEaZB6mCDFhZmEDcbwZ4nWaqTEleEm5gDAyQmemlPsCOIOWSE0j6riM7VlrVIUfdPsmy0
parent: bridge; artifact: bridge
Puml Server ID: BSR14SCm20J0Lf82BFxf1akCJ4R26ZZYzkE7zxLljJgoIVfu7S2A3v7pLRhYo3r3l9u6CPHwJjAH5uETllpZhKbejsqn86v1a-CExQwj2mdgqv8-oyev_W00
parent: servant; artifact: servant
Puml Server ID: DSkn4O0m20NGLNG0G-ys63cDbv0SV7HzRUnUy-QYkSOkONKwWU4haV6JZe8pjd2nt1MYIBatAZKU1XjTVFEoYvT3by60c3erzW_qdPiL9CY_KrXB8rfz0G00
parent: lazy-loading; artifact: lazy-loading
Puml Server ID: LSXB3W8X303Gg-W1e7jlqu66gIc5zED4JwzRTo_lpjeaEwN9xOpO_W0mlEhWEFD89sjBWpHgMnDOyi90WoU-i7Ho7besHf2fmqJ_0GG_xo8BE-i0YlONDMtMdLE-
parent: flyweight; artifact: flyweight
Puml Server ID: HSV94S8m3030Lg20M7-w4OvYAoCh7Xtnq3ty-Eq-MQlaJcdow17JNm26gpIEdkzqidffa4Qfrm2MN1XeSEADsqxEJRU94MJgCD1_W4C-YxZr08hwNqaRPUQGBm00
parent: mutex; artifact: mutex
Puml Server ID: 9SR13OCm30NGLSe0n7UsCS62LB69x6zWV2hrdTxKhFRS9Br_3c34GkHybxtXo3L3l9u6CPHwAhMUDuETldpnl4cqtUR1WBW5ASSlf0bvI53_A-bQHcf_0G00
parent: mediator; artifact: mediator
Puml Server ID: FSV14SCm20J0Lk82BFxf1akCJKOW3JhizfDNVhkRUktP9AE_Bc2kDr7mKqx5bKSkYJeSuYXr66dFXy517xvvRxBqz7qo8E6BZDSFPDAKCO84zP-IOMMczIy0
parent: page-object; artifact: page-object
Puml Server ID: JSV14OGW30NGLjO28FVj9iOCua1Wme-sxnxtzjvMJLeS6ju-9p3NbyZvoQNYZ3sMkWo36hACJhN5ms2dYszEXwvQB4q6r6rHv_K3JIwQndwfW1Jo_npUyupUNW00
parent: factory-kit; artifact: factory-kit
Puml Server ID: JST15i8m20N0g-W14lRU1YcsQ4BooCS-RwzBTpDNSscvQKQx7C1SDwBWi-w68--vD6Gur55bTBAM9uE3dlpcikcotSjaGCCNTLu_q8C58pxbPI25_Bzcz3gpjoy0
parent: property; artifact: property
Puml Server ID: FSV13OCm30NGLTe1YEziumOBKYMEPN-3s9wUUdlltRJst2Izlmx0OYLolihUSEGdGxnEXIXAdODQpul1Jby-UTaasgwBCI2kGOFZ1pAV9ewR1FMVaZwAvUWF
parent: dependency-injection; artifact: dependency-injection
Puml Server ID: RSdB3SCW303GLPe1mFTkunWhSGG6-PEesxS3zFQajubIpyPf_NL6B7y363xra3XpJsUZgS4QbUO0wVbWeC65DvR6BeUMXH5iwZ3GVu36YxMnqgU8NamXKu63_aPD6tNbw5y0
parent: layers; artifact: layers
Puml Server ID: BSR13OCm30NGLSe0n7UsCS62L8w9x6yGszD3t-bDpQhc9kdwEO0H2v7pNVQ68zSCyNeQn53gsQbftWns-lB5yoRHTfi70-8Mr3b-8UL7F4XG_otflOpi-W80
parent: producer-consumer; artifact: producer-consumer
Puml Server ID: PSjB3iCW303HgxG70Ezx6zTO2HKso9_a-c7VtUX9y-vA8nkdZTSPiVm3O7ZNeyUPttGscXgiKMaAz94t1XhyyCBIsFkXPM44cpe8-WvODbiIMzcdfspXe7-jQL9NodW0
parent: builder; artifact: builder
Puml Server ID: DSR94O0m2030LhG0mzzkC64KXs26GzlNZw_TcRLADagJwOWOlW8OFcNdE79B9wkN1ccKUdLWoGS33KwySMdalEioC89C7Jhw5zYIfNrIrFybhPUHNLu0
parent: specification; artifact: specification
Puml Server ID: LSX14i8m20NGg-W16lRU1YcsE0d9mCTUNxVkthoxkVJQjQBVJc3bWoZuQeVXh6UbXao7EfhCGTRhOd3Gcp-yxPfs-BOOqF2amVa3vLAnbmd3ffD2_gTLZBPgz2y0
parent: state; artifact: state
Puml Server ID: 9SRH3O0m20N0LNG0ox_RO2LQqz867hg-9jxNpKLpZLt2wdG2mrSYuoST1MTiuMAvAqIHSczKQZmCDhhuvcKNBuSkWm4nTMhiNyZ141BaVocifH6jlW00
parent: reader-writer-lock; artifact: reader-writer-lock
Puml Server ID: RSZB4S8m303HLg00MtUw4R8cCP5bZpwuVL80jttxx4gIZTFaSKOiVm4OxdhqEFETpaPJWpKgpG5TScEWmGU_M1fxFxGiZ61JXu5-1nXZOolR-gqYaoxWe3-xfeswSiWF
parent: interpreter; artifact: interpreter
Puml Server ID: JSf13eCm30NHgz034E-vZGaM62Kcih_BzQ6xxjv8yr6hBJT9RzC1Z5Y8dE-oAuvSCyJhPH13gLSdRNapsEdaBy-RXEus3mR4BQXpl21zVnykFmlgVvVqNaRszW00
parent: template-method; artifact: template-method
Puml Server ID: NSZ13SCW30NGLPe1mFTkuu0Lg6n0vZjPlpttzlIEFef6bN1zDM3jDv7paw-E5cTiyJ87P22NQTGr7WOxVVZcL6NtQwJ5WFZOPBn_88WjPKWoGPkL1EN_ShZb5QPV
parent: feature-toggle; artifact: feature-toggle
Puml Server ID: NSZ14G8X30NGLhG0oDrk8XjPd12OvCTjNy_UthpxiAPvIBhUJc37WyZvgdtWp6U6U5i6CTIs9WtDYy5ER_vmEIH6jx8P4BUWoV43lOIHBWMhTnKIjB-gwRFkdFe5
parent: business-delegate; artifact: business-delegate
Puml Server ID: POl13SCm3CHMQGU8zUysgYCuBcJ5a4x9-l6_Fu84tzsgvYxf-Zg06HyYvxkqZYE_6UBrD8YXr7DGrxmPxFJZYxTTeZVR9WFY5ZGu5j2wkad4wYgD8IIe_xQaZp9pw0C0
parent: naked-objects; artifact: naked-objects-integtests
Puml Server ID: LSmn4iCW30NHgoG70FMvZGmQ6ni48tt5ru_RT3kls7VJqgDAM7yTmF8FaV6TzuOZjd2nCXMYo6KEQZrk1XkT_ELKnTkkQJ4Wfaw3_GbIlgIckPrIu2Ge_vBQyziX3izX8wyO_GS0
I dont want to program this, just add the following lines to the README.md file that corresponds to this puml file 'naked-objects/etc/naked-objects-integtests.urm.puml'
pumlid: LSmn4iCW30NHgoG70FMvZGmQ6ni48tt5ru_RT3kls7VJqgDAM7yTmF8FaV6TzuOZjd2nCXMYo6KEQZrk1XkT_ELKnTkkQJ4Wfaw3_GbIlgIckPrIu2Ge_vBQyziX3izX8wyO_GS0
parent: naked-objects; artifact: naked-objects-dom
Puml Server ID: LSZ94SCW3030Lf82G7zt8mkDZOC4eyDkF_dcjxFlhZIoSTfudH7BDm33fnuzpjpJsMXgi4QbAT17FXXeSE6DfR7tGyl223Pr4FGVGF73hSpzOWe73lgVqgRKDAahPNm1
I dont want to program this, just add the following lines to the README.md file that corresponds to this puml file 'naked-objects/etc/naked-objects-dom.urm.puml'
pumlid: LSZ94SCW3030Lf82G7zt8mkDZOC4eyDkF_dcjxFlhZIoSTfudH7BDm33fnuzpjpJsMXgi4QbAT17FXXeSE6DfR7tGyl223Pr4FGVGF73hSpzOWe73lgVqgRKDAahPNm1
parent: naked-objects; artifact: naked-objects-fixture
Puml Server ID: LSX15i8W30N0g-W187jlaq9igH1uoO_r-BfrDs_kJKkFAc7zTW3B7qJ6LzuRZjZ2nSfKY2ANEQZrk1XiTFARKnLlkwR5W9Ww3VOVIFabDStjb08dGVcVz6mVX4aE6td5w5y0
I dont want to program this, just add the following lines to the README.md file that corresponds to this puml file 'naked-objects/etc/naked-objects-fixture.urm.puml'
pumlid: LSX15i8W30N0g-W187jlaq9igH1uoO_r-BfrDs_kJKkFAc7zTW3B7qJ6LzuRZjZ2nSfKY2ANEQZrk1XiTFARKnLlkwR5W9Ww3VOVIFabDStjb08dGVcVz6mVX4aE6td5w5y0
parent: model-view-controller; artifact: model-view-controller
Puml Server ID: ROl13SCm201NQGUm-NSRQgE42h258Lw_wR-_qvtkoTOaEwNBuuoOwmNWkEl1SUOx5taR5cHHsr1WoOs13X-yi7HQV5YP645k2nJN3Q2ZavIBQPVVwqFajXJjVwdfMcUgV040
parent: proxy; artifact: proxy
Puml Server ID: 9SR13OCm30NGLM00udktCS62eCI9x6yesrEfx_Jcehd69c5rEe3X7oBZE-q5HwpXOhahH95oRrHgt0msEldYPHClkow30J5rQko_qB3-VKYG_qjXBOrezGK0
parent: memento; artifact: memento
Puml Server ID: DSgn4OCm30NGLM00h3xR2AC3SvRiaxx2-g59zugtDgiz3qdlomNC-10vF-Lik7BF4A_388PIXrBh-J3OwUOlRuT4EssR38XRa7Ay81Lz_o11_RkaQvcf_GS0
parent: decorator; artifact: decorator
Puml Server ID: HSV14SCm20J0Lk82BFxf1YF6LaP26ZZizfDVVhjRC-bPDRs_Bc35cyZvAMV3bKU6kao36ehCGQtdms2d3z-yLursshuOKBUWmV43LPNfZEcaaFzA-YWhH_y2
parent: data-mapper; artifact: data-mapper
Puml Server ID: JShB3OGm303HLg20nFVjnYGM1CN6ycTfVtFSsnjfzY5jPgUqkLqHwXy0mxUU8wuyqidQ8q4IjJqCO-QBWGOtVh5qyd5AKOmW4mT6Nu2-ZiAekapH_hkcSTNa-GC0
parent: caching; artifact: caching
Puml Server ID: DSRB4OKm2030LhG0m_rrWyWaE0bc-6ZxpujxsbMKUXwSrfSMCVq7OFYKAj5oJsUZIuCr2bq3fEU3WGOdthWTx59rcnZ1fWu3_GqGKXEjm47VIzeeCqV_0m00
parent: reactor; artifact: reactor
Puml Server ID: DSR14OGm20NGLjO23FVj1f7Hx2Ga0nzjVxtuJc-f9YrtJM-V4vZn9NA-or5nvfQXBiEWXYAZKsrvCzZfnnUlkqOzR9qCg5jGvtX2hYmOJWfvNz9xcTdR7m00
parent: iterator; artifact: iterator
Puml Server ID: FSV13OGm30NHLg00uljsOu85HeaJsTzB-yjfBwCtgrfjUKXwMovWneV8-IcduiezGxmEWnXA7PsqvSDWfvk_l1qIUjes6H2teCxnWlGDOpW9wdzAUYypU_i1
parent: callback; artifact: callback
Puml Server ID: FSVB4S8m30N0Lg20M7UwUL4qYOciUFGXxSE9s-wp6sjjKgwF8tF6YyXnjxtdKMk5E5-MOjdu6jIrRYIStlXWsIJwRij4fhW53SGFn51TmIT9yZ-jVBHPGxy0
parent: repository; artifact: repository
Puml Server ID: JSV13OCm30NGLM00udktCS42eyI9xE-YRjyUUtjlLQij3qblomNCU14vF-LKNBbdYDTX44EfevEsV1ZiTFERjqD2Jzic0-8Mr3b-89SvGZ7yGuBwrvBUoypUlW00
parent: mute-idiom; artifact: mute-idiom
Puml Server ID: JSf13iCm20NHgxG7iDdtDjH62PKX5luarq-MtSsJvgtUHdR96AyTcEj357pLJR7dDvT4EnpYgEqmqf4NWuD-V7BfidJpCXcGy4N6wmcoX1Jj-lo2ziUQONMcZHi0
parent: prototype; artifact: prototype
Puml Server ID: HSV13OCm30NGLM00udktCS62eCInxE-YRj_UUdjlRLfx7fBUbmkmU14vF-Lik7BF4AzJ8OfIvw3Mys6mqyrltWw9Tkfc38XhqE3uWSmd9Zuc9AZ_bVHHB4V_0W00
parent: step-builder; artifact: step-builder
Puml Server ID: LOZ93SCm3C1MQGQmzUysYYqaAcJ5q96i7t_x8KXkh4soKvfypeZfNm33fnuSP-xfPEtI88tQhW4i-M2WmGzlB9sS3oqJ8yZKOQ0lWOLPzcJfAoZQtwXfeyuSyW80
parent: double-checked-locking; artifact: double-checked-locking
Puml Server ID: TSdH4SCW203GLTe1bFzkGv1J6qGFeLc_MI1_x-wzkv94uJ1vDVUrFm26LwxTMnonsMYgitgcEQ1BNEXeyCKVfiAxLqqBtTbqmy1z0ygCGpXHOpgv99bqTgt0JW-LmqPUCUGF

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<artifactId>abstract-document</artifactId>
<dependencies>

View File

@ -18,7 +18,107 @@ Kit
Provide an interface for creating families of related or dependent
objects without specifying their concrete classes.
![alt text](./etc/abstract-factory_1.png "Abstract Factory")
## Explanation
Real world example
> To create a kingdom we need objects with common theme. Elven kingdom needs an Elven king, Elven castle and Elven army whereas Orcish kingdom needs an Orcish king, Orcish castle and Orcish army. There is a dependency between the objects in the kingdom.
In plain words
> A factory of factories; a factory that groups the individual but related/dependent factories together without specifying their concrete classes.
Wikipedia says
> The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes
**Programmatic Example**
Translating the kingdom example above. First of all we have some interfaces and implementation for the objects in the kingdom
```
public interface Castle {
String getDescription();
}
public interface King {
String getDescription();
}
public interface Army {
String getDescription();
}
// Elven implementations ->
public class ElfCastle implements Castle {
static final String DESCRIPTION = "This is the Elven castle!";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
public class ElfKing implements King {
static final String DESCRIPTION = "This is the Elven king!";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
public class ElfArmy implements Army {
static final String DESCRIPTION = "This is the Elven Army!";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
// Orcish implementations similarly...
```
Then we have the abstraction and implementations for the kingdom factory
```
public interface KingdomFactory {
Castle createCastle();
King createKing();
Army createArmy();
}
public class ElfKingdomFactory implements KingdomFactory {
public Castle createCastle() {
return new ElfCastle();
}
public King createKing() {
return new ElfKing();
}
public Army createArmy() {
return new ElfArmy();
}
}
public class OrcKingdomFactory implements KingdomFactory {
public Castle createCastle() {
return new OrcCastle();
}
public King createKing() {
return new OrcKing();
}
public Army createArmy() {
return new OrcArmy();
}
}
```
Now we have our abstract factory that lets us make family of related objects i.e. Elven kingdom factory creates Elven castle, king and army etc.
```
KingdomFactory factory = new ElfKingdomFactory();
Castle castle = factory.createCastle();
King king = factory.createKing();
Army army = factory.createArmy();
castle.getDescription(); // Output: This is the Elven castle!
king.getDescription(); // Output: This is the Elven king!
army.getDescription(); // Output: This is the Elven Army!
```
## Applicability
Use the Abstract Factory pattern when
@ -27,6 +127,19 @@ Use the Abstract Factory pattern when
* a system should be configured with one of multiple families of products
* a family of related product objects is designed to be used together, and you need to enforce this constraint
* you want to provide a class library of products, and you want to reveal just their interfaces, not their implementations
* the lifetime of the dependency is conceptually shorter than the lifetime of the consumer.
* you need a run-time value to construct a particular dependency
* you want to decide which product to call from a family at runtime.
* you need to supply one or more parameters only known at run-time before you can resolve a dependency.
## Use Cases:
* Selecting to call the appropriate implementation of FileSystemAcmeService or DatabaseAcmeService or NetworkAcmeService at runtime.
* Unit test case writing becomes much easier
## Consequences:
* Dependency injection in java hides the service class dependencies that can lead to runtime errors that would have been caught at compile time.
## Real world examples

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@ -1,159 +0,0 @@
<?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="false" nesting-relationships="true">
<interface id="1" language="java" name="com.iluwatar.abstractfactory.Army" project="abstract-factory"
file="/abstract-factory/src/main/java/com/iluwatar/abstractfactory/Army.java" binary="false" corner="BOTTOM_RIGHT">
<position height="70" width="161" x="1407" y="300"/>
<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="2" language="java" name="com.iluwatar.abstractfactory.KingdomFactory" project="abstract-factory"
file="/abstract-factory/src/main/java/com/iluwatar/abstractfactory/KingdomFactory.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="124" width="161" x="1001" y="300"/>
<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>
<class id="3" language="java" name="com.iluwatar.abstractfactory.ElfCastle" project="abstract-factory"
file="/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfCastle.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="106" width="161" x="96" y="118"/>
<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="4" language="java" name="com.iluwatar.abstractfactory.ElfKingdomFactory" project="abstract-factory"
file="/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKingdomFactory.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="142" width="161" x="900" y="118"/>
<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="5" language="java" name="com.iluwatar.abstractfactory.ElfKing" project="abstract-factory"
file="/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKing.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="106" width="161" x="498" y="118"/>
<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>
<interface id="6" language="java" name="com.iluwatar.abstractfactory.King" project="abstract-factory"
file="/abstract-factory/src/main/java/com/iluwatar/abstractfactory/King.java" binary="false" corner="BOTTOM_RIGHT">
<position height="70" width="161" x="599" y="300"/>
<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>
<class id="7" language="java" name="com.iluwatar.abstractfactory.OrcCastle" project="abstract-factory"
file="/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcCastle.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="106" width="161" x="297" y="118"/>
<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="8" language="java" name="com.iluwatar.abstractfactory.OrcKing" project="abstract-factory"
file="/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKing.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="106" width="161" x="699" y="118"/>
<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="9" language="java" name="com.iluwatar.abstractfactory.ElfArmy" project="abstract-factory"
file="/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfArmy.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="106" width="161" x="1306" y="118"/>
<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="10" language="java" name="com.iluwatar.abstractfactory.OrcArmy" project="abstract-factory"
file="/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcArmy.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="106" width="161" x="1507" y="118"/>
<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>
<interface id="11" language="java" name="com.iluwatar.abstractfactory.Castle" project="abstract-factory"
file="/abstract-factory/src/main/java/com/iluwatar/abstractfactory/Castle.java" binary="false" corner="BOTTOM_RIGHT">
<position height="70" width="161" x="197" y="300"/>
<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>
<class id="12" language="java" name="com.iluwatar.abstractfactory.OrcKingdomFactory" project="abstract-factory"
file="/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKingdomFactory.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="142" width="165" x="1101" y="118"/>
<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>
<realization id="13">
<end type="SOURCE" refId="4"/>
<end type="TARGET" refId="2"/>
</realization>
<realization id="14">
<end type="SOURCE" refId="7"/>
<end type="TARGET" refId="11"/>
</realization>
<realization id="15">
<end type="SOURCE" refId="8"/>
<end type="TARGET" refId="6"/>
</realization>
<realization id="16">
<end type="SOURCE" refId="3"/>
<end type="TARGET" refId="11"/>
</realization>
<realization id="17">
<end type="SOURCE" refId="10"/>
<end type="TARGET" refId="1"/>
</realization>
<realization id="18">
<end type="SOURCE" refId="12"/>
<end type="TARGET" refId="2"/>
</realization>
<realization id="19">
<end type="SOURCE" refId="5"/>
<end type="TARGET" refId="6"/>
</realization>
<realization id="20">
<end type="SOURCE" refId="9"/>
<end type="TARGET" refId="1"/>
</realization>
<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>

View File

@ -1,89 +0,0 @@
@startuml
package com.iluwatar.abstractfactory {
class App {
- LOGGER : Logger {static}
- army : Army
- castle : Castle
- king : King
+ App()
+ createKingdom(factory : KingdomFactory)
+ getArmy() : Army
~ getArmy(factory : KingdomFactory) : Army
+ getCastle() : Castle
~ getCastle(factory : KingdomFactory) : Castle
+ getKing() : King
~ getKing(factory : KingdomFactory) : King
+ main(args : String[]) {static}
- setArmy(army : Army)
- setCastle(castle : Castle)
- setKing(king : King)
}
interface Army {
+ getDescription() : String {abstract}
}
interface Castle {
+ getDescription() : String {abstract}
}
class ElfArmy {
~ DESCRIPTION : String {static}
+ ElfArmy()
+ getDescription() : String
}
class ElfCastle {
~ DESCRIPTION : String {static}
+ ElfCastle()
+ getDescription() : String
}
class ElfKing {
~ DESCRIPTION : String {static}
+ ElfKing()
+ getDescription() : String
}
class ElfKingdomFactory {
+ ElfKingdomFactory()
+ createArmy() : Army
+ createCastle() : Castle
+ createKing() : King
}
interface King {
+ getDescription() : String {abstract}
}
interface KingdomFactory {
+ createArmy() : Army {abstract}
+ createCastle() : Castle {abstract}
+ createKing() : King {abstract}
}
class OrcArmy {
~ DESCRIPTION : String {static}
+ OrcArmy()
+ getDescription() : String
}
class OrcCastle {
~ DESCRIPTION : String {static}
+ OrcCastle()
+ getDescription() : String
}
class OrcKing {
~ DESCRIPTION : String {static}
+ OrcKing()
+ getDescription() : String
}
class OrcKingdomFactory {
+ OrcKingdomFactory()
+ createArmy() : Army
+ createCastle() : Castle
+ createKing() : King
}
}
App --> "-castle" Castle
App --> "-king" King
App --> "-army" Army
ElfArmy ..|> Army
ElfCastle ..|> Castle
ElfKing ..|> King
ElfKingdomFactory ..|> KingdomFactory
OrcArmy ..|> Army
OrcCastle ..|> Castle
OrcKing ..|> King
OrcKingdomFactory ..|> KingdomFactory
@enduml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<artifactId>abstract-factory</artifactId>
<dependencies>

View File

@ -28,6 +28,9 @@ import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
/**
* Test for abstract factory
*/
public class AbstractFactoryTest {
private App app = new App();

View File

@ -19,7 +19,85 @@ Convert the interface of a class into another interface the clients
expect. Adapter lets classes work together that couldn't otherwise because of
incompatible interfaces.
![alt text](./etc/adapter.png "Adapter")
## Explanation
Real world example
> Consider that you have some pictures in your memory card and you need to transfer them to your computer. In order to transfer them you need some kind of adapter that is compatible with your computer ports so that you can attach memory card to your computer. In this case card reader is an adapter.
> Another example would be the famous power adapter; a three legged plug can't be connected to a two pronged outlet, it needs to use a power adapter that makes it compatible with the two pronged outlet.
> Yet another example would be a translator translating words spoken by one person to another
In plain words
> Adapter pattern lets you wrap an otherwise incompatible object in an adapter to make it compatible with another class.
Wikipedia says
> In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code.
**Programmatic Example**
Consider a captain that can only use rowing boats and cannot sail at all.
First we have interfaces `RowingBoat` and `FishingBoat`
```
public interface RowingBoat {
void row();
}
public class FishingBoat {
private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoat.class);
public void sail() {
LOGGER.info("The fishing boat is sailing");
}
}
```
And captain expects an implementation of `RowingBoat` interface to be able to move
```
public class Captain implements RowingBoat {
private RowingBoat rowingBoat;
public Captain(RowingBoat rowingBoat) {
this.rowingBoat = rowingBoat;
}
@Override
public void row() {
rowingBoat.row();
}
}
```
Now let's say the pirates are coming and our captain needs to escape but there is only fishing boat available. We need to create an adapter that allows the captain to operate the fishing boat with his rowing boat skills.
```
public class FishingBoatAdapter implements RowingBoat {
private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoatAdapter.class);
private FishingBoat boat;
public FishingBoatAdapter() {
boat = new FishingBoat();
}
@Override
public void row() {
boat.sail();
}
}
```
And now the `Captain` can use the `FishingBoat` to escape the pirates.
```
Captain captain = new Captain(new FishingBoatAdapter());
captain.row();
```
## Applicability
Use the Adapter pattern when
@ -27,6 +105,20 @@ Use the Adapter pattern when
* you want to use an existing class, and its interface does not match the one you need
* you want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don't necessarily have compatible interfaces
* you need to use several existing subclasses, but it's impractical to adapt their interface by subclassing every one. An object adapter can adapt the interface of its parent class.
* most of the applications using third party libraries use adapters as a middle layer between the application and the 3rd party library to decouple the application from the library. If another library has to be used only an adapter for the new library is required without having to change the application code.
## Consequences:
Class and object adapters have different trade-offs. A class adapter
* adapts Adaptee to Target by committing to a concrete Adaptee class. As a consequence, a class adapter wont work when we want to adapt a class and all its subclasses.
* lets Adapter override some of Adaptees behavior, since Adapter is a subclass of Adaptee.
* introduces only one object, and no additional pointer indirection is needed to get to the adaptee.
An object adapter
* lets a single Adapter work with many Adaptees—that is, the Adaptee itself and all of its subclasses (if any). The Adapter can also add functionality to all Adaptees at once.
* makes it harder to override Adaptee behavior. It will require subclassing Adaptee and making Adapter refer to the subclass rather than the Adaptee itself.
## Real world examples

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,37 +0,0 @@
@startuml
package com.iluwatar.adapter {
class App {
+ App()
+ main(args : String[]) {static}
}
class BattleFishingBoat {
- LOGGER : Logger {static}
- boat : FishingBoat
+ BattleFishingBoat()
+ fire()
+ move()
}
interface BattleShip {
+ fire() {abstract}
+ move() {abstract}
}
class Captain {
- battleship : BattleShip
+ Captain()
+ Captain(battleship : BattleShip)
+ fire()
+ move()
+ setBattleship(battleship : BattleShip)
}
class FishingBoat {
- LOGGER : Logger {static}
+ FishingBoat()
+ fish()
+ sail()
}
}
BattleFishingBoat --> "-boat" FishingBoat
Captain --> "-battleship" BattleShip
BattleFishingBoat ..|> BattleShip
Captain ..|> BattleShip
@enduml

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<artifactId>adapter</artifactId>
<dependencies>

View File

@ -34,14 +34,14 @@ package com.iluwatar.adapter;
* object. This example uses the object adapter approach.
*
* <p>
* The Adapter ({@link BattleFishingBoat}) converts the interface of the adaptee class (
* {@link FishingBoat}) into a suitable one expected by the client ( {@link BattleShip} ).
* The Adapter ({@link FishingBoatAdapter}) converts the interface of the adaptee class (
* {@link FishingBoat}) into a suitable one expected by the client ( {@link RowingBoat} ).
*
* <p>
* The story of this implementation is this. <br>
* Pirates are coming! we need a {@link BattleShip} to fight! We have a {@link FishingBoat} and our
* Pirates are coming! we need a {@link RowingBoat} to flee! We have a {@link FishingBoat} and our
* captain. We have no time to make up a new ship! we need to reuse this {@link FishingBoat}. The
* captain needs a battleship which can fire and move. The spec is in {@link BattleShip}. We will
* captain needs a rowing boat which he can operate. The spec is in {@link RowingBoat}. We will
* use the Adapter pattern to reuse {@link FishingBoat}.
*
*/
@ -53,8 +53,8 @@ public class App {
* @param args command line args
*/
public static void main(String[] args) {
Captain captain = new Captain(new BattleFishingBoat());
captain.move();
captain.fire();
// The captain can only operate rowing boats but with adapter he is able to use fishing boats as well
Captain captain = new Captain(new FishingBoatAdapter());
captain.row();
}
}

View File

@ -23,33 +23,26 @@
package com.iluwatar.adapter;
/**
* The Captain uses {@link BattleShip} to fight. <br>
* The Captain uses {@link RowingBoat} to sail. <br>
* This is the client in the pattern.
*/
public class Captain implements BattleShip {
public class Captain implements RowingBoat {
private BattleShip battleship;
private RowingBoat rowingBoat;
public Captain() {
public Captain() {}
public Captain(RowingBoat rowingBoat) {
this.rowingBoat = rowingBoat;
}
public Captain(BattleShip battleship) {
this.battleship = battleship;
}
public void setBattleship(BattleShip battleship) {
this.battleship = battleship;
public void setRowingBoat(RowingBoat rowingBoat) {
this.rowingBoat = rowingBoat;
}
@Override
public void fire() {
battleship.fire();
}
@Override
public void move() {
battleship.move();
public void row() {
rowingBoat.row();
}
}

View File

@ -27,7 +27,8 @@ import org.slf4j.LoggerFactory;
/**
*
* Device class (adaptee in the pattern). We want to reuse this class
* Device class (adaptee in the pattern). We want to reuse this class.
* Fishing boat moves by sailing.
*
*/
public class FishingBoat {
@ -35,11 +36,7 @@ public class FishingBoat {
private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoat.class);
public void sail() {
LOGGER.info("The Boat is moving to that place");
}
public void fish() {
LOGGER.info("fishing ...");
LOGGER.info("The fishing boat is sailing");
}
}

View File

@ -20,28 +20,24 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.bridge;
package com.iluwatar.adapter;
/**
*
* MagicWeapon
*
*
* Adapter class. Adapts the interface of the device ({@link FishingBoat}) into {@link RowingBoat}
* interface expected by the client ({@link Captain}).
*
*/
public abstract class MagicWeapon {
public class FishingBoatAdapter implements RowingBoat {
protected MagicWeaponImpl imp;
private FishingBoat boat;
public MagicWeapon(MagicWeaponImpl imp) {
this.imp = imp;
public FishingBoatAdapter() {
boat = new FishingBoat();
}
public abstract void wield();
public abstract void swing();
public abstract void unwield();
public MagicWeaponImpl getImp() {
return imp;
@Override
public void row() {
boat.sail();
}
}

View File

@ -24,13 +24,11 @@ package com.iluwatar.adapter;
/**
* The interface expected by the client.<br>
* A Battleship can fire and move.
* A rowing boat is rowed to move.
*
*/
public interface BattleShip {
public interface RowingBoat {
void fire();
void move();
void row();
}

View File

@ -39,9 +39,9 @@ public class AdapterPatternTest {
private Map<String, Object> beans;
private static final String BATTLESHIP_BEAN = "engineer";
private static final String FISHING_BEAN = "fisher";
private static final String CAPTAIN_BEAN = "captain";
private static final String ROWING_BEAN = "captain";
/**
* This method runs before the test execution and sets the bean objects in the beans Map.
@ -50,34 +50,29 @@ public class AdapterPatternTest {
public void setup() {
beans = new HashMap<>();
BattleFishingBoat battleFishingBoat = spy(new BattleFishingBoat());
beans.put(BATTLESHIP_BEAN, battleFishingBoat);
FishingBoatAdapter fishingBoatAdapter = spy(new FishingBoatAdapter());
beans.put(FISHING_BEAN, fishingBoatAdapter);
Captain captain = new Captain();
captain.setBattleship((BattleFishingBoat) beans.get(BATTLESHIP_BEAN));
beans.put(CAPTAIN_BEAN, captain);
captain.setRowingBoat((FishingBoatAdapter) beans.get(FISHING_BEAN));
beans.put(ROWING_BEAN, captain);
}
/**
* This test asserts that when we use the move() method on a captain bean(client), it is
* internally calling move method on the battleship object. The Adapter ({@link BattleFishingBoat}
* This test asserts that when we use the row() method on a captain bean(client), it is
* internally calling sail method on the fishing boat object. The Adapter ({@link FishingBoatAdapter}
* ) converts the interface of the target class ( {@link FishingBoat}) into a suitable one
* expected by the client ({@link Captain} ).
*/
@Test
public void testAdapter() {
BattleShip captain = (BattleShip) beans.get(CAPTAIN_BEAN);
RowingBoat captain = (RowingBoat) beans.get(ROWING_BEAN);
// when captain moves
captain.move();
captain.row();
// the captain internally calls the battleship object to move
BattleShip battleship = (BattleShip) beans.get(BATTLESHIP_BEAN);
verify(battleship).move();
// same with above with firing
captain.fire();
verify(battleship).fire();
RowingBoat adapter = (RowingBoat) beans.get(FISHING_BEAN);
verify(adapter).row();
}
}

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>aggregator-microservices</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -25,6 +25,9 @@ package com.iluwatar.aggregator.microservices;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Spring Boot EntryPoint Class
*/
@SpringBootApplication
public class App {

View File

@ -22,15 +22,18 @@
*/
package com.iluwatar.aggregator.microservices;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
/**
* Test Aggregation of domain objects
*/
public class AggregatorTest {
@InjectMocks
@ -64,4 +67,4 @@ public class AggregatorTest {
assertEquals(inventories, testProduct.getProductInventories());
}
}
}

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>aggregator-microservices</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -26,6 +26,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* Controller providing endpoints to retrieve information about products
*/
@RestController
public class InformationController {

View File

@ -25,6 +25,9 @@ package com.iluwatar.information.microservice;
import org.junit.Assert;
import org.junit.Test;
/**
* Test for Information Rest Controller
*/
public class InformationControllerTest {
@Test
@ -36,4 +39,4 @@ public class InformationControllerTest {
Assert.assertEquals("The Product Title.", title);
}
}
}

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>aggregator-microservices</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -26,6 +26,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* Controller providing endpoints to retrieve product inventories
*/
@RestController
public class InventoryController {

View File

@ -25,8 +25,10 @@ package com.iluwatar.inventory.microservice;
import org.junit.Assert;
import org.junit.Test;
/**
* Test Inventory Rest Controller
*/
public class InventoryControllerTest {
@Test
public void testGetProductInventories() throws Exception {
InventoryController inventoryController = new InventoryController();
@ -35,4 +37,4 @@ public class InventoryControllerTest {
Assert.assertEquals(5, numberOfInventories);
}
}
}

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>aggregator-microservices</artifactId>

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>api-gateway</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>api-gateway-service</artifactId>

View File

@ -35,7 +35,7 @@ import java.io.IOException;
* An adapter to communicate with the Image microservice
*/
@Component
public class ImageClientImpl implements ImageClient{
public class ImageClientImpl implements ImageClient {
/**
* Makes a simple HTTP Get request to the Image microservice
* @return The path to the image

View File

@ -35,7 +35,7 @@ import java.io.IOException;
* An adapter to communicate with the Price microservice
*/
@Component
public class PriceClientImpl implements PriceClient{
public class PriceClientImpl implements PriceClient {
/**
* Makes a simple HTTP Get request to the Price microservice
* @return The price of the product

View File

@ -22,15 +22,18 @@
*/
package com.iluwatar.api.gateway;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
/**
* Test API Gateway Pattern
*/
public class ApiGatewayTest {
@InjectMocks

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>api-gateway</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -25,6 +25,9 @@ package com.iluwatar.image.microservice;
import org.junit.Assert;
import org.junit.Test;
/**
* Test for Image Rest Controller
*/
public class ImageControllerTest {
@Test
public void testGetImagePath() {

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>api-gateway</artifactId>

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>api-gateway</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -25,6 +25,10 @@ package com.iluwatar.price.microservice;
import org.junit.Assert;
import org.junit.Test;
/**
* Test for Price Rest Controller
*/
public class PriceControllerTest {
@Test
public void testgetPrice() {

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<artifactId>async-method-invocation</artifactId>
<dependencies>

View File

@ -25,8 +25,8 @@ package com.iluwatar.async.method.invocation;
import java.util.concurrent.ExecutionException;
/**
*
* AsyncResult interface
* @param <T> parameter returned when getValue is invoked
*/
public interface AsyncResult<T> {

View File

@ -139,7 +139,7 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
@Override
public void await() throws InterruptedException {
synchronized (lock) {
if (!isCompleted()) {
while (!isCompleted()) {
lock.wait();
}
}

27
balking/README.md Normal file
View File

@ -0,0 +1,27 @@
---
layout: pattern
title: Balking
folder: balking
permalink: /patterns/balking/
categories: Concurrency
tags:
- Java
- Difficulty-Beginner
---
## Intent
Balking Pattern is used to prevent an object from executing certain code if it is an
incomplete or inappropriate state
![alt text](./etc/balking.png "Balking")
## Applicability
Use the Balking pattern when
*you want to invoke an action on an object only when it is in a particular state
*objects are generally only in a state that is prone to balking temporarily
but for an unknown amount of time
## Related patterns
* Guarded Suspension Pattern
* Double Checked Locking Pattern

BIN
balking/etc/balking.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

46
balking/etc/balking.ucls Normal file
View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<class-diagram version="1.1.13" 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.balking.App" project="balking"
file="/balking/src/main/java/com/iluwatar/balking/App.java" binary="false" corner="BOTTOM_RIGHT">
<position height="113" width="114" x="135" y="103"/>
<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.balking.WashingMachine" project="balking"
file="/balking/src/main/java/com/iluwatar/balking/WashingMachine.java" binary="false" corner="BOTTOM_RIGHT">
<position height="149" width="268" x="289" y="103"/>
<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>
<enumeration id="3" language="java" name="com.iluwatar.balking.WashingMachineState" project="balking"
file="/balking/src/main/java/com/iluwatar/balking/WashingMachineState.java" binary="false" corner="BOTTOM_RIGHT">
<position height="113" width="192" x="289" y="292"/>
<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>
</enumeration>
<association id="4">
<end type="SOURCE" refId="2" navigable="false">
<attribute id="5" name="washingMachineState"/>
<multiplicity id="6" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="3" 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>

View File

@ -0,0 +1,24 @@
@startuml
package com.iluwatar.balking {
class App {
- LOGGER : Logger {static}
+ App()
+ main(args : String[]) {static}
}
class WashingMachine {
- LOGGER : Logger {static}
- washingMachineState : WashingMachineState
+ WashingMachine()
+ endOfWashing()
+ getWashingMachineState() : WashingMachineState
+ wash()
}
enum WashingMachineState {
+ ENABLED {static}
+ WASHING {static}
+ valueOf(name : String) : WashingMachineState {static}
+ values() : WashingMachineState[] {static}
}
}
WashingMachine --> "-washingMachineState" WashingMachineState
@enduml

46
balking/pom.xml Normal file
View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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 xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.17.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>balking</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,65 @@
/**
* The MIT License
* Copyright (c) 2014 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.balking;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* In Balking Design Pattern if an objects method is invoked when it is in an inappropriate state,
* then the method will return without doing anything. Objects that use this pattern are generally only in a
* state that is prone to balking temporarily but for an unknown amount of time
*
* In this example implementation WashingMachine is an object that has two states
* in which it can be: ENABLED and WASHING. If the machine is ENABLED
* the state is changed into WASHING that any other thread can't invoke this action on this and then do the job.
* On the other hand if it have been already washing and any other thread execute wash()
* it can't do that once again and returns doing nothing.
*/
public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
/**
* @param args the command line arguments - not used
*/
public static void main(String... args) {
final WashingMachine washingMachine = new WashingMachine();
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
executorService.execute(washingMachine::wash);
}
executorService.shutdown();
try {
executorService.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ie) {
LOGGER.error("ERROR: Waiting on executor service shutdown!");
}
}
}

View File

@ -0,0 +1,76 @@
/**
* The MIT License
* Copyright (c) 2014 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.balking;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Washing machine class
*/
public class WashingMachine {
private static final Logger LOGGER = LoggerFactory.getLogger(WashingMachine.class);
private WashingMachineState washingMachineState;
public WashingMachine() {
washingMachineState = WashingMachineState.ENABLED;
}
public WashingMachineState getWashingMachineState() {
return washingMachineState;
}
/**
* Method responsible for washing
* if the object is in appropriate state
*/
public void wash() {
synchronized (this) {
LOGGER.info("{}: Actual machine state: {}", Thread.currentThread().getName(), getWashingMachineState());
if (washingMachineState == WashingMachineState.WASHING) {
LOGGER.error("ERROR: Cannot wash if the machine has been already washing!");
return;
}
washingMachineState = WashingMachineState.WASHING;
}
LOGGER.info("{}: Doing the washing", Thread.currentThread().getName());
try {
Thread.sleep(50);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
endOfWashing();
}
/**
* Method responsible of ending the washing
* by changing machine state
*/
public synchronized void endOfWashing() {
washingMachineState = WashingMachineState.ENABLED;
LOGGER.info("{}: Washing completed.", Thread.currentThread().getId());
}
}

View File

@ -0,0 +1,32 @@
/**
* The MIT License
* Copyright (c) 2014 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.balking;
/**
* WashingMachineState enum describes in which state machine is,
* it can be enabled and ready to work as well as during washing
*/
public enum WashingMachineState {
ENABLED, WASHING
}

View File

@ -0,0 +1,39 @@
/**
* The MIT License
* Copyright (c) 2014 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.balking;
import org.junit.Test;
/**
* Application test
*/
public class AppTest {
@Test
public void main() throws Exception {
String[] args = {};
App.main(args);
}
}

View File

@ -0,0 +1,65 @@
/**
* The MIT License
* Copyright (c) 2014 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.balking;
import org.junit.Test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
/**
* Tests for {@link WashingMachine}
*/
public class WashingMachineTest {
private volatile WashingMachineState machineStateGlobal;
@Test
public void wash() throws Exception {
WashingMachine washingMachine = new WashingMachine();
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(washingMachine::wash);
executorService.execute(() -> {
washingMachine.wash();
machineStateGlobal = washingMachine.getWashingMachineState();
});
executorService.shutdown();
try {
executorService.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
assertEquals(WashingMachineState.WASHING, machineStateGlobal);
}
@Test
public void endOfWashing() throws Exception {
WashingMachine washingMachine = new WashingMachine();
washingMachine.wash();
assertEquals(WashingMachineState.ENABLED, washingMachine.getWashingMachineState());
}
}

View File

@ -15,10 +15,170 @@ tags:
Handle/Body
## Intent
Decouple an abstraction from its implementation so that the two can
vary independently.
Decouple an abstraction from its implementation so that the two can vary independently.
![alt text](./etc/bridge.png "Bridge")
## Explanation
Real world example
> Consider you have a weapon with different enchantments and you are supposed to allow mixing different weapons with different enchantments. What would you do? Create multiple copies of each of the weapons for each of the enchantments or would you just create separate enchantment and set it for the weapon as needed? Bridge pattern allows you to do the second.
In Plain Words
> Bridge pattern is about preferring composition over inheritance. Implementation details are pushed from a hierarchy to another object with a separate hierarchy.
Wikipedia says
> The bridge pattern is a design pattern used in software engineering that is meant to "decouple an abstraction from its implementation so that the two can vary independently"
**Programmatic Example**
Translating our weapon example from above. Here we have the `Weapon` hierarchy
```
public interface Weapon {
void wield();
void swing();
void unwield();
Enchantment getEnchantment();
}
public class Sword implements Weapon {
private final Enchantment enchantment;
public Sword(Enchantment enchantment) {
this.enchantment = enchantment;
}
@Override
public void wield() {
LOGGER.info("The sword is wielded.");
enchantment.onActivate();
}
@Override
public void swing() {
LOGGER.info("The sword is swinged.");
enchantment.apply();
}
@Override
public void unwield() {
LOGGER.info("The sword is unwielded.");
enchantment.onDeactivate();
}
@Override
public Enchantment getEnchantment() {
return enchantment;
}
}
public class Hammer implements Weapon {
private final Enchantment enchantment;
public Hammer(Enchantment enchantment) {
this.enchantment = enchantment;
}
@Override
public void wield() {
LOGGER.info("The hammer is wielded.");
enchantment.onActivate();
}
@Override
public void swing() {
LOGGER.info("The hammer is swinged.");
enchantment.apply();
}
@Override
public void unwield() {
LOGGER.info("The hammer is unwielded.");
enchantment.onDeactivate();
}
@Override
public Enchantment getEnchantment() {
return enchantment;
}
}
```
And the separate enchantment hierarchy
```
public interface Enchantment {
void onActivate();
void apply();
void onDeactivate();
}
public class FlyingEnchantment implements Enchantment {
@Override
public void onActivate() {
LOGGER.info("The item begins to glow faintly.");
}
@Override
public void apply() {
LOGGER.info("The item flies and strikes the enemies finally returning to owner's hand.");
}
@Override
public void onDeactivate() {
LOGGER.info("The item's glow fades.");
}
}
public class SoulEatingEnchantment implements Enchantment {
@Override
public void onActivate() {
LOGGER.info("The item spreads bloodlust.");
}
@Override
public void apply() {
LOGGER.info("The item eats the soul of enemies.");
}
@Override
public void onDeactivate() {
LOGGER.info("Bloodlust slowly disappears.");
}
}
```
And both the hierarchies in action
```
Sword enchantedSword = new Sword(new SoulEatingEnchantment());
enchantedSword.wield();
enchantedSword.swing();
enchantedSword.unwield();
// The sword is wielded.
// The item spreads bloodlust.
// The sword is swinged.
// The item eats the soul of enemies.
// The sword is unwielded.
// Bloodlust slowly disappears.
Hammer hammer = new Hammer(new FlyingEnchantment());
hammer.wield();
hammer.swing();
hammer.unwield();
// The hammer is wielded.
// The item begins to glow faintly.
// The hammer is swinged.
// The item flies and strikes the enemies finally returning to owner's hand.
// The hammer is unwielded.
// The item's glow fades.
```
## Applicability
Use the Bridge pattern when

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

View File

@ -1,157 +0,0 @@
<?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="false" nesting-relationships="true">
<class id="1" language="java" name="com.iluwatar.bridge.FlyingMagicWeaponImpl" project="bridge"
file="/bridge/src/main/java/com/iluwatar/bridge/FlyingMagicWeaponImpl.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="515" y="591"/>
<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.bridge.SoulEatingMagicWeaponImpl" project="bridge"
file="/bridge/src/main/java/com/iluwatar/bridge/SoulEatingMagicWeaponImpl.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="791" y="605"/>
<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.bridge.Stormbringer" project="bridge"
file="/bridge/src/main/java/com/iluwatar/bridge/Stormbringer.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="791" y="788"/>
<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="4" language="java" name="com.iluwatar.bridge.MagicWeaponImpl" project="bridge"
file="/bridge/src/main/java/com/iluwatar/bridge/MagicWeaponImpl.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="791" y="433"/>
<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="5" language="java" name="com.iluwatar.bridge.BlindingMagicWeaponImpl" project="bridge"
file="/bridge/src/main/java/com/iluwatar/bridge/BlindingMagicWeaponImpl.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="1105" y="593"/>
<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="6" language="java" name="com.iluwatar.bridge.SoulEatingMagicWeapon" project="bridge"
file="/bridge/src/main/java/com/iluwatar/bridge/SoulEatingMagicWeapon.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="380" y="21"/>
<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="7" language="java" name="com.iluwatar.bridge.Excalibur" project="bridge"
file="/bridge/src/main/java/com/iluwatar/bridge/Excalibur.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="1105" y="782"/>
<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="8" language="java" name="com.iluwatar.bridge.Mjollnir" project="bridge"
file="/bridge/src/main/java/com/iluwatar/bridge/Mjollnir.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="515" y="788"/>
<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="9" language="java" name="com.iluwatar.bridge.BlindingMagicWeapon" project="bridge"
file="/bridge/src/main/java/com/iluwatar/bridge/BlindingMagicWeapon.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="791" y="14"/>
<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="10" language="java" name="com.iluwatar.bridge.MagicWeapon" project="bridge"
file="/bridge/src/main/java/com/iluwatar/bridge/MagicWeapon.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="791" y="237"/>
<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="11" language="java" name="com.iluwatar.bridge.FlyingMagicWeapon" project="bridge"
file="/bridge/src/main/java/com/iluwatar/bridge/FlyingMagicWeapon.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="1144" y="12"/>
<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>
<generalization id="12">
<end type="SOURCE" refId="8"/>
<end type="TARGET" refId="1"/>
</generalization>
<generalization id="13">
<end type="SOURCE" refId="1"/>
<end type="TARGET" refId="4"/>
</generalization>
<generalization id="14">
<end type="SOURCE" refId="9"/>
<end type="TARGET" refId="10"/>
</generalization>
<generalization id="15">
<end type="SOURCE" refId="2"/>
<end type="TARGET" refId="4"/>
</generalization>
<association id="16">
<end type="SOURCE" refId="10" navigable="false">
<attribute id="17" name="imp">
<position height="0" width="0" x="478" y="284"/>
</attribute>
<multiplicity id="18" minimum="0" maximum="1">
<position height="0" width="0" x="478" y="284"/>
</multiplicity>
</end>
<end type="TARGET" refId="4" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<generalization id="19">
<end type="SOURCE" refId="5"/>
<end type="TARGET" refId="4"/>
</generalization>
<generalization id="20">
<end type="SOURCE" refId="6"/>
<end type="TARGET" refId="10"/>
</generalization>
<generalization id="21">
<end type="SOURCE" refId="7"/>
<end type="TARGET" refId="5"/>
</generalization>
<generalization id="22">
<end type="SOURCE" refId="3"/>
<end type="TARGET" refId="2"/>
</generalization>
<generalization id="23">
<end type="SOURCE" refId="11"/>
<end type="TARGET" refId="10"/>
</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>

View File

@ -1,92 +0,0 @@
@startuml
package com.iluwatar.bridge {
class App {
+ App()
+ main(args : String[]) {static}
}
class BlindingMagicWeapon {
+ BlindingMagicWeapon(imp : BlindingMagicWeaponImpl)
+ blind()
+ getImp() : BlindingMagicWeaponImpl
+ swing()
+ unwield()
+ wield()
}
abstract class BlindingMagicWeaponImpl {
+ BlindingMagicWeaponImpl()
+ blindImp() {abstract}
}
class Excalibur {
- LOGGER : Logger {static}
+ Excalibur()
+ blindImp()
+ swingImp()
+ unwieldImp()
+ wieldImp()
}
class FlyingMagicWeapon {
+ FlyingMagicWeapon(imp : FlyingMagicWeaponImpl)
+ fly()
+ getImp() : FlyingMagicWeaponImpl
+ swing()
+ unwield()
+ wield()
}
abstract class FlyingMagicWeaponImpl {
+ FlyingMagicWeaponImpl()
+ flyImp() {abstract}
}
abstract class MagicWeapon {
# imp : MagicWeaponImpl
+ MagicWeapon(imp : MagicWeaponImpl)
+ getImp() : MagicWeaponImpl
+ swing() {abstract}
+ unwield() {abstract}
+ wield() {abstract}
}
abstract class MagicWeaponImpl {
+ MagicWeaponImpl()
+ swingImp() {abstract}
+ unwieldImp() {abstract}
+ wieldImp() {abstract}
}
class Mjollnir {
- LOGGER : Logger {static}
+ Mjollnir()
+ flyImp()
+ swingImp()
+ unwieldImp()
+ wieldImp()
}
class SoulEatingMagicWeapon {
+ SoulEatingMagicWeapon(imp : SoulEatingMagicWeaponImpl)
+ eatSoul()
+ getImp() : SoulEatingMagicWeaponImpl
+ swing()
+ unwield()
+ wield()
}
abstract class SoulEatingMagicWeaponImpl {
+ SoulEatingMagicWeaponImpl()
+ eatSoulImp() {abstract}
}
class Stormbringer {
- LOGGER : Logger {static}
+ Stormbringer()
+ eatSoulImp()
+ swingImp()
+ unwieldImp()
+ wieldImp()
}
}
MagicWeapon --> "-imp" MagicWeaponImpl
BlindingMagicWeapon --|> MagicWeapon
BlindingMagicWeaponImpl --|> MagicWeaponImpl
Excalibur --|> BlindingMagicWeaponImpl
FlyingMagicWeapon --|> MagicWeapon
FlyingMagicWeaponImpl --|> MagicWeaponImpl
Mjollnir --|> FlyingMagicWeaponImpl
SoulEatingMagicWeapon --|> MagicWeapon
SoulEatingMagicWeaponImpl --|> MagicWeaponImpl
Stormbringer --|> SoulEatingMagicWeaponImpl
@enduml

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<artifactId>bridge</artifactId>
<dependencies>

View File

@ -22,40 +22,42 @@
*/
package com.iluwatar.bridge;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* The Bridge pattern can also be thought of as two layers of abstraction. With Bridge, you can
* decouple an abstraction from its implementation so that the two can vary independently.
* Composition over inheritance. The Bridge pattern can also be thought of as two layers of abstraction.
* With Bridge, you can decouple an abstraction from its implementation so that the two can vary independently.
* <p>
* In Bridge pattern both abstraction ({@link MagicWeapon}) and implementation (
* {@link MagicWeaponImpl}) have their own class hierarchies. The interface of the implementations
* In Bridge pattern both abstraction ({@link Weapon}) and implementation (
* {@link Enchantment}) have their own class hierarchies. The interface of the implementations
* can be changed without affecting the clients.
* <p>
* In this example we have two class hierarchies. One of weapons and another one of enchantments. We can easily
* combine any weapon with any enchantment using composition instead of creating deep class hierarchy.
*
*/
public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
/**
* Program entry point
*
* @param args command line args
*/
public static void main(String[] args) {
BlindingMagicWeapon blindingMagicWeapon = new BlindingMagicWeapon(new Excalibur());
blindingMagicWeapon.wield();
blindingMagicWeapon.blind();
blindingMagicWeapon.swing();
blindingMagicWeapon.unwield();
LOGGER.info("The knight receives an enchanted sword.");
Sword enchantedSword = new Sword(new SoulEatingEnchantment());
enchantedSword.wield();
enchantedSword.swing();
enchantedSword.unwield();
FlyingMagicWeapon flyingMagicWeapon = new FlyingMagicWeapon(new Mjollnir());
flyingMagicWeapon.wield();
flyingMagicWeapon.fly();
flyingMagicWeapon.swing();
flyingMagicWeapon.unwield();
SoulEatingMagicWeapon soulEatingMagicWeapon = new SoulEatingMagicWeapon(new Stormbringer());
soulEatingMagicWeapon.wield();
soulEatingMagicWeapon.swing();
soulEatingMagicWeapon.eatSoul();
soulEatingMagicWeapon.unwield();
LOGGER.info("The valkyrie receives an enchanted hammer.");
Hammer hammer = new Hammer(new FlyingEnchantment());
hammer.wield();
hammer.swing();
hammer.unwield();
}
}

View File

@ -24,11 +24,14 @@ package com.iluwatar.bridge;
/**
*
* FlyingMagicWeaponImpl
*
* Enchantment
*
*/
public abstract class FlyingMagicWeaponImpl extends MagicWeaponImpl {
public interface Enchantment {
public abstract void flyImp();
void onActivate();
void apply();
void onDeactivate();
}

View File

@ -27,30 +27,25 @@ import org.slf4j.LoggerFactory;
/**
*
* Excalibur
* FlyingEnchantment
*
*/
public class Excalibur extends BlindingMagicWeaponImpl {
public class FlyingEnchantment implements Enchantment {
private static final Logger LOGGER = LoggerFactory.getLogger(Excalibur.class);
private static final Logger LOGGER = LoggerFactory.getLogger(FlyingEnchantment.class);
@Override
public void wieldImp() {
LOGGER.info("wielding Excalibur");
public void onActivate() {
LOGGER.info("The item begins to glow faintly.");
}
@Override
public void swingImp() {
LOGGER.info("swinging Excalibur");
public void apply() {
LOGGER.info("The item flies and strikes the enemies finally returning to owner's hand.");
}
@Override
public void unwieldImp() {
LOGGER.info("unwielding Excalibur");
}
@Override
public void blindImp() {
LOGGER.info("bright light streams from Excalibur blinding the enemy");
public void onDeactivate() {
LOGGER.info("The item's glow fades.");
}
}

View File

@ -22,38 +22,44 @@
*/
package com.iluwatar.bridge;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* BlindingMagicWeapon
* Hammer
*
*/
public class BlindingMagicWeapon extends MagicWeapon {
public class Hammer implements Weapon {
public BlindingMagicWeapon(BlindingMagicWeaponImpl imp) {
super(imp);
}
private static final Logger LOGGER = LoggerFactory.getLogger(Hammer.class);
@Override
public BlindingMagicWeaponImpl getImp() {
return (BlindingMagicWeaponImpl) imp;
private final Enchantment enchantment;
public Hammer(Enchantment enchantment) {
this.enchantment = enchantment;
}
@Override
public void wield() {
getImp().wieldImp();
LOGGER.info("The hammer is wielded.");
enchantment.onActivate();
}
@Override
public void swing() {
getImp().swingImp();
LOGGER.info("The hammer is swinged.");
enchantment.apply();
}
@Override
public void unwield() {
getImp().unwieldImp();
LOGGER.info("The hammer is unwielded.");
enchantment.onDeactivate();
}
public void blind() {
getImp().blindImp();
@Override
public Enchantment getEnchantment() {
return enchantment;
}
}

View File

@ -27,30 +27,25 @@ import org.slf4j.LoggerFactory;
/**
*
* Stormbringer
* SoulEatingEnchantment
*
*/
public class Stormbringer extends SoulEatingMagicWeaponImpl {
public class SoulEatingEnchantment implements Enchantment {
private static final Logger LOGGER = LoggerFactory.getLogger(Stormbringer.class);
private static final Logger LOGGER = LoggerFactory.getLogger(SoulEatingEnchantment.class);
@Override
public void wieldImp() {
LOGGER.info("wielding Stormbringer");
public void onActivate() {
LOGGER.info("The item spreads bloodlust.");
}
@Override
public void swingImp() {
LOGGER.info("swinging Stormbringer");
public void apply() {
LOGGER.info("The item eats the soul of enemies.");
}
@Override
public void unwieldImp() {
LOGGER.info("unwielding Stormbringer");
}
@Override
public void eatSoulImp() {
LOGGER.info("Stormbringer devours the enemy's soul");
public void onDeactivate() {
LOGGER.info("Bloodlust slowly disappears.");
}
}

View File

@ -22,39 +22,44 @@
*/
package com.iluwatar.bridge;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* SoulEatingMagicWeapon
* Sword
*
*/
public class SoulEatingMagicWeapon extends MagicWeapon {
public class Sword implements Weapon {
public SoulEatingMagicWeapon(SoulEatingMagicWeaponImpl imp) {
super(imp);
}
private static final Logger LOGGER = LoggerFactory.getLogger(Sword.class);
@Override
public SoulEatingMagicWeaponImpl getImp() {
return (SoulEatingMagicWeaponImpl) imp;
private final Enchantment enchantment;
public Sword(Enchantment enchantment) {
this.enchantment = enchantment;
}
@Override
public void wield() {
getImp().wieldImp();
LOGGER.info("The sword is wielded.");
enchantment.onActivate();
}
@Override
public void swing() {
getImp().swingImp();
LOGGER.info("The sword is swinged.");
enchantment.apply();
}
@Override
public void unwield() {
getImp().unwieldImp();
LOGGER.info("The sword is unwielded.");
enchantment.onDeactivate();
}
public void eatSoul() {
getImp().eatSoulImp();
@Override
public Enchantment getEnchantment() {
return enchantment;
}
}

View File

@ -24,11 +24,16 @@ package com.iluwatar.bridge;
/**
*
* BlindingMagicWeaponImpl
*
* Weapon
*
*/
public abstract class BlindingMagicWeaponImpl extends MagicWeaponImpl {
public interface Weapon {
public abstract void blindImp();
void wield();
void swing();
void unwield();
Enchantment getEnchantment();
}

View File

@ -24,32 +24,22 @@ package com.iluwatar.bridge;
import org.junit.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.internal.verification.VerificationModeFactory.times;
/**
* Date: 12/6/15 - 11:26 PM
*
* @author Jeroen Meulemeester
* Tests for hammer
*/
public class FlyingMagicWeaponTest extends MagicWeaponTest {
public class HammerTest extends WeaponTest {
/**
* Invoke all possible actions on the weapon and check if the actions are executed on the actual
* underlying weapon implementation.
*/
@Test
public void testMjollnir() throws Exception {
final Mjollnir mjollnir = spy(new Mjollnir());
final FlyingMagicWeapon flyingMagicWeapon = new FlyingMagicWeapon(mjollnir);
testBasicWeaponActions(flyingMagicWeapon, mjollnir);
flyingMagicWeapon.fly();
verify(mjollnir, times(1)).flyImp();
verifyNoMoreInteractions(mjollnir);
public void testHammer() throws Exception {
final Hammer hammer = spy(new Hammer(mock(FlyingEnchantment.class)));
testBasicWeaponActions(hammer);
}
}

View File

@ -22,38 +22,24 @@
*/
package com.iluwatar.bridge;
import org.junit.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
/**
*
* FlyingMagicWeapon
*
* Tests for sword
*/
public class FlyingMagicWeapon extends MagicWeapon {
public class SwordTest extends WeaponTest {
public FlyingMagicWeapon(FlyingMagicWeaponImpl imp) {
super(imp);
/**
* Invoke all possible actions on the weapon and check if the actions are executed on the actual
* underlying weapon implementation.
*/
@Test
public void testSword() throws Exception {
final Sword sword = spy(new Sword(mock(FlyingEnchantment.class)));
testBasicWeaponActions(sword);
}
public FlyingMagicWeaponImpl getImp() {
return (FlyingMagicWeaponImpl) imp;
}
@Override
public void wield() {
getImp().wieldImp();
}
@Override
public void swing() {
getImp().swingImp();
}
@Override
public void unwield() {
getImp().unwieldImp();
}
public void fly() {
getImp().flyImp();
}
}
}

View File

@ -28,37 +28,32 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.internal.verification.VerificationModeFactory.times;
/**
* Date: 12/6/15 - 11:28 PM
*
* @author Jeroen Meulemeester
* Base class for weapon tests
*/
public abstract class MagicWeaponTest {
public abstract class WeaponTest {
/**
* Invoke the basic actions of the given weapon, and test if the underlying weapon implementation
* Invoke the basic actions of the given weapon, and test if the underlying enchantment implementation
* is invoked
*
* @param weaponImpl The spied weapon implementation where actions are bridged to
* @param weapon The weapon, handled by the app
*/
protected final void testBasicWeaponActions(final MagicWeapon weapon,
final MagicWeaponImpl weaponImpl) {
protected final void testBasicWeaponActions(final Weapon weapon) {
assertNotNull(weapon);
assertNotNull(weaponImpl);
assertNotNull(weapon.getImp());
Enchantment enchantment = weapon.getEnchantment();
assertNotNull(enchantment);
assertNotNull(weapon.getEnchantment());
weapon.swing();
verify(weaponImpl, times(1)).swingImp();
verifyNoMoreInteractions(weaponImpl);
verify(enchantment).apply();
verifyNoMoreInteractions(enchantment);
weapon.wield();
verify(weaponImpl, times(1)).wieldImp();
verifyNoMoreInteractions(weaponImpl);
verify(enchantment).onActivate();
verifyNoMoreInteractions(enchantment);
weapon.unwield();
verify(weaponImpl, times(1)).unwieldImp();
verifyNoMoreInteractions(weaponImpl);
verify(enchantment).onDeactivate();
verifyNoMoreInteractions(enchantment);
}
}

View File

@ -16,7 +16,103 @@ Separate the construction of a complex object from its
representation so that the same construction process can create different
representations.
![alt text](./etc/builder_1.png "Builder")
## Explanation
Real world example
> Imagine a character generator for a role playing game. The easiest option is to let computer create the character for you. But if you want to select the character details like profession, gender, hair color etc. the character generation becomes a step-by-step process that completes when all the selections are ready.
In plain words
> Allows you to create different flavors of an object while avoiding constructor pollution. Useful when there could be several flavors of an object. Or when there are a lot of steps involved in creation of an object.
Wikipedia says
> The builder pattern is an object creation software design pattern with the intentions of finding a solution to the telescoping constructor anti-pattern.
Having said that let me add a bit about what telescoping constructor anti-pattern is. At one point or the other we have all seen a constructor like below:
```
public Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) {
}
```
As you can see the number of constructor parameters can quickly get out of hand and it might become difficult to understand the arrangement of parameters. Plus this parameter list could keep on growing if you would want to add more options in future. This is called telescoping constructor anti-pattern.
**Programmatic Example**
The sane alternative is to use the Builder pattern. First of all we have our hero that we want to create
```
public final class Hero {
private final Profession profession;
private final String name;
private final HairType hairType;
private final HairColor hairColor;
private final Armor armor;
private final Weapon weapon;
private Hero(Builder builder) {
this.profession = builder.profession;
this.name = builder.name;
this.hairColor = builder.hairColor;
this.hairType = builder.hairType;
this.weapon = builder.weapon;
this.armor = builder.armor;
}
}
```
And then we have the builder
```
public static class Builder {
private final Profession profession;
private final String name;
private HairType hairType;
private HairColor hairColor;
private Armor armor;
private Weapon weapon;
public Builder(Profession profession, String name) {
if (profession == null || name == null) {
throw new IllegalArgumentException("profession and name can not be null");
}
this.profession = profession;
this.name = name;
}
public Builder withHairType(HairType hairType) {
this.hairType = hairType;
return this;
}
public Builder withHairColor(HairColor hairColor) {
this.hairColor = hairColor;
return this;
}
public Builder withArmor(Armor armor) {
this.armor = armor;
return this;
}
public Builder withWeapon(Weapon weapon) {
this.weapon = weapon;
return this;
}
public Hero build() {
return new Hero(this);
}
}
```
And then it can be used as:
```
Hero mage = new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();
```
## Applicability
Use the Builder pattern when

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

View File

@ -1,162 +0,0 @@
<?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="false" nesting-relationships="true">
<enumeration id="1" language="java" name="com.iluwatar.builder.HairType" project="builder"
file="/builder/src/main/java/com/iluwatar/builder/HairType.java" binary="false" corner="BOTTOM_RIGHT">
<position height="214" width="189" x="177" y="419"/>
<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>
</enumeration>
<enumeration id="2" language="java" name="com.iluwatar.builder.Weapon" project="builder"
file="/builder/src/main/java/com/iluwatar/builder/Weapon.java" binary="false" corner="BOTTOM_RIGHT">
<position height="196" width="171" x="406" y="419"/>
<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>
</enumeration>
<enumeration id="3" language="java" name="com.iluwatar.builder.HairColor" project="builder"
file="/builder/src/main/java/com/iluwatar/builder/HairColor.java" binary="false" corner="BOTTOM_RIGHT">
<position height="196" width="144" x="-204" y="419"/>
<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>
</enumeration>
<class id="4" language="java" name="com.iluwatar.builder.Hero.Builder" project="builder"
file="/builder/src/main/java/com/iluwatar/builder/Hero.java" binary="false" corner="BOTTOM_RIGHT">
<position height="196" width="234" x="20" y="183"/>
<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>
<enumeration id="5" language="java" name="com.iluwatar.builder.Armor" project="builder"
file="/builder/src/main/java/com/iluwatar/builder/Armor.java" binary="false" corner="BOTTOM_RIGHT">
<position height="196" width="145" x="617" y="419"/>
<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>
</enumeration>
<enumeration id="6" language="java" name="com.iluwatar.builder.Profession" project="builder"
file="/builder/src/main/java/com/iluwatar/builder/Profession.java" binary="false" corner="BOTTOM_RIGHT">
<position height="178" width="157" x="-20" y="419"/>
<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>
</enumeration>
<class id="7" language="java" name="com.iluwatar.builder.Hero" project="builder"
file="/builder/src/main/java/com/iluwatar/builder/Hero.java" binary="false" corner="BOTTOM_RIGHT">
<position height="232" width="178" x="275" y="-89"/>
<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="8">
<bendpoint x="284" y="183"/>
<end type="SOURCE" refId="7" navigable="false">
<attribute id="9" name="hairType"/>
<multiplicity id="10" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="1" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="11">
<end type="SOURCE" refId="4" navigable="false">
<attribute id="12" name="weapon"/>
<multiplicity id="13" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="2" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="14">
<end type="SOURCE" refId="4" navigable="false">
<attribute id="15" name="profession"/>
<multiplicity id="16" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="6" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="17">
<end type="SOURCE" refId="4" navigable="false">
<attribute id="18" name="hairColor"/>
<multiplicity id="19" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="3" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="20">
<bendpoint x="350" y="183"/>
<end type="SOURCE" refId="7" navigable="false">
<attribute id="21" name="weapon"/>
<multiplicity id="22" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="2" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="23">
<end type="SOURCE" refId="4" navigable="false">
<attribute id="24" name="hairType"/>
<multiplicity id="25" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="1" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<nesting id="26">
<end type="SOURCE" refId="7"/>
<end type="TARGET" refId="4"/>
</nesting>
<association id="27">
<end type="SOURCE" refId="4" navigable="false">
<attribute id="28" name="armor"/>
<multiplicity id="29" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="5" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="30">
<bendpoint x="-11" y="183"/>
<end type="SOURCE" refId="7" navigable="false">
<attribute id="31" name="profession"/>
<multiplicity id="32" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="6" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="33">
<bendpoint x="-32" y="183"/>
<end type="SOURCE" refId="7" navigable="false">
<attribute id="34" name="hairColor"/>
<multiplicity id="35" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="3" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="36">
<bendpoint x="455" y="183"/>
<end type="SOURCE" refId="7" navigable="false">
<attribute id="37" name="armor"/>
<multiplicity id="38" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="5" 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>

View File

@ -1,100 +0,0 @@
@startuml
package com.iluwatar.builder {
class App {
- LOGGER : Logger {static}
+ App()
+ main(args : String[]) {static}
}
enum Armor {
+ CHAIN_MAIL {static}
+ CLOTHES {static}
+ LEATHER {static}
+ PLATE_MAIL {static}
- title : String
+ toString() : String
+ valueOf(name : String) : Armor {static}
+ values() : Armor[] {static}
}
enum HairColor {
+ BLACK {static}
+ BLOND {static}
+ BROWN {static}
+ RED {static}
+ WHITE {static}
+ toString() : String
+ valueOf(name : String) : HairColor {static}
+ values() : HairColor[] {static}
}
enum HairType {
+ BALD {static}
+ CURLY {static}
+ LONG_CURLY {static}
+ LONG_STRAIGHT {static}
+ SHORT {static}
- title : String
+ toString() : String
+ valueOf(name : String) : HairType {static}
+ values() : HairType[] {static}
}
class Hero {
- armor : Armor
- hairColor : HairColor
- hairType : HairType
- name : String
- profession : Profession
- weapon : Weapon
- Hero(builder : Builder)
+ getArmor() : Armor
+ getHairColor() : HairColor
+ getHairType() : HairType
+ getName() : String
+ getProfession() : Profession
+ getWeapon() : Weapon
+ toString() : String
}
class Builder {
- armor : Armor
- hairColor : HairColor
- hairType : HairType
- name : String
- profession : Profession
- weapon : Weapon
+ Builder(profession : Profession, name : String)
+ build() : Hero
+ withArmor(armor : Armor) : Builder
+ withHairColor(hairColor : HairColor) : Builder
+ withHairType(hairType : HairType) : Builder
+ withWeapon(weapon : Weapon) : Builder
}
enum Profession {
+ MAGE {static}
+ PRIEST {static}
+ THIEF {static}
+ WARRIOR {static}
+ toString() : String
+ valueOf(name : String) : Profession {static}
+ values() : Profession[] {static}
}
enum Weapon {
+ AXE {static}
+ BOW {static}
+ DAGGER {static}
+ SWORD {static}
+ WARHAMMER {static}
+ toString() : String
+ valueOf(name : String) : Weapon {static}
+ values() : Weapon[] {static}
}
}
Hero --> "-profession" Profession
Builder ..+ Hero
Hero --> "-armor" Armor
Builder --> "-weapon" Weapon
Builder --> "-hairType" HairType
Builder --> "-hairColor" HairColor
Hero --> "-hairColor" HairColor
Builder --> "-profession" Profession
Hero --> "-weapon" Weapon
Hero --> "-hairType" HairType
Builder --> "-armor" Armor
@enduml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<artifactId>builder</artifactId>
<dependencies>

View File

@ -46,8 +46,8 @@ package com.iluwatar.business.delegate {
+ values() : ServiceType[] {static}
}
}
BusinessDelegate --> "-serviceType" ServiceType
BusinessLookup --> "-ejbService" EjbService
BusinessDelegate --> "-serviceType" ServiceType
Client --> "-businessDelegate" BusinessDelegate
BusinessDelegate --> "-businessService" BusinessService
BusinessDelegate --> "-lookupService" BusinessLookup

View File

@ -30,7 +30,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<artifactId>business-delegate</artifactId>
<dependencies>

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<artifactId>caching</artifactId>
<dependencies>

View File

@ -167,7 +167,7 @@ public class LruCache {
* Returns cache data in list form.
*/
public List<UserAccount> getCacheDataInListForm() {
ArrayList<UserAccount> listOfCacheData = new ArrayList<>();
List<UserAccount> listOfCacheData = new ArrayList<>();
Node temp = head;
while (temp != null) {
listOfCacheData.add(temp.userAccount);

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<artifactId>callback</artifactId>
<dependencies>

View File

@ -16,7 +16,131 @@ Avoid coupling the sender of a request to its receiver by giving
more than one object a chance to handle the request. Chain the receiving
objects and pass the request along the chain until an object handles it.
![alt text](./etc/chain_1.png "Chain of Responsibility")
## Explanation
Real world example
> The Orc King gives loud orders to his army. The closest one to react is the commander, then officer and then soldier. The commander, officer and soldier here form a chain of responsibility.
In plain words
> It helps building a chain of objects. Request enters from one end and keeps going from object to object till it finds the suitable handler.
Wikipedia says
> In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain.
**Programmatic Example**
Translating our example with orcs from above. First we have the request class
```
public class Request {
private final RequestType requestType;
private final String requestDescription;
private boolean handled;
public Request(final RequestType requestType, final String requestDescription) {
this.requestType = Objects.requireNonNull(requestType);
this.requestDescription = Objects.requireNonNull(requestDescription);
}
public String getRequestDescription() { return requestDescription; }
public RequestType getRequestType() { return requestType; }
public void markHandled() { this.handled = true; }
public boolean isHandled() { return this.handled; }
@Override
public String toString() { return getRequestDescription(); }
}
public enum RequestType {
DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX
}
```
Then the request handler hierarchy
```
public abstract class RequestHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(RequestHandler.class);
private RequestHandler next;
public RequestHandler(RequestHandler next) {
this.next = next;
}
public void handleRequest(Request req) {
if (next != null) {
next.handleRequest(req);
}
}
protected void printHandling(Request req) {
LOGGER.info("{} handling request \"{}\"", this, req);
}
@Override
public abstract String toString();
}
public class OrcCommander extends RequestHandler {
public OrcCommander(RequestHandler handler) {
super(handler);
}
@Override
public void handleRequest(Request req) {
if (req.getRequestType().equals(RequestType.DEFEND_CASTLE)) {
printHandling(req);
req.markHandled();
} else {
super.handleRequest(req);
}
}
@Override
public String toString() {
return "Orc commander";
}
}
// OrcOfficer and OrcSoldier are defined similarly as OrcCommander
```
Then we have the Orc King who gives the orders and forms the chain
```
public class OrcKing {
RequestHandler chain;
public OrcKing() {
buildChain();
}
private void buildChain() {
chain = new OrcCommander(new OrcOfficer(new OrcSoldier(null)));
}
public void makeRequest(Request req) {
chain.handleRequest(req);
}
}
```
Then it is used as follows
```
OrcKing king = new OrcKing();
king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); // Orc commander handling request "defend castle"
king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner")); // Orc officer handling request "torture prisoner"
king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); // Orc soldier handling request "collect tax"
```
## Applicability
Use Chain of Responsibility when

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

View File

@ -1,109 +0,0 @@
<?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="false" nesting-relationships="true">
<class id="1" language="java" name="com.iluwatar.chain.Request" project="chain"
file="/chain/src/main/java/com/iluwatar/chain/Request.java" binary="false" corner="BOTTOM_RIGHT">
<position height="196" width="228" x="168" y="182"/>
<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.chain.OrcOfficer" project="chain"
file="/chain/src/main/java/com/iluwatar/chain/OrcOfficer.java" binary="false" corner="BOTTOM_RIGHT">
<position height="124" width="194" x="168" y="609"/>
<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.chain.OrcCommander" project="chain"
file="/chain/src/main/java/com/iluwatar/chain/OrcCommander.java" binary="false" corner="BOTTOM_RIGHT">
<position height="124" width="217" x="402" y="609"/>
<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="4" language="java" name="com.iluwatar.chain.RequestHandler" project="chain"
file="/chain/src/main/java/com/iluwatar/chain/RequestHandler.java" binary="false" corner="BOTTOM_RIGHT">
<position height="141" width="218" x="451" y="418"/>
<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="5" language="java" name="com.iluwatar.chain.OrcSoldier" project="chain"
file="/chain/src/main/java/com/iluwatar/chain/OrcSoldier.java" binary="false" corner="BOTTOM_RIGHT">
<position height="124" width="194" x="659" y="609"/>
<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="6" language="java" name="com.iluwatar.chain.OrcKing" project="chain"
file="/chain/src/main/java/com/iluwatar/chain/OrcKing.java" binary="false" corner="BOTTOM_RIGHT">
<position height="124" width="188" x="451" y="182"/>
<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>
<enumeration id="7" language="java" name="com.iluwatar.chain.RequestType" project="chain"
file="/chain/src/main/java/com/iluwatar/chain/RequestType.java" binary="false" corner="BOTTOM_RIGHT">
<position height="142" width="243" x="168" y="418"/>
<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>
</enumeration>
<association id="8">
<end type="SOURCE" refId="6" navigable="false">
<attribute id="9" name="chain"/>
<multiplicity id="10" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="4" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="11">
<end type="SOURCE" refId="4" navigable="false">
<attribute id="12" name="next"/>
<multiplicity id="13" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="4" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<generalization id="14">
<end type="SOURCE" refId="5"/>
<end type="TARGET" refId="4"/>
</generalization>
<association id="15">
<end type="SOURCE" refId="1" navigable="false">
<attribute id="16" name="requestType"/>
<multiplicity id="17" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="7" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<generalization id="18">
<end type="SOURCE" refId="2"/>
<end type="TARGET" refId="4"/>
</generalization>
<generalization id="19">
<end type="SOURCE" refId="3"/>
<end type="TARGET" refId="4"/>
</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>

View File

@ -1,61 +0,0 @@
@startuml
package com.iluwatar.chain {
class App {
+ App()
+ main(args : String[]) {static}
}
class OrcCommander {
+ OrcCommander(handler : RequestHandler)
+ handleRequest(req : Request)
+ toString() : String
}
class OrcKing {
~ chain : RequestHandler
+ OrcKing()
- buildChain()
+ makeRequest(req : Request)
}
class OrcOfficer {
+ OrcOfficer(handler : RequestHandler)
+ handleRequest(req : Request)
+ toString() : String
}
class OrcSoldier {
+ OrcSoldier(handler : RequestHandler)
+ handleRequest(req : Request)
+ toString() : String
}
class Request {
- handled : boolean
- requestDescription : String
- requestType : RequestType
+ Request(requestType : RequestType, requestDescription : String)
+ getRequestDescription() : String
+ getRequestType() : RequestType
+ isHandled() : boolean
+ markHandled()
+ toString() : String
}
abstract class RequestHandler {
- LOGGER : Logger {static}
- next : RequestHandler
+ RequestHandler(next : RequestHandler)
+ handleRequest(req : Request)
# printHandling(req : Request)
+ toString() : String {abstract}
}
enum RequestType {
+ COLLECT_TAX {static}
+ DEFEND_CASTLE {static}
+ TORTURE_PRISONER {static}
+ valueOf(name : String) : RequestType {static}
+ values() : RequestType[] {static}
}
}
RequestHandler --> "-next" RequestHandler
OrcKing --> "-chain" RequestHandler
Request --> "-requestType" RequestType
OrcCommander --|> RequestHandler
OrcOfficer --|> RequestHandler
OrcSoldier --|> RequestHandler
@enduml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<artifactId>chain</artifactId>
<dependencies>

View File

@ -32,10 +32,10 @@
Source = https://github.com/checkstyle/checkstyle/tree/master/src/main/resources
Checkstyle configurartion that checks the Google coding conventions from:
- Google Java Style
https://google-styleguide.googlecode.com/svn-history/r130/trunk/javaguide.html
Checkstyle is very configurable. Be sure to read the documentation at
http://checkstyle.sf.net (or in your downloaded distribution).
@ -44,12 +44,12 @@
To completely disable a check, just comment it out or delete it from the file.
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
-->
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="fileExtensions" value="java, xml, properties"/>
<property name="severity" value="error"/>
@ -77,7 +77,6 @@
<property name="max" value="120"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="AvoidStarImport"/>
<module name="OneTopLevelClass"/>
<module name="NoLineWrap"/>
<module name="EmptyBlock">
@ -86,9 +85,7 @@
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces"/>
<module name="LeftCurly">
<property name="maxLineLength" value="120"/>
</module>
<module name="LeftCurly"/>
<module name="RightCurly"/>
<module name="RightCurly">
<property name="option" value="alone"/>
@ -120,7 +117,7 @@
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<!-- Checks for Naming Conventions. -->
<!-- See http://checkstyle.sf.net/config_naming.html -->
<module name="ConstantName"/>
@ -185,6 +182,10 @@
<property name="allowedAnnotations" value="Override, Test, Before, After, Parameters, Given, When, BeforeClass, AfterClass, Parameterized"/>
<property name="allowThrowsTagsForSubclasses" value="true"/>
</module>
<module name="JavadocType">
<property name="scope" value="public"/>
<property name="allowUnknownTags" value="true"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<artifactId>command</artifactId>
<dependencies>

View File

@ -29,7 +29,7 @@ package com.iluwatar.command;
*/
public enum Size {
SMALL("small"), NORMAL("normal"), LARGE("large"), UNDEFINED("");
SMALL("small"), NORMAL("normal");
private String title;

View File

@ -29,7 +29,7 @@ package com.iluwatar.command;
*/
public enum Visibility {
VISIBLE("visible"), INVISIBLE("invisible"), UNDEFINED("");
VISIBLE("visible"), INVISIBLE("invisible");
private String title;

View File

@ -40,7 +40,9 @@ public class Wizard {
private Deque<Command> undoStack = new LinkedList<>();
private Deque<Command> redoStack = new LinkedList<>();
public Wizard() {}
public Wizard() {
// comment to ignore sonar issue: LEVEL critical
}
/**
* Cast spell

View File

@ -16,7 +16,119 @@ Compose objects into tree structures to represent part-whole
hierarchies. Composite lets clients treat individual objects and compositions
of objects uniformly.
![alt text](./etc/composite_1.png "Composite")
## Explanation
Real world example
> Every sentence is composed of words which are in turn composed of characters. Each of these objects is printable and they can have something printed before or after them like sentence always ends with full stop and word always has space before it
In plain words
> Composite pattern lets clients treat the individual objects in a uniform manner.
Wikipedia says
> In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes that a group of objects is to be treated in the same way as a single instance of an object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.
**Programmatic Example**
Taking our sentence example from above. Here we have the base class and different printable types
```
public abstract class LetterComposite {
private List<LetterComposite> children = new ArrayList<>();
public void add(LetterComposite letter) {
children.add(letter);
}
public int count() {
return children.size();
}
protected void printThisBefore() {}
protected void printThisAfter() {}
public void print() {
printThisBefore();
for (LetterComposite letter : children) {
letter.print();
}
printThisAfter();
}
}
public class Letter extends LetterComposite {
private char c;
public Letter(char c) {
this.c = c;
}
@Override
protected void printThisBefore() {
System.out.print(c);
}
}
public class Word extends LetterComposite {
public Word(List<Letter> letters) {
for (Letter l : letters) {
this.add(l);
}
}
@Override
protected void printThisBefore() {
System.out.print(" ");
}
}
public class Sentence extends LetterComposite {
public Sentence(List<Word> words) {
for (Word w : words) {
this.add(w);
}
}
@Override
protected void printThisAfter() {
System.out.print(".");
}
}
```
Then we have a messenger to carry messages
```
public class Messenger {
LetterComposite messageFromOrcs() {
List<Word> words = new ArrayList<>();
words.add(new Word(Arrays.asList(new Letter('W'), new Letter('h'), new Letter('e'), new Letter('r'), new Letter('e'))));
words.add(new Word(Arrays.asList(new Letter('t'), new Letter('h'), new Letter('e'), new Letter('r'), new Letter('e'))));
words.add(new Word(Arrays.asList(new Letter('i'), new Letter('s'))));
words.add(new Word(Arrays.asList(new Letter('a'))));
words.add(new Word(Arrays.asList(new Letter('w'), new Letter('h'), new Letter('i'), new Letter('p'))));
words.add(new Word(Arrays.asList(new Letter('t'), new Letter('h'), new Letter('e'), new Letter('r'), new Letter('e'))));
words.add(new Word(Arrays.asList(new Letter('i'), new Letter('s'))));
words.add(new Word(Arrays.asList(new Letter('a'))));
words.add(new Word(Arrays.asList(new Letter('w'), new Letter('a'), new Letter('y'))));
return new Sentence(words);
}
LetterComposite messageFromElves() {
List<Word> words = new ArrayList<>();
words.add(new Word(Arrays.asList(new Letter('M'), new Letter('u'), new Letter('c'), new Letter('h'))));
words.add(new Word(Arrays.asList(new Letter('w'), new Letter('i'), new Letter('n'), new Letter('d'))));
words.add(new Word(Arrays.asList(new Letter('p'), new Letter('o'), new Letter('u'), new Letter('r'), new Letter('s'))));
words.add(new Word(Arrays.asList(new Letter('f'), new Letter('r'), new Letter('o'), new Letter('m'))));
words.add(new Word(Arrays.asList(new Letter('y'), new Letter('o'), new Letter('u'), new Letter('r'))));
words.add(new Word(Arrays.asList(new Letter('m'), new Letter('o'), new Letter('u'), new Letter('t'), new Letter('h'))));
return new Sentence(words);
}
}
```
And then it can be used as
```
LetterComposite orcMessage = new Messenger().messageFromOrcs();
orcMessage.print(); // Where there is a whip there is a way.
LetterComposite elfMessage = new Messenger().messageFromElves();
elfMessage.print(); // Much wind pours from your mouth.
```
## Applicability
Use the Composite pattern when

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,75 +0,0 @@
<?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="false" nesting-relationships="true">
<class id="1" language="java" name="com.iluwatar.composite.Messenger" project="composite"
file="/composite/src/main/java/com/iluwatar/composite/Messenger.java" binary="false" corner="BOTTOM_RIGHT">
<position height="124" width="247" x="118" y="180"/>
<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.composite.Sentence" project="composite"
file="/composite/src/main/java/com/iluwatar/composite/Sentence.java" binary="false" corner="BOTTOM_RIGHT">
<position height="124" width="157" x="118" y="407"/>
<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.composite.LetterComposite" project="composite"
file="/composite/src/main/java/com/iluwatar/composite/LetterComposite.java" binary="false" corner="BOTTOM_RIGHT">
<position height="177" width="176" x="405" y="180"/>
<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="4" language="java" name="com.iluwatar.composite.Letter" project="composite"
file="/composite/src/main/java/com/iluwatar/composite/Letter.java" binary="false" corner="BOTTOM_RIGHT">
<position height="142" width="146" x="315" y="407"/>
<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="5" language="java" name="com.iluwatar.composite.Word" project="composite"
file="/composite/src/main/java/com/iluwatar/composite/Word.java" binary="false" corner="BOTTOM_RIGHT">
<position height="124" width="146" x="501" y="407"/>
<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>
<generalization id="6">
<end type="SOURCE" refId="2"/>
<end type="TARGET" refId="3"/>
</generalization>
<generalization id="7">
<end type="SOURCE" refId="4"/>
<end type="TARGET" refId="3"/>
</generalization>
<association id="8">
<end type="SOURCE" refId="3" navigable="false">
<attribute id="9" name="children"/>
<multiplicity id="10" minimum="0" maximum="2147483647"/>
</end>
<end type="TARGET" refId="3" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<generalization id="11">
<end type="SOURCE" refId="5"/>
<end type="TARGET" refId="3"/>
</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>

View File

@ -1,43 +0,0 @@
@startuml
package com.iluwatar.composite {
class App {
- LOGGER : Logger {static}
+ App()
+ main(args : String[]) {static}
}
class Letter {
- c : char
+ Letter(c : char)
# printThisAfter()
# printThisBefore()
}
abstract class LetterComposite {
- children : List<LetterComposite>
+ LetterComposite()
+ add(letter : LetterComposite)
+ count() : int
+ print()
# printThisAfter() {abstract}
# printThisBefore() {abstract}
}
class Messenger {
+ Messenger()
~ messageFromElves() : LetterComposite
~ messageFromOrcs() : LetterComposite
}
class Sentence {
+ Sentence(words : List<Word>)
# printThisAfter()
# printThisBefore()
}
class Word {
+ Word(letters : List<Letter>)
# printThisAfter()
# printThisBefore()
}
}
LetterComposite --> "-children" LetterComposite
Letter --|> LetterComposite
Sentence --|> LetterComposite
Word --|> LetterComposite
@enduml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.14.0</version>
<version>1.17.0</version>
</parent>
<artifactId>composite</artifactId>
<dependencies>

View File

@ -51,9 +51,7 @@ public class App {
LetterComposite orcMessage = new Messenger().messageFromOrcs();
orcMessage.print();
LOGGER.info("\n");
LOGGER.info("Message from the elves: ");
LOGGER.info("\nMessage from the elves: ");
LetterComposite elfMessage = new Messenger().messageFromElves();
elfMessage.print();

View File

@ -39,9 +39,4 @@ public class Letter extends LetterComposite {
protected void printThisBefore() {
System.out.print(c);
}
@Override
protected void printThisAfter() {
// nop
}
}

View File

@ -42,9 +42,9 @@ public abstract class LetterComposite {
return children.size();
}
protected abstract void printThisBefore();
protected void printThisBefore() {}
protected abstract void printThisAfter();
protected void printThisAfter() {}
/**
* Print

View File

@ -40,11 +40,6 @@ public class Sentence extends LetterComposite {
}
}
@Override
protected void printThisBefore() {
// nop
}
@Override
protected void printThisAfter() {
System.out.print(".");

Some files were not shown because too many files have changed in this diff Show More