├── .gitattributes ├── .gitignore ├── .java-version ├── LICENSE ├── README.adoc ├── abstract-document ├── README.md ├── build.gradle.kts ├── doc │ ├── abstract-document.png │ └── abstract-document.ucls └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── abstractdocument │ │ ├── AbstractDocument.kt │ │ ├── Document.kt │ │ └── domain │ │ ├── Car.kt │ │ ├── HasModel.kt │ │ ├── HasParts.kt │ │ ├── HasPrice.kt │ │ ├── HasType.kt │ │ ├── Part.kt │ │ └── Property.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── abstractdocument │ │ ├── AbstractDocumentTest.kt │ │ └── DocumentTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── abstract-factory ├── README.md ├── build.gradle.kts ├── doc │ ├── diagram1.png │ ├── diagram2.png │ └── presentation.html └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── abstractfactory │ │ ├── Army.kt │ │ ├── Castle.kt │ │ ├── FactoryMaker.kt │ │ ├── King.kt │ │ ├── KingdomFactory.kt │ │ ├── elf │ │ ├── ElfArmy.kt │ │ ├── ElfCastle.kt │ │ ├── ElfKing.kt │ │ └── ElfKingdomFactory.kt │ │ └── orc │ │ ├── OrcArmy.kt │ │ ├── OrcCastle.kt │ │ ├── OrcKing.kt │ │ └── OrcKingdomFactory.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── abstractfactory │ │ └── AbstractFactoryTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── acycle-visitor ├── README.md ├── build.gradle.kts ├── etc │ ├── Acyclic Visitor.ucls │ └── acyclic-visitor.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── acyclicvisitor │ │ ├── AllModemVisitor.kt │ │ ├── ConfigureForDosVisitor.kt │ │ ├── ConfigureForUnixVisitor.kt │ │ ├── Hayes.kt │ │ ├── HayesVisitor.kt │ │ ├── Modem.kt │ │ ├── ModemVisitor.kt │ │ ├── Zoom.kt │ │ └── ZoomVisitor.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── acyclicvisitor │ │ ├── ConfigureForDosVisitorTest.kt │ │ ├── ConfigureForUnixVisitorTest.kt │ │ ├── HayesTest.kt │ │ └── ZoomTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── adaptor ├── README.md ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── adapter │ │ ├── App.kt │ │ ├── Captain.kt │ │ ├── FishingBoat.kt │ │ ├── FishingBoatAdapter.kt │ │ └── RowingBoat.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── adapter │ │ └── AdapterPatternTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── ambassador ├── README.md ├── build.gradle.kts ├── etc │ ├── ambassador.urm.png │ └── ambassador.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── ambassador │ │ ├── Client.kt │ │ ├── RemoteService.kt │ │ ├── RemoteServiceInterface.kt │ │ ├── ServiceAmbassador.kt │ │ └── util │ │ └── RandomProvider.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── ambassador │ │ ├── ClientTest.kt │ │ ├── RemoveServiceTest.kt │ │ └── ServiceAmbassadorTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── api-gateway ├── README.md ├── api-gateway-service │ ├── build.gradle.kts │ └── etc │ │ └── api-gateway-service.urm.puml ├── etc │ ├── api-gateway.png │ ├── api-gateway.ucls │ └── api-gateway.urm.puml ├── image-microservice │ ├── build.gradle.kts │ └── etc │ │ ├── image-microservice.png │ │ ├── image-microservice.ucls │ │ └── image-microservice.urm.puml └── price-microservice │ ├── build.gradle.kts │ └── etc │ ├── price-microservice.png │ ├── price-microservice.ucls │ └── price-microservice.urm.puml ├── async-method-invocation ├── README.md ├── build.gradle.kts ├── etc │ ├── async-method-invocation.png │ └── async-method-invocation.ucls └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── methodinvocation │ │ ├── async │ │ ├── AsyncCallback.kt │ │ ├── AsyncExecutor.kt │ │ ├── AsyncResult.kt │ │ └── ThreadAsyncExecutor.kt │ │ ├── coroutines │ │ └── CoroutineExecutor.kt │ │ └── future │ │ └── CompletableFutureExecutor.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── methodinvocation │ │ ├── asyc │ │ └── ThreadAsyncExecutorTest.kt │ │ └── coroutines │ │ └── CoroutineExecutorTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── balking ├── README.md ├── build.gradle.kts ├── doc │ └── balking.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── balking │ │ ├── DelayProvider.kt │ │ ├── WashingMachine.kt │ │ └── WashingMachineState.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── balking │ │ └── WashingMachineTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── bridge ├── README.md └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── bridge │ │ ├── App.kt │ │ ├── Enchantment.kt │ │ ├── Weapon.kt │ │ ├── enchantments │ │ ├── FlyingEnchantment.kt │ │ └── SoulEatingEnchantment.kt │ │ └── weapons │ │ ├── Hammer.kt │ │ └── Sword.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── bridge │ │ ├── AbstractWeaponTest.kt │ │ ├── AppTest.kt │ │ ├── HammerTest.kt │ │ └── SwordTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── build.gradle.kts ├── buildSrc ├── build.gradle.kts ├── build │ └── pluginUnderTestMetadata │ │ └── plugin-under-test-metadata.properties ├── gradle.properties └── src │ └── main │ └── kotlin │ └── Libraries.kt ├── builder ├── README.md ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── builder │ │ ├── Enums.kt │ │ ├── Hero.kt │ │ └── KotlinHero.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── builder │ │ ├── HeroTest.kt │ │ └── KotlinHeroTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── business-delegate ├── README.md ├── build.gradle.kts ├── doc │ └── business-delegate.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── businessdelegate │ │ ├── BusinessDelegate.kt │ │ ├── BusinessLookup.kt │ │ ├── Client.kt │ │ ├── ServiceType.kt │ │ └── services │ │ ├── BusinessService.kt │ │ ├── EjbService.kt │ │ └── JmsService.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── businessdelegate │ │ └── BusinessDelegateTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── caching ├── README.md ├── build.gradle.kts ├── etc │ ├── caching.png │ └── caching.ucls └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── caching │ │ ├── AppManager.kt │ │ ├── CacheStore.kt │ │ ├── CachingConstants.kt │ │ ├── CachingPolicy.kt │ │ ├── DbManager.kt │ │ └── UserAccount.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── caching │ │ └── CachingTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── callback ├── README.md ├── build.gradle.kts ├── doc │ └── callback.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── callback │ │ ├── Callback.kt │ │ └── Task.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── callback │ │ └── CallbackTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── chain ├── README.md ├── build.gradle.kts ├── etc │ ├── chain.urm.png │ └── chain.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── chain │ │ ├── OrcCommander.kt │ │ ├── OrcKing.kt │ │ ├── OrcOfficer.kt │ │ ├── OrcSoldier.kt │ │ ├── Request.kt │ │ ├── RequestHandler.kt │ │ └── RequestType.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── chain │ │ └── ChainTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── collection-pipeline ├── README.md ├── build.gradle.kts ├── etc │ ├── collection-pipeline.png │ └── collection-pipeline.ucls └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── collectionpipeline │ │ ├── Car.kt │ │ ├── CarFactory.kt │ │ ├── Category.kt │ │ ├── JavaFunctionalProgramming.kt │ │ ├── KotlinFunctionalProgramming.kt │ │ └── Person.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── collectionpipeline │ │ └── CollectionPipelineTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── command ├── README.md ├── build.gradle.kts ├── etc │ ├── command.png │ ├── command.ucls │ ├── diagram.png │ └── presentation.html └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── command │ │ ├── Command.kt │ │ ├── Goblin.kt │ │ ├── Size.kt │ │ ├── Target.kt │ │ ├── Visibility.kt │ │ ├── Wizard.kt │ │ └── commands │ │ ├── InvisibilitySpell.kt │ │ └── ShrinkSpell.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── command │ │ └── CommandTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── composite ├── README.adoc ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── composite │ │ ├── LetterComposite.kt │ │ └── Messenger.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── composite │ │ └── MessengerTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── converter ├── README.md ├── build.gradle.kts ├── doc │ └── converter.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── converter │ │ ├── Converter.kt │ │ ├── DomainConverter.kt │ │ ├── User.kt │ │ ├── UserConvertExtensions.kt │ │ ├── UserConverter.kt │ │ └── UserDto.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── converter │ │ └── UserConverterTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── cqrs ├── README.md ├── build.gradle.kts ├── etc │ ├── cqrs.png │ └── cqrs.ucls └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── cqrs │ │ ├── commands │ │ ├── CommandService.kt │ │ └── CommandServiceImpl.kt │ │ ├── domain │ │ ├── model │ │ │ ├── Author.kt │ │ │ ├── Book.kt │ │ │ └── LongEntity.kt │ │ └── repository │ │ │ ├── AuthorRepository.kt │ │ │ └── BookRepository.kt │ │ ├── dto │ │ ├── AuthorDto.kt │ │ └── BookDto.kt │ │ └── queries │ │ ├── QueryService.kt │ │ └── QueryServiceImpl.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── cqrs │ │ ├── CqrsIntegrationTest.kt │ │ └── CqrsJpaConfiguration.kt │ └── resources │ ├── application.properties │ ├── junit-platform.properties │ └── logback-test.xml ├── data-bus ├── README.md ├── build.gradle.kts ├── etc │ └── data-bus.urm.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── databus │ │ ├── AbstractDataType.kt │ │ ├── DataBus.kt │ │ ├── DataType.kt │ │ ├── Member.kt │ │ ├── data │ │ ├── MessageData.kt │ │ ├── StartingData.kt │ │ └── StoppingData.kt │ │ └── members │ │ ├── MessageCollectorMember.kt │ │ └── StatusMember.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── databus │ │ ├── DataBusTest.kt │ │ └── members │ │ ├── MessageCollectorMemberTest.kt │ │ └── StatusMemberTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── data-locality ├── README.md ├── build.gradle.kts ├── etc │ ├── data-locality.urm.png │ └── data-locality.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── datalocality │ │ ├── App.kt │ │ └── game │ │ ├── Components.kt │ │ ├── GameEntity.kt │ │ └── Managers.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── datalocality │ │ └── GameEntityTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── data-mapper ├── README.md ├── build.gradle.kts ├── etc │ ├── data-mapper.png │ └── data-mapper.ucls └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── datamapper │ │ ├── DataMapperException.kt │ │ ├── Student.kt │ │ ├── StudentDataMapper.kt │ │ └── StudentDataMapperImpl.kt │ └── test │ └── kotlin │ └── io │ └── kommons │ └── designpatterns │ └── datamapper │ ├── StudentDataMapperTest.kt │ └── StudentTest.kt ├── data-transfer-object ├── README.md ├── build.gradle.kts ├── etc │ ├── data-transfer-object.ucls │ └── data-transfer-object.urm.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── dto │ │ ├── CustomerDto.kt │ │ └── CustomerResource.kt │ └── test │ └── kotlin │ └── io │ └── kommons │ └── designpatterns │ └── dto │ └── CustomerResourceTest.kt ├── decorator ├── README.md ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── decorator │ │ ├── ClubbedTroll.kt │ │ ├── SimpleTroll.kt │ │ └── Troll.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── decorator │ │ ├── ClubbedTrollTest.kt │ │ └── SimpleTrollTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── delegation ├── README.md ├── build.gradle.kts ├── doc │ └── delegation.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── delegation │ │ ├── Printer.kt │ │ ├── PrinterController.kt │ │ └── printers │ │ ├── CanonPrinter.kt │ │ ├── EpsonPrinter.kt │ │ └── HpPrinter.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── delegation │ │ └── DelegateTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── dirty-flag ├── README.md ├── build.gradle.kts ├── etc │ ├── dirty-flag.png │ └── dirty-flag.ucls └── src │ ├── main │ ├── kotlin │ │ └── io │ │ │ └── kommons │ │ │ └── designpatterns │ │ │ └── dirty │ │ │ └── flag │ │ │ ├── App.kt │ │ │ ├── DataFetcher.kt │ │ │ └── World.kt │ └── resources │ │ └── world.txt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── dirty │ │ └── flag │ │ ├── AppTest.kt │ │ └── DirtyFlagTest.kt │ └── resources │ ├── junit-platform.properties │ ├── logback-test.xml │ └── world.txt ├── double-buffer ├── README.md ├── build.gradle.kts ├── etc │ ├── double-buffer.urm.png │ └── double-buffer.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── doublebuffer │ │ ├── App.kt │ │ ├── Buffer.kt │ │ ├── Pixel.kt │ │ └── Scene.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── doublebuffer │ │ ├── AppTest.kt │ │ ├── FrameBufferTest.kt │ │ └── SceneTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── event-aggregator ├── README.md ├── build.gradle.kts ├── etc │ ├── classes.png │ └── classes.ucls └── src │ ├── main │ ├── kotlin │ │ └── io │ │ │ └── kommons │ │ │ └── designpatterns │ │ │ └── event │ │ │ └── aggregator │ │ │ ├── App.kt │ │ │ ├── Event.kt │ │ │ ├── EventEmitter.kt │ │ │ ├── EventObserver.kt │ │ │ ├── KingsHand.kt │ │ │ ├── Weekday.kt │ │ │ ├── emitters │ │ │ ├── LoadVarys.kt │ │ │ ├── LordBaelish.kt │ │ │ └── Scout.kt │ │ │ └── observers │ │ │ └── KingJoffrey.kt │ └── resources │ │ └── logback.xml │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── event │ │ └── aggregator │ │ ├── AppTest.kt │ │ ├── EventTest.kt │ │ ├── KingsHandTest.kt │ │ ├── WeekdayTest.kt │ │ ├── emitters │ │ ├── AbstractEventEmitterTest.kt │ │ ├── LordBaelishTest.kt │ │ ├── LordVarysTest.kt │ │ └── ScoutTest.kt │ │ └── observers │ │ └── KingJoffreyTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── event-asynchronous ├── README.md ├── build.gradle.kts ├── etc │ ├── event-asynchronous.png │ └── event-asynchronous.ucls └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── event │ │ ├── ThreadCompleteListener.kt │ │ ├── async │ │ ├── Event.kt │ │ ├── EventManager.kt │ │ └── IEvent.kt │ │ ├── coroutines │ │ ├── CoEvent.kt │ │ ├── CoEventManager.kt │ │ └── ICoEvent.kt │ │ └── exception │ │ ├── EventDoesNotExistException.kt │ │ ├── InvalidOperationException.kt │ │ ├── LongRunningEventException.kt │ │ └── MaxNumOfEventsAllowedException.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── event │ │ ├── async │ │ └── EventAsynchronousTest.kt │ │ └── coroutines │ │ └── EventCoroutinesTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── event-driven-architecture ├── README.md ├── build.gradle.kts ├── etc │ ├── eda.png │ ├── eda.ucls │ └── event-driven-architecture.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── eda │ │ ├── App.kt │ │ ├── Events.kt │ │ ├── Handlers.kt │ │ ├── User.kt │ │ └── framework │ │ ├── Event.kt │ │ ├── EventDispatcher.kt │ │ └── Handler.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── eda │ │ ├── AppTest.kt │ │ ├── EventTest.kt │ │ └── framework │ │ └── EventDispatcherTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── event-queue ├── README.md ├── etc │ ├── Bass-Drum-1.aif │ ├── Bass-Drum-1.wav │ ├── Closed-Hi-Hat-1.aif │ ├── Closed-Hi-Hat-1.wav │ ├── event-queue.urm.puml │ ├── model.png │ └── model.ucls └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── eventqueue │ │ ├── Audio.kt │ │ └── PlayMessage.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── eventqueue │ │ └── AudioTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── event-sourcing ├── Journal.json ├── README.md ├── build.gradle.kts ├── etc │ ├── event-sourcing.png │ └── event-sourcing.ucls └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── eventsourcing │ │ ├── App.kt │ │ ├── domain │ │ └── Account.kt │ │ ├── event │ │ ├── AbstractDomainEvent.kt │ │ ├── AccountCreateEvent.kt │ │ ├── DomainEvent.kt │ │ ├── MoneyDepositEvent.kt │ │ └── MoneyTransferEvent.kt │ │ ├── processor │ │ ├── DomainEventProcessor.kt │ │ └── JsonFileJournal.kt │ │ └── state │ │ └── AccountAggregate.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── eventsourcing │ │ └── IntegrationTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── execute-around ├── README.md ├── build.gradle.kts ├── etc │ ├── execute-around.png │ └── execute-around.ucls └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── execute │ │ └── around │ │ ├── App.kt │ │ ├── FileWriterAction.kt │ │ ├── SimpleFileWriter.kt │ │ └── WithFileWriter.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── execute │ │ └── around │ │ ├── SimpleFileWriterTest.kt │ │ └── WithFileWriterTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── extension-objects ├── README.md ├── build.gradle.kts ├── etc │ ├── extension-objects.urm.puml │ ├── extension_obj.png │ └── extension_obj.ucls └── src │ ├── main │ ├── kotlin │ │ └── io │ │ │ └── kommons │ │ │ └── designpatterns │ │ │ └── extensionobjects │ │ │ ├── App.kt │ │ │ ├── Concretes.kt │ │ │ ├── Extensions.kt │ │ │ ├── KotlinExtensions.kt │ │ │ └── Units.kt │ └── resources │ │ └── logback.xml │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── extensionobjects │ │ ├── AppTest.kt │ │ ├── ConcreteExtensionTest.kt │ │ ├── KotlinExtensionTest.kt │ │ └── UnitTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── facade ├── README.md ├── etc │ ├── facade.urm.png │ └── facade.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── facade │ │ ├── App.kt │ │ ├── DwarvenCartOperator.kt │ │ ├── DwarvenGoldDigger.kt │ │ ├── DwarvenGoldmineFacade.kt │ │ ├── DwarvenMineWorker.kt │ │ └── DwarvenTunnelDigger.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── facade │ │ ├── AppTest.kt │ │ └── DwarvenGoldmineFacadeTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── factory-kit ├── README.md ├── etc │ ├── factory-kit.png │ ├── factory-kit.ucls │ └── factory-kit.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── factorykit │ │ ├── App.kt │ │ ├── Builder.kt │ │ ├── WeaponFactory.kt │ │ └── Weapons.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── factorykit │ │ ├── AppTest.kt │ │ └── FactoryKitTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── factory-method ├── README.md ├── build.gradle.kts ├── etc │ ├── diagram1.png │ └── presentation.html └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── factory │ │ └── method │ │ ├── blacksmith │ │ ├── Blacksmith.kt │ │ ├── ElfBlacksmith.kt │ │ └── OrcBlacksmith.kt │ │ └── weapon │ │ ├── ElfWeapon.kt │ │ ├── OrcWeapon.kt │ │ ├── Weapon.kt │ │ └── WeaponType.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── factory │ │ └── method │ │ └── FactoryMethodTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── feature-toggle ├── README.md ├── build.gradle.kts ├── etc │ ├── feature-toggle.png │ ├── feature-toggle.ucls │ └── feature-toggle.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── featuretoggle │ │ ├── App.kt │ │ ├── Users.kt │ │ └── pattern │ │ ├── PropertiesFeatureToggleVersion.kt │ │ ├── Service.kt │ │ └── TieredFeatureToggleVersion.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── featuretoggle │ │ ├── UserGroupTest.kt │ │ └── pattern │ │ ├── PropertiesFeatureToggleVersionTest.kt │ │ └── TieredFeatureToggleVersionTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── guarded-suspension ├── README.md ├── build.gradle.kts ├── doc │ └── guarded-suspension.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── guarded │ │ └── suspension │ │ └── GuardedQueue.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── guarded │ │ └── suspension │ │ └── GuardedQueueTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── interpreter ├── README.md ├── etc │ ├── interpreter.png │ ├── interpreter.ucls │ ├── interpreter.urm.puml │ └── interpreter_1.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── interpreter │ │ ├── App.kt │ │ ├── Expression.kt │ │ ├── MinusExpression.kt │ │ ├── MultiplyExpression.kt │ │ ├── NumberExpression.kt │ │ └── PlusExpression.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── interpreter │ │ ├── AppTest.kt │ │ ├── ExpressionTest.kt │ │ ├── MinusExpressionTest.kt │ │ ├── MultiplyExpressionTest.kt │ │ ├── NumberExpressionTest.kt │ │ └── PlusExpressionTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── kommons-core ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ ├── AnyExtensions.kt │ │ ├── ArrayExtensions.kt │ │ ├── AssertFunctions.kt │ │ ├── BigDecimalExtensions.kt │ │ ├── BigIntegerExtensions.kt │ │ ├── BinaryStringFormat.kt │ │ ├── BooleanExtensions.kt │ │ ├── ByteArrayNumber.kt │ │ ├── ClassLoaderExtensions.kt │ │ ├── CloseableExtensions.kt │ │ ├── ClosedRangeExtensions.kt │ │ ├── ConvertExtensions.kt │ │ ├── Defaults.kt │ │ ├── EnumExtensions.kt │ │ ├── GetterSetters.kt │ │ ├── JavaObjectExtensions.kt │ │ ├── KommonsException.kt │ │ ├── LazyValue.kt │ │ ├── Local.kt │ │ ├── NotSupportedException.kt │ │ ├── NumberExtensions.kt │ │ ├── ObjectWrapper.kt │ │ ├── OpenedRange.kt │ │ ├── Option.kt │ │ ├── ReflectionExtensions.kt │ │ ├── RequireFunctions.kt │ │ ├── SingletonHolder.kt │ │ ├── SortDirection.kt │ │ ├── StringBuilderExtensions.kt │ │ ├── StringExtensions.kt │ │ ├── SystemPropertyExtensions.kt │ │ ├── ToStringBuilder.kt │ │ ├── TypeReference.kt │ │ ├── ValueObject.kt │ │ ├── ValueWrapper.kt │ │ ├── cache │ │ ├── AsyncCacheProvider.kt │ │ ├── Cache2kProvider.kt │ │ ├── CacheProvider.kt │ │ ├── CacheProviderManager.kt │ │ └── NamedCacheManager.kt │ │ ├── functional │ │ └── Currying.kt │ │ └── utils │ │ ├── AtomicIntRoundrobin.kt │ │ ├── BoundedStack.kt │ │ ├── ComparisonChain.kt │ │ ├── KoreanExtensions.kt │ │ ├── KotlinDelegate.kt │ │ ├── KotlinDetector.kt │ │ ├── LocaleExtensions.kt │ │ ├── Networkx.kt │ │ ├── Runtimex.kt │ │ ├── Stopwatch.kt │ │ ├── Systemx.kt │ │ ├── codec │ │ ├── Base64StringEncoder.kt │ │ ├── HexStringEncoder.kt │ │ ├── StringEncoder.kt │ │ └── StringEncoderExtensions.kt │ │ ├── concurrency │ │ ├── ConcurrencyLocks.kt │ │ └── NamedThreadFactory.kt │ │ ├── memorizer │ │ ├── AsyncMemorizer.kt │ │ ├── InMemoryAsyncMemorizer.kt │ │ ├── InMemoryMemorizer.kt │ │ ├── Memorizer.kt │ │ └── cache2k │ │ │ ├── Cache2kAsyncMemorizer.kt │ │ │ └── Cache2kMemorizer.kt │ │ └── resizablearray │ │ ├── ArrayBlock.kt │ │ ├── QueueIntFlip.kt │ │ ├── ResizableArray.kt │ │ └── ResizableArrayBuffer.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ ├── AssertExtensionsTest.kt │ │ ├── AynExtensionsTest.kt │ │ ├── BigDecimalExtensionsTest.kt │ │ ├── BigIntegerExtensionsTest.kt │ │ ├── ByteArrayNumberTest.kt │ │ ├── ClassLoaderExtensionsTest.kt │ │ ├── CloseableExtensionsTest.kt │ │ ├── ClosedRangeExtensionsTest.kt │ │ ├── ConvertExtensionsTest.kt │ │ ├── EnumExtensionsTest.kt │ │ ├── GetterSettersTest.kt │ │ ├── LazyValueTest.kt │ │ ├── NumberExtensionsTest.kt │ │ ├── ReflectionExtensionsTest.kt │ │ ├── RequireFunctionsTest.kt │ │ ├── SingletonHolderTest.kt │ │ ├── StringExtensionsTest.kt │ │ ├── SystemPropertyExtensionsTest.kt │ │ ├── ToStringBuilderTest.kt │ │ ├── TypeReferenceTest.kt │ │ ├── ValueObjectTest.kt │ │ ├── ValueWrapperTest.kt │ │ ├── examples │ │ ├── DelegateExamples.kt │ │ └── LiteralFunctionExamples.kt │ │ ├── functional │ │ └── CurryingTest.kt │ │ └── utils │ │ ├── AtomicIntRoundrobinTest.kt │ │ ├── ComparisonChainTest.kt │ │ ├── KoreanExtensionsTest.kt │ │ ├── KotlinDelegateTest.kt │ │ ├── KotlinDetectorTest.kt │ │ ├── LocaleExtensionsTest.kt │ │ ├── NetworkxTest.kt │ │ ├── RuntimexTest.kt │ │ ├── SystemxTest.kt │ │ ├── codec │ │ ├── AbstractStringEncoderTest.kt │ │ ├── Base64StringEncoderTest.kt │ │ └── HexStringEncoderTest.kt │ │ ├── concurrency │ │ └── ConcurrencyLocksTest.kt │ │ ├── memorizer │ │ ├── AbstractAsyncMemorizerTest.kt │ │ ├── AbstractMemorizerTest.kt │ │ ├── InMemoryAsyncMemorizerTest.kt │ │ ├── InMemoryMemorizerTest.kt │ │ └── cache2k │ │ │ ├── Cachd2kMemorizerTest.kt │ │ │ └── Cache2kAsyncMemorizerTest.kt │ │ └── resizablearray │ │ ├── ResizableArrayBufferTest.kt │ │ └── ResizableArrayTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── kommons-junit-jupiter ├── README.adoc ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── junit │ │ └── jupiter │ │ ├── JupiterExtensions.kt │ │ ├── benchmark │ │ └── BenchmarkExtension.kt │ │ ├── folder │ │ ├── TempFolder.kt │ │ ├── TempFolderExtension.kt │ │ └── TempFolderTest.kt │ │ ├── output │ │ ├── CaptureSystemOutput.kt │ │ ├── CaptureSystemOutputExtension.kt │ │ ├── InMemoryAppender.kt │ │ └── OutputCapture.kt │ │ ├── random │ │ ├── RandomExtension.kt │ │ ├── RandomValue.kt │ │ └── RandomizedTest.kt │ │ ├── stopwatch │ │ ├── StopWatchExtension.kt │ │ └── StopWatchTest.kt │ │ ├── system │ │ ├── RestoreContext.kt │ │ ├── SystemProperties.kt │ │ ├── SystemProperty.kt │ │ └── SystemPropertyExtension.kt │ │ └── utils │ │ ├── ExecutionEvent.kt │ │ ├── ExtensionTester.kt │ │ └── RecordingExecutionListener.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── junit │ │ └── jupiter │ │ ├── JupiterExtensionsTest.kt │ │ ├── benchmark │ │ └── BenchmarkExtensionTest.kt │ │ ├── folder │ │ ├── TempFolderExtensionBeforeAllTest.kt │ │ ├── TempFolderExtensionBeforeEachTest.kt │ │ ├── TempFolderExtensionParameterTest.kt │ │ └── TempFolderTests.kt │ │ ├── output │ │ ├── CaptureSystemOutputExtensionTest.kt │ │ └── InMemoryAppenderTest.kt │ │ ├── random │ │ ├── AssertionExtensions.kt │ │ ├── DomainObject.kt │ │ ├── NestedDomainObject.kt │ │ ├── RandomExtensionFieldTest.kt │ │ └── RandomExtensionParameterTest.kt │ │ ├── stopwatch │ │ └── StopWatchExtensionTest.kt │ │ └── system │ │ ├── SystemPropertyExtensionClassTest.kt │ │ └── SystemPropertyExtensionMetaTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── kommons-logging ├── README.adoc ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── logging │ │ ├── KLogging.kt │ │ ├── KotlinLogging.kt │ │ ├── LoggerExtenstions.kt │ │ └── internal │ │ ├── KLoggerFactory.kt │ │ └── KLoggerNameResolver.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── logging │ │ └── KLoggingTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── kommons-testcontainers ├── README.adoc ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── testcontainers │ │ ├── GenericServer.kt │ │ ├── aws │ │ ├── DynaliteServer.kt │ │ ├── DynamoDBServer.kt │ │ └── S3Server.kt │ │ ├── databases │ │ ├── DatabaseFactory.kt │ │ ├── JdbcDatabaseServer.kt │ │ ├── JdbcDatabaseServerExtensions.kt │ │ ├── MariaDBServer.kt │ │ ├── MySQLServer.kt │ │ └── PostgreSQLServer.kt │ │ ├── generic │ │ ├── ArangoDBServer.kt │ │ ├── HazelcastServer.kt │ │ ├── IgniteServer.kt │ │ ├── MemcachedExtensions.kt │ │ ├── MemcachedServer.kt │ │ ├── MongoDBServer.kt │ │ ├── RedisServer.kt │ │ └── ZipkinServer.kt │ │ ├── message │ │ ├── KafkaServer.kt │ │ ├── PulsarServer.kt │ │ └── RabbitmqServer.kt │ │ └── nosql │ │ ├── CassandraServer.kt │ │ ├── ElassandraServer.kt │ │ ├── ElasticsearchServer.kt │ │ └── InfluxDBServer.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── testcontainers │ │ ├── aws │ │ ├── DynaliteServerTest.kt │ │ ├── DynamoDBServerTest.kt │ │ └── S3ServerTest.kt │ │ ├── databases │ │ ├── DatabaseFactoryTest.kt │ │ ├── MariaDBServerTest.kt │ │ ├── MySQLServerTest.kt │ │ └── PostgreSQLServerTest.kt │ │ ├── generic │ │ ├── ArangoDBServerTest.kt │ │ ├── HazelcastServerTest.kt │ │ ├── IgniteServerTest.kt │ │ ├── MemcachedServerTest.kt │ │ ├── MongoDBServerTest.kt │ │ ├── RedisServerTest.kt │ │ └── RedissonExtensions.kt │ │ ├── message │ │ ├── KafkaServerTest.kt │ │ ├── PulsarServerTest.kt │ │ └── RabbitmqServerTest.kt │ │ └── nosql │ │ ├── CassandraServerTest.kt │ │ ├── ElassandraServerTest.kt │ │ ├── ElasticsearchServerTest.kt │ │ └── InfluxDBServerTest.kt │ └── resources │ ├── cassandra-test-configuration-example │ └── cassandra.yaml │ ├── hazelcast-client.xml │ ├── initial.cql │ ├── junit-platform.properties │ └── logback-test.xml ├── lazy-loading ├── README.md ├── build.gradle.kts ├── doc │ └── lazy-loading.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── lazy │ │ └── loading │ │ ├── Heavy.kt │ │ ├── HolderNaive.kt │ │ ├── HolderThreadSafe.kt │ │ └── KotlinHolder.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── lazy │ │ └── loading │ │ ├── AbstractHolderTest.kt │ │ ├── HolderNaiveTest.kt │ │ ├── HolderThreadSafeTest.kt │ │ └── KotlinHolderTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── poison-pill ├── README.md ├── build.gradle.kts ├── etc │ ├── poison-pill.png │ ├── poison-pill.ucls │ └── poison-pill.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── poisonpill │ │ ├── App.kt │ │ ├── Consumer.kt │ │ ├── Message.kt │ │ ├── MessageQueue.kt │ │ └── Producer.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── poisonpill │ │ ├── AppTest.kt │ │ ├── ConsumerTest.kt │ │ ├── PoisonMessageTest.kt │ │ ├── ProducerTest.kt │ │ └── SimpleMessageTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── producer-consumer ├── README.md ├── build.gradle.kts ├── etc │ ├── producer-consumer.png │ └── producer-consumer.ucls └── src │ ├── main │ ├── kotlin │ │ └── io │ │ │ └── kommons │ │ │ └── designpatterns │ │ │ └── producer │ │ │ └── consumer │ │ │ ├── App.kt │ │ │ ├── Consumer.kt │ │ │ ├── Item.kt │ │ │ ├── ItemQueue.kt │ │ │ └── Producer.kt │ └── resources │ │ └── logback.xml │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── producer │ │ └── consumer │ │ ├── AppTest.kt │ │ ├── ConsumerTest.kt │ │ └── ProducerTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── promise ├── README.md ├── build.gradle.kts ├── etc │ ├── promise.png │ ├── promise.ucls │ └── promise.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── promise │ │ ├── App.kt │ │ ├── Promise.kt │ │ ├── PromiseSupport.kt │ │ └── Utility.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── promise │ │ ├── AppTest.kt │ │ └── PromiseTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── queue-load-leveling ├── README.md ├── build.gradle.kts ├── etc │ ├── queue-load-leveling.gif │ ├── queue-load-leveling.ucls │ └── queue-load-leveling.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── queueloadleveling │ │ ├── App.kt │ │ ├── Message.kt │ │ ├── MessageQueue.kt │ │ ├── ServiceExecutor.kt │ │ ├── Task.kt │ │ └── TaskGenerator.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── queueloadleveling │ │ ├── AppTest.kt │ │ ├── MessageQueueTest.kt │ │ └── TaskGeneratorTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── resource-acquisition-is-initialization ├── README.md ├── build.gradle.kts ├── etc │ ├── resource-acquisition-is-initialization.png │ ├── resource-acquisition-is-initialization.ucls │ └── resource-acquisition-is-initialization.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── resource │ │ └── acquisition │ │ └── is │ │ └── initialization │ │ ├── App.kt │ │ ├── SlidingDoor.kt │ │ └── TreasureChest.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── resource │ │ └── acquisition │ │ └── is │ │ └── initialization │ │ ├── AppTest.kt │ │ └── CloseableTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── retry ├── README.md ├── build.gradle.kts ├── etc │ ├── retry.png │ └── retry.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── retry │ │ ├── App.kt │ │ ├── BusinessException.kt │ │ ├── BusinessOperation.kt │ │ └── FindCustomer.kt │ └── test │ └── kotlin │ └── io │ └── kommons │ └── designpatterns │ └── retry │ ├── AppTest.kt │ └── FindCustomerTest.kt ├── role-object ├── README.md ├── build.gradle.kts ├── etc │ ├── role-object.urm.png │ └── role-object.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── roleobject │ │ ├── ApplicationRoleObject.kt │ │ ├── BorrowerRole.kt │ │ ├── Customer.kt │ │ ├── CustomerCore.kt │ │ ├── CustomerRole.kt │ │ ├── InvestorRole.kt │ │ └── Role.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── roleobject │ │ ├── ApplicationRoleObjectTest.kt │ │ ├── BorrowerRoleTest.kt │ │ ├── CustomerCoreTest.kt │ │ ├── InvestorRoleTest.kt │ │ └── RoleTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── semaphore ├── README.md ├── build.gradle.kts ├── etc │ ├── semaphore.png │ └── semaphore.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── semaphore │ │ ├── App.kt │ │ ├── Customer.kt │ │ ├── Fruits.kt │ │ ├── Lock.kt │ │ └── Semaphore.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── semaphore │ │ ├── AppTest.kt │ │ ├── FruitBowlTest.kt │ │ └── SemaphoreTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── servant ├── README.md ├── etc │ ├── servant-pattern.png │ ├── servant-pattern.ucls │ └── servant.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── servant │ │ ├── App.kt │ │ ├── King.kt │ │ ├── Queen.kt │ │ ├── Royalty.kt │ │ └── Servant.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── servant │ │ ├── AppTest.kt │ │ └── ServantTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── service-locator ├── README.md ├── etc │ ├── service-locator.png │ ├── service-locator.ucls │ └── service-locator.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── servicelocator │ │ ├── App.kt │ │ ├── InitContext.kt │ │ ├── Service.kt │ │ ├── ServiceCache.kt │ │ ├── ServiceImpl.kt │ │ └── ServiceLocator.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── servicelocator │ │ ├── AppTest.kt │ │ └── ServiceLocatorTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── settings.gradle.kts ├── sharding ├── README.md ├── build.gradle.kts ├── etc │ ├── sharding.urm.png │ └── sharding.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── sharding │ │ ├── Shard.kt │ │ └── managers │ │ ├── HashShardManager.kt │ │ ├── LookupShardManager.kt │ │ ├── RangeShardManager.kt │ │ └── ShardManager.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── sharding │ │ ├── AbstractShardManagerTest.kt │ │ ├── HashShardManagerTest.kt │ │ ├── LookupShardManagerTest.kt │ │ ├── RangeShardManagerTest.kt │ │ └── ShardTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── singleton ├── README.md ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── singleton │ │ ├── EnumIvoryTower.kt │ │ ├── InitializingOnDemandHolderIdiom.kt │ │ ├── IvoryTower.kt │ │ ├── IvoryTowerObject.kt │ │ ├── KotlinSingleton.kt │ │ ├── ThreadSafeDoubleCheckLocking.kt │ │ └── ThreadSafeLazyLoadedIvoryTower.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── singleton │ │ ├── AbstractSingletonTest.kt │ │ ├── EnumIvoryTowerTest.kt │ │ ├── InitializingOnDemandHolderIdiomTest.kt │ │ ├── IvoryTowerTest.kt │ │ ├── ThreadSafeDoubleCheckLockingTest.kt │ │ └── ThreadSafeLazyLoadedIvoryTowerTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── specification ├── README.md ├── build.gradle.kts ├── etc │ ├── specification.png │ ├── specification.ucls │ └── specification.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── specification │ │ ├── App.kt │ │ ├── Creatures.kt │ │ ├── Properties.kt │ │ └── Selectors.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── specification │ │ ├── CreatureTest.kt │ │ └── SelectorTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── state ├── README.md ├── build.gradle.kts ├── etc │ ├── state.png │ ├── state.ucls │ └── state_1.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── state │ │ ├── AngreState.kt │ │ ├── Mammoth.kt │ │ ├── PeacefulState.kt │ │ └── State.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── state │ │ └── MammonthTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── step-builder ├── README.md ├── build.gradle.kts ├── etc │ ├── step-builder.png │ ├── step-builder.ucls │ └── step-builder.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── stepbuilder │ │ ├── App.kt │ │ ├── Character.kt │ │ └── CharacterStepBuilder.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── stepbuilder │ │ └── CharacterStepBuilderTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── strategy ├── README.md ├── build.gradle.kts ├── etc │ ├── strategy.png │ ├── strategy.ucls │ └── strategy_1.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── strategy │ │ ├── DragonSlayer.kt │ │ ├── DragonSlayingStrategy.kt │ │ ├── MeleeStrategy.kt │ │ ├── ProjectileStrategy.kt │ │ └── SpellStrategy.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── strategy │ │ ├── DragonSlayerTest.kt │ │ └── DragonSlayingStrategyTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── subclass-sandbox ├── README.md ├── build.gradle.kts ├── etc │ ├── subclass-sandbox.urm.png │ └── subclass-sandbox.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── subclasssandbox │ │ ├── GroundDive.kt │ │ ├── SkyLauncher.kt │ │ └── Superpower.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── subclasssandbox │ │ ├── GroundDiveTest.kt │ │ └── SuperpowerTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── template-method ├── README.md ├── etc │ ├── template-method.png │ ├── template-method.ucls │ └── template-method_1.png └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── templatemethod │ │ ├── HalflingThief.kt │ │ ├── HitAndRunMethod.kt │ │ ├── StealingMethod.kt │ │ └── SubtleMethod.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── templatemethod │ │ ├── HalflingThiefTest.kt │ │ ├── HitAndRunMethodTest.kt │ │ ├── StealingMethodTest.kt │ │ └── SubtleMethodTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── thread-pool ├── README.md ├── build.gradle.kts ├── etc │ ├── thread-pool.png │ ├── thread-pool.ucls │ └── thread-pool.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── threadpool │ │ ├── App.kt │ │ ├── Tasks.kt │ │ └── Worker.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── threadpool │ │ ├── AppTest.kt │ │ ├── CoffeeMakingTaskTest.kt │ │ ├── PotatoPeelingTaskTest.kt │ │ ├── TaskTest.kt │ │ └── WorkerTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── throttling ├── README.md ├── build.gradle.kts ├── etc │ ├── throttling-pattern.png │ └── throttling-pattern.ucls └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── throttling │ │ ├── B2BService.kt │ │ ├── CallsCount.kt │ │ ├── Tenant.kt │ │ └── timer │ │ ├── ThrottleTimerImpl.kt │ │ └── Throttler.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── throttling │ │ ├── B2BServiceTest.kt │ │ └── TenantTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── tls ├── README.md ├── etc │ ├── tls.png │ ├── tls.ucls │ └── tls.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── tls │ │ ├── App.kt │ │ ├── DateFormatCallable.kt │ │ └── Result.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── tls │ │ ├── AppTest.kt │ │ └── DateFormatCallableTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── tolerant-reader ├── README.md ├── build.gradle.kts ├── etc │ ├── tolerant-reader.png │ ├── tolerant-reader.ucls │ └── tolerant-reader.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── tolerantreader │ │ ├── App.kt │ │ ├── RainbowFish.kt │ │ └── RainbowFishSerializer.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── tolerantreader │ │ └── RainbowFishSerializerTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── update-method ├── README.md ├── build.gradle.kts ├── etc │ ├── update-method.urm.png │ └── update-method.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── updatemethod │ │ ├── App.kt │ │ ├── Entities.kt │ │ └── World.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── updatemethod │ │ ├── AppTest.kt │ │ └── WorldTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml ├── value-object ├── README.md ├── etc │ ├── value-object.png │ ├── value-object.ucls │ └── value-object.urm.puml └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── valueobject │ │ ├── App.kt │ │ └── HeroStat.kt │ └── test │ ├── kotlin │ └── io │ │ └── kommons │ │ └── designpatterns │ │ └── valueobject │ │ └── HeroStatTest.kt │ └── resources │ ├── junit-platform.properties │ └── logback-test.xml └── visitor ├── README.md ├── build.gradle.kts ├── doc ├── visitor.png ├── visitor.ucls └── visitor_1.png └── src ├── main └── kotlin │ └── io │ └── kommons │ └── designpatterns │ └── visitor │ ├── Commander.kt │ ├── CommanderVisitor.kt │ ├── Node.kt │ ├── NodeVisitor.kt │ ├── Sergeant.kt │ ├── SergeantVisitor.kt │ ├── Soldier.kt │ └── SoldierVisitor.kt └── test ├── kotlin └── io │ └── kommons │ └── designpatterns │ └── visitor │ ├── AbstractNodeTest.kt │ ├── AbstractVisitorTest.kt │ ├── CommanderTest.kt │ ├── CommanderVisitorTest.kt │ ├── SergeantTest.kt │ ├── SergeantVisitorTest.kt │ ├── SoldierTest.kt │ └── SoldierVisitorTest.kt └── resources ├── junit-platform.properties └── logback-test.xml /.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | # 4 | # These are explicitly windows files and should use crlf 5 | *.bat text eol=crlf 6 | 7 | -------------------------------------------------------------------------------- /.java-version: -------------------------------------------------------------------------------- 1 | 11 2 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Design Patterns by Kotlin 2 | 3 | https://github.com/iluwatar/java-design-patterns.git[Java Design Patterns] 를 참고하여, Kotlin 언어로 Design Patterns 예제를 설명합니다. -------------------------------------------------------------------------------- /abstract-document/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /abstract-document/doc/abstract-document.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/abstract-document/doc/abstract-document.png -------------------------------------------------------------------------------- /abstract-document/src/main/kotlin/io/kommons/designpatterns/abstractdocument/Document.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractdocument 2 | 3 | /** 4 | * Document 5 | * 6 | * @author debop 7 | * @since 28/09/2019 8 | */ 9 | interface Document { 10 | 11 | operator fun set(key: String, value: Any?) 12 | 13 | operator fun get(key: String): Any? 14 | 15 | fun children(key: String, constructor: (MutableMap) -> T): Sequence 16 | } -------------------------------------------------------------------------------- /abstract-document/src/main/kotlin/io/kommons/designpatterns/abstractdocument/domain/Car.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractdocument.domain 2 | 3 | import io.kommons.designpatterns.abstractdocument.AbstractDocument 4 | 5 | /** 6 | * Car 7 | * 8 | * @author debop 9 | * @since 28/09/2019 10 | */ 11 | class Car(properties: MutableMap): AbstractDocument(properties), HasModel, HasPrice, HasParts -------------------------------------------------------------------------------- /abstract-document/src/main/kotlin/io/kommons/designpatterns/abstractdocument/domain/HasModel.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractdocument.domain 2 | 3 | import io.kommons.designpatterns.abstractdocument.Document 4 | 5 | /** 6 | * HasModel 7 | * 8 | * @author debop 9 | * @since 28/09/2019 10 | */ 11 | interface HasModel: Document { 12 | 13 | @JvmDefault 14 | fun getModel(): String? = get(Property.MODEL.name) as? String 15 | } -------------------------------------------------------------------------------- /abstract-document/src/main/kotlin/io/kommons/designpatterns/abstractdocument/domain/HasParts.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractdocument.domain 2 | 3 | import io.kommons.designpatterns.abstractdocument.Document 4 | 5 | /** 6 | * HasParts 7 | * 8 | * @author debop 9 | * @since 28/09/2019 10 | */ 11 | interface HasParts: Document { 12 | 13 | @JvmDefault 14 | fun getParts(): Sequence = 15 | children(Property.PARTS.name) { Part(it) } 16 | } -------------------------------------------------------------------------------- /abstract-document/src/main/kotlin/io/kommons/designpatterns/abstractdocument/domain/HasPrice.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractdocument.domain 2 | 3 | import io.kommons.designpatterns.abstractdocument.Document 4 | 5 | /** 6 | * HasPrice 7 | * 8 | * @author debop 9 | * @since 28/09/2019 10 | */ 11 | interface HasPrice: Document { 12 | 13 | @JvmDefault 14 | fun getPrice(): Number? = get(Property.PRICE.name) as? Number 15 | } -------------------------------------------------------------------------------- /abstract-document/src/main/kotlin/io/kommons/designpatterns/abstractdocument/domain/HasType.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractdocument.domain 2 | 3 | import io.kommons.designpatterns.abstractdocument.Document 4 | 5 | /** 6 | * HasType 7 | * 8 | * @author debop 9 | * @since 28/09/2019 10 | */ 11 | interface HasType: Document { 12 | 13 | @JvmDefault 14 | fun getType(): String? = get(Property.TYPE.name) as? String 15 | 16 | } -------------------------------------------------------------------------------- /abstract-document/src/main/kotlin/io/kommons/designpatterns/abstractdocument/domain/Part.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractdocument.domain 2 | 3 | import io.kommons.designpatterns.abstractdocument.AbstractDocument 4 | 5 | /** 6 | * Part 7 | * 8 | * @author debop 9 | * @since 28/09/2019 10 | */ 11 | class Part(properties: MutableMap): AbstractDocument(properties), HasType, HasModel, HasPrice -------------------------------------------------------------------------------- /abstract-document/src/main/kotlin/io/kommons/designpatterns/abstractdocument/domain/Property.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractdocument.domain 2 | 3 | /** 4 | * Property 5 | * 6 | * @author debop 7 | * @since 28/09/2019 8 | */ 9 | enum class Property { 10 | 11 | PARTS, 12 | TYPE, 13 | PRICE, 14 | MODEL; 15 | 16 | } -------------------------------------------------------------------------------- /abstract-document/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /abstract-factory/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | } -------------------------------------------------------------------------------- /abstract-factory/doc/diagram1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/abstract-factory/doc/diagram1.png -------------------------------------------------------------------------------- /abstract-factory/doc/diagram2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/abstract-factory/doc/diagram2.png -------------------------------------------------------------------------------- /abstract-factory/src/main/kotlin/io/kommons/designpatterns/abstractfactory/Army.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractfactory 2 | 3 | /** 4 | * Army 5 | * 6 | * @author debop 7 | * @since 28/09/2019 8 | */ 9 | interface Army { 10 | 11 | fun getDescription(): String 12 | 13 | } -------------------------------------------------------------------------------- /abstract-factory/src/main/kotlin/io/kommons/designpatterns/abstractfactory/Castle.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractfactory 2 | 3 | /** 4 | * Castle 5 | * 6 | * @author debop 7 | * @since 28/09/2019 8 | */ 9 | interface Castle { 10 | 11 | fun getDescription(): String 12 | 13 | } -------------------------------------------------------------------------------- /abstract-factory/src/main/kotlin/io/kommons/designpatterns/abstractfactory/FactoryMaker.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractfactory 2 | 3 | import io.kommons.designpatterns.abstractfactory.elf.ElfKingdomFactory 4 | import io.kommons.designpatterns.abstractfactory.orc.OrcKingdomFactory 5 | 6 | /** 7 | * FactoryMaker 8 | * 9 | * @author debop 10 | * @since 28/09/2019 11 | */ 12 | object FactoryMaker { 13 | 14 | enum class KingdomType { 15 | ELF, ORC 16 | } 17 | 18 | fun makeFactory(type: KingdomType): KingdomFactory = when (type) { 19 | KingdomType.ELF -> ElfKingdomFactory() 20 | KingdomType.ORC -> OrcKingdomFactory() 21 | } 22 | } -------------------------------------------------------------------------------- /abstract-factory/src/main/kotlin/io/kommons/designpatterns/abstractfactory/King.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractfactory 2 | 3 | /** 4 | * King 5 | * 6 | * @author debop 7 | * @since 28/09/2019 8 | */ 9 | interface King { 10 | 11 | fun getDescription(): String 12 | 13 | } -------------------------------------------------------------------------------- /abstract-factory/src/main/kotlin/io/kommons/designpatterns/abstractfactory/KingdomFactory.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractfactory 2 | 3 | /** 4 | * KingdomFactory 5 | * 6 | * @author debop 7 | * @since 28/09/2019 8 | */ 9 | interface KingdomFactory { 10 | 11 | fun createCastle(): Castle 12 | 13 | fun createKing(): King 14 | 15 | fun createArmy(): Army 16 | 17 | } -------------------------------------------------------------------------------- /abstract-factory/src/main/kotlin/io/kommons/designpatterns/abstractfactory/elf/ElfArmy.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractfactory.elf 2 | 3 | import io.kommons.designpatterns.abstractfactory.Army 4 | 5 | /** 6 | * ElfArmy 7 | * 8 | * @author debop 9 | * @since 28/09/2019 10 | */ 11 | class ElfArmy: Army { 12 | 13 | companion object { 14 | const val DESCRIPTION = "This is the Elven Army!" 15 | } 16 | 17 | override fun getDescription(): String = DESCRIPTION 18 | 19 | } -------------------------------------------------------------------------------- /abstract-factory/src/main/kotlin/io/kommons/designpatterns/abstractfactory/elf/ElfCastle.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractfactory.elf 2 | 3 | import io.kommons.designpatterns.abstractfactory.Castle 4 | 5 | /** 6 | * ElfCastle 7 | * 8 | * @author debop 9 | * @since 28/09/2019 10 | */ 11 | class ElfCastle: Castle { 12 | 13 | companion object { 14 | const val DESCRIPTION = "This is the Elven castle!" 15 | } 16 | 17 | override fun getDescription(): String = DESCRIPTION 18 | 19 | } -------------------------------------------------------------------------------- /abstract-factory/src/main/kotlin/io/kommons/designpatterns/abstractfactory/elf/ElfKing.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractfactory.elf 2 | 3 | import io.kommons.designpatterns.abstractfactory.King 4 | 5 | /** 6 | * ElfKing 7 | * 8 | * @author debop 9 | * @since 28/09/2019 10 | */ 11 | class ElfKing: King { 12 | 13 | companion object { 14 | const val DESCRIPTION = "This is the Elven king!" 15 | } 16 | 17 | override fun getDescription(): String = DESCRIPTION 18 | 19 | } -------------------------------------------------------------------------------- /abstract-factory/src/main/kotlin/io/kommons/designpatterns/abstractfactory/orc/OrcArmy.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractfactory.orc 2 | 3 | import io.kommons.designpatterns.abstractfactory.Army 4 | 5 | /** 6 | * OrcArmy 7 | * 8 | * @author debop 9 | * @since 28/09/2019 10 | */ 11 | class OrcArmy: Army { 12 | 13 | companion object { 14 | const val DESCRIPTION = "This is the Orc Army!" 15 | } 16 | 17 | override fun getDescription(): String = DESCRIPTION 18 | 19 | } -------------------------------------------------------------------------------- /abstract-factory/src/main/kotlin/io/kommons/designpatterns/abstractfactory/orc/OrcCastle.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractfactory.orc 2 | 3 | import io.kommons.designpatterns.abstractfactory.Castle 4 | 5 | /** 6 | * OrcCastle 7 | * 8 | * @author debop 9 | * @since 28/09/2019 10 | */ 11 | class OrcCastle: Castle { 12 | 13 | companion object { 14 | const val DESCRIPTION = "This is the Orc Castle!" 15 | } 16 | 17 | override fun getDescription(): String = DESCRIPTION 18 | 19 | } -------------------------------------------------------------------------------- /abstract-factory/src/main/kotlin/io/kommons/designpatterns/abstractfactory/orc/OrcKing.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.abstractfactory.orc 2 | 3 | import io.kommons.designpatterns.abstractfactory.King 4 | 5 | /** 6 | * OrcKing 7 | * 8 | * @author debop 9 | * @since 28/09/2019 10 | */ 11 | class OrcKing: King { 12 | 13 | companion object { 14 | const val DESCRIPTION = "This is the Orc King!" 15 | } 16 | 17 | override fun getDescription(): String = DESCRIPTION 18 | 19 | } -------------------------------------------------------------------------------- /abstract-factory/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /acycle-visitor/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /acycle-visitor/etc/acyclic-visitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/acycle-visitor/etc/acyclic-visitor.png -------------------------------------------------------------------------------- /acycle-visitor/src/main/kotlin/io/kommons/designpatterns/acyclicvisitor/AllModemVisitor.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.acyclicvisitor 2 | 3 | /** 4 | * All ModemVisitor interface extends all visitor interfaces. This interface 5 | * provides ease of use when a visitor needs to visit all modem types. 6 | */ 7 | interface AllModemVisitor: ZoomVisitor, HayesVisitor { 8 | } -------------------------------------------------------------------------------- /acycle-visitor/src/main/kotlin/io/kommons/designpatterns/acyclicvisitor/ConfigureForUnixVisitor.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.acyclicvisitor 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.debug 5 | 6 | /** 7 | * ConfigureForUnixVisitor class implements zoom's visit method for Unix 8 | * manufacturer, unlike traditional visitor pattern, this class may selectively implement 9 | * visit for other modems. 10 | */ 11 | class ConfigureForUnixVisitor: ZoomVisitor { 12 | 13 | companion object: KLogging() 14 | 15 | override fun visit(zoom: Zoom) { 16 | log.debug { "$zoom used with Unix configurator." } 17 | } 18 | } -------------------------------------------------------------------------------- /acycle-visitor/src/main/kotlin/io/kommons/designpatterns/acyclicvisitor/HayesVisitor.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.acyclicvisitor 2 | 3 | /** 4 | * HayesVisitor interface 5 | */ 6 | interface HayesVisitor: ModemVisitor { 7 | 8 | fun visit(hayes: Hayes) 9 | 10 | } -------------------------------------------------------------------------------- /acycle-visitor/src/main/kotlin/io/kommons/designpatterns/acyclicvisitor/Modem.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.acyclicvisitor 2 | 3 | /** 4 | * Modem abstract class 5 | */ 6 | abstract class Modem { 7 | 8 | abstract fun accept(modemVisitor: ModemVisitor) 9 | 10 | } -------------------------------------------------------------------------------- /acycle-visitor/src/main/kotlin/io/kommons/designpatterns/acyclicvisitor/ModemVisitor.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.acyclicvisitor 2 | 3 | /** 4 | * ModemVisitor interface does not contain any visit methods so that it does not 5 | * depend on the visited hierarchy. Each derivative's visit method is declared in 6 | * its own visitor interface 7 | */ 8 | interface ModemVisitor { 9 | // Visitor is a degenerate base class for all visitors. 10 | } -------------------------------------------------------------------------------- /acycle-visitor/src/main/kotlin/io/kommons/designpatterns/acyclicvisitor/Zoom.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.acyclicvisitor 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | /** 7 | * Zoom 8 | * 9 | * @author debop 10 | */ 11 | class Zoom: Modem() { 12 | 13 | companion object: KLogging() 14 | 15 | override fun accept(modemVisitor: ModemVisitor) { 16 | when (modemVisitor) { 17 | is ZoomVisitor -> modemVisitor.visit(this) 18 | else -> log.info { "Only ZoomVisitor is allowed to visit Zoom modem" } 19 | } 20 | } 21 | 22 | override fun toString(): String = "Zoom modem" 23 | } -------------------------------------------------------------------------------- /acycle-visitor/src/main/kotlin/io/kommons/designpatterns/acyclicvisitor/ZoomVisitor.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.acyclicvisitor 2 | 3 | /** 4 | * ZoomVisitor interface 5 | * 6 | * @author debop 7 | */ 8 | interface ZoomVisitor: ModemVisitor { 9 | 10 | fun visit(zoom: Zoom) 11 | 12 | } -------------------------------------------------------------------------------- /acycle-visitor/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /adaptor/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /adaptor/src/main/kotlin/io/kommons/designpatterns/adapter/App.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.adapter 2 | 3 | class App 4 | 5 | fun main() { 6 | val captain = Captain(FishingBoatAdapter()) 7 | captain.row() 8 | } -------------------------------------------------------------------------------- /adaptor/src/main/kotlin/io/kommons/designpatterns/adapter/Captain.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.adapter 2 | 3 | /** 4 | * Captain 5 | * 6 | * @author debop 7 | * @since 19. 9. 18. 8 | */ 9 | class Captain(val rowingBoat: RowingBoat) { 10 | 11 | fun row() { 12 | rowingBoat.row() 13 | } 14 | } -------------------------------------------------------------------------------- /adaptor/src/main/kotlin/io/kommons/designpatterns/adapter/FishingBoat.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.adapter 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.debug 5 | 6 | /** 7 | * FishingBoat 8 | * 9 | * @author debop 10 | * @since 19. 9. 18. 11 | */ 12 | class FishingBoat { 13 | 14 | companion object: KLogging() 15 | 16 | fun sail() { 17 | log.debug { "The fishing boat is sailing" } 18 | } 19 | } -------------------------------------------------------------------------------- /adaptor/src/main/kotlin/io/kommons/designpatterns/adapter/FishingBoatAdapter.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.adapter 2 | 3 | /** 4 | * [FishingBoat]를 [RowingBoat]로 공개하기 위한 Adapter 5 | */ 6 | class FishingBoatAdapter(private val fishingBoat: FishingBoat = FishingBoat()): RowingBoat { 7 | 8 | override fun row() { 9 | fishingBoat.sail() 10 | } 11 | } -------------------------------------------------------------------------------- /adaptor/src/main/kotlin/io/kommons/designpatterns/adapter/RowingBoat.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.adapter 2 | 3 | /** 4 | * Client 가 사용할 노 젓는 배 5 | */ 6 | interface RowingBoat { 7 | 8 | fun row() 9 | 10 | } -------------------------------------------------------------------------------- /adaptor/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /ambassador/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | api(project(":kommons-logging")) 3 | testApi(project(":kommons-junit-jupiter")) 4 | 5 | api(Libraries.resilience4j_retry) 6 | } -------------------------------------------------------------------------------- /ambassador/etc/ambassador.urm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/ambassador/etc/ambassador.urm.png -------------------------------------------------------------------------------- /ambassador/src/main/kotlin/io/kommons/designpatterns/ambassador/Client.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.ambassador 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | class Client { 7 | 8 | companion object: KLogging() 9 | 10 | private val serviceAmbassador = ServiceAmbassador() 11 | 12 | fun useService(value: Int): Long { 13 | val result = serviceAmbassador.doRemoteFunction(value) 14 | log.info { "Service result: $result" } 15 | return result 16 | } 17 | } -------------------------------------------------------------------------------- /ambassador/src/main/kotlin/io/kommons/designpatterns/ambassador/RemoteServiceInterface.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.ambassador 2 | 3 | /** 4 | * Interface shared by [RemoteService] and [ServiceEmbassador] 5 | * 6 | * @author debop 7 | */ 8 | interface RemoteServiceInterface { 9 | 10 | companion object { 11 | const val FAILURE = -1L 12 | } 13 | 14 | fun doRemoteFunction(value: Int): Long 15 | } -------------------------------------------------------------------------------- /ambassador/src/main/kotlin/io/kommons/designpatterns/ambassador/util/RandomProvider.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.ambassador.util 2 | 3 | interface RandomProvider { 4 | 5 | fun random(): Double 6 | 7 | } 8 | 9 | fun randomProviderOf(nextDouble: () -> Double): RandomProvider = 10 | object: RandomProvider { 11 | override fun random(): Double = nextDouble() 12 | } -------------------------------------------------------------------------------- /ambassador/src/test/kotlin/io/kommons/designpatterns/ambassador/ClientTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.ambassador 2 | 3 | import io.kommons.logging.KLogging 4 | import org.junit.jupiter.api.Test 5 | import kotlin.test.assertTrue 6 | 7 | /** 8 | * ClientTest 9 | * 10 | * @author debop 11 | */ 12 | class ClientTest { 13 | 14 | companion object: KLogging() 15 | 16 | @Test 17 | fun `run remote service via ambassador`() { 18 | val client = Client() 19 | val result = client.useService(10) 20 | 21 | assertTrue { result == RemoteServiceInterface.FAILURE || result == 100L } 22 | } 23 | } -------------------------------------------------------------------------------- /ambassador/src/test/kotlin/io/kommons/designpatterns/ambassador/ServiceAmbassadorTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.ambassador 2 | 3 | import org.junit.jupiter.api.Test 4 | import kotlin.test.assertTrue 5 | 6 | /** 7 | * ServiceAmbassadorTest 8 | * 9 | * @author debop 10 | */ 11 | class ServiceAmbassadorTest { 12 | 13 | @Test 14 | fun `run service ambassador`() { 15 | val result = ServiceAmbassador().doRemoteFunction(10) 16 | assertTrue { result == RemoteServiceInterface.FAILURE || result == 100L } 17 | } 18 | } -------------------------------------------------------------------------------- /ambassador/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /api-gateway/api-gateway-service/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | api(Libraries.resilience4j_all) 3 | 4 | api("org.springframework.boot:spring-boot-starter-webflux") 5 | testApi("org.springframework.boot:spring-boot-starter-test") 6 | } -------------------------------------------------------------------------------- /api-gateway/etc/api-gateway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/api-gateway/etc/api-gateway.png -------------------------------------------------------------------------------- /api-gateway/etc/api-gateway.urm.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | @enduml -------------------------------------------------------------------------------- /api-gateway/image-microservice/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | api(Libraries.resilience4j_all) 4 | 5 | api("org.springframework.boot:spring-boot-starter-webflux") 6 | testApi("org.springframework.boot:spring-boot-starter-test") 7 | } -------------------------------------------------------------------------------- /api-gateway/image-microservice/etc/image-microservice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/api-gateway/image-microservice/etc/image-microservice.png -------------------------------------------------------------------------------- /api-gateway/image-microservice/etc/image-microservice.urm.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | package com.iluwatar.image.microservice { 3 | class ImageApplication { 4 | + ImageApplication() 5 | + main(args : String[]) {static} 6 | } 7 | class ImageController { 8 | + ImageController() 9 | + getImagePath() : String 10 | } 11 | } 12 | @enduml -------------------------------------------------------------------------------- /api-gateway/price-microservice/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | api(Libraries.resilience4j_all) 4 | 5 | api("org.springframework.boot:spring-boot-starter-webflux") 6 | testApi("org.springframework.boot:spring-boot-starter-test") 7 | 8 | } -------------------------------------------------------------------------------- /api-gateway/price-microservice/etc/price-microservice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/api-gateway/price-microservice/etc/price-microservice.png -------------------------------------------------------------------------------- /api-gateway/price-microservice/etc/price-microservice.urm.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | package com.iluwatar.price.microservice { 3 | class PriceApplication { 4 | + PriceApplication() 5 | + main(args : String[]) {static} 6 | } 7 | class PriceController { 8 | + PriceController() 9 | + getPrice() : String 10 | } 11 | } 12 | @enduml -------------------------------------------------------------------------------- /async-method-invocation/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /async-method-invocation/etc/async-method-invocation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/async-method-invocation/etc/async-method-invocation.png -------------------------------------------------------------------------------- /async-method-invocation/src/main/kotlin/io/kommons/designpatterns/methodinvocation/coroutines/CoroutineExecutor.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.methodinvocation.coroutines 2 | 3 | /** 4 | * CoroutineExecutor 5 | * 6 | * @author debop 7 | */ 8 | class CoroutineExecutor { 9 | } -------------------------------------------------------------------------------- /async-method-invocation/src/main/kotlin/io/kommons/designpatterns/methodinvocation/future/CompletableFutureExecutor.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.methodinvocation.future 2 | 3 | /** 4 | * CompletableFutureExecutor 5 | * 6 | * @author debop 7 | */ 8 | class CompletableFutureExecutor { 9 | } -------------------------------------------------------------------------------- /async-method-invocation/src/test/kotlin/io/kommons/designpatterns/methodinvocation/coroutines/CoroutineExecutorTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.methodinvocation.coroutines 2 | 3 | /** 4 | * CoroutineExecutorTest 5 | * 6 | * @author debop 7 | */ 8 | class CoroutineExecutorTest { 9 | } -------------------------------------------------------------------------------- /async-method-invocation/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /balking/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | implementation(Libraries.kotlinx_coroutines_jdk8) 4 | } -------------------------------------------------------------------------------- /balking/doc/balking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/balking/doc/balking.png -------------------------------------------------------------------------------- /balking/src/main/kotlin/io/kommons/designpatterns/balking/DelayProvider.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.balking 2 | 3 | import java.time.Duration 4 | 5 | /** 6 | * DelayProvider 7 | */ 8 | interface DelayProvider { 9 | 10 | suspend fun executeAfterDelay(delayDuration: Duration, task: suspend () -> Unit) 11 | 12 | } -------------------------------------------------------------------------------- /balking/src/main/kotlin/io/kommons/designpatterns/balking/WashingMachineState.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.balking 2 | 3 | /** 4 | * WashingMachineState 5 | * 6 | * @author debop 7 | * @since 27/09/2019 8 | */ 9 | enum class WashingMachineState { 10 | 11 | ENABLED, 12 | WASHING 13 | } -------------------------------------------------------------------------------- /balking/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /bridge/src/main/kotlin/io/kommons/designpatterns/bridge/Enchantment.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.bridge 2 | 3 | /** 4 | * 마법 5 | */ 6 | interface Enchantment { 7 | 8 | fun onActivate() 9 | 10 | fun invoke() 11 | 12 | fun onDeactivate() 13 | } -------------------------------------------------------------------------------- /bridge/src/main/kotlin/io/kommons/designpatterns/bridge/Weapon.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.bridge 2 | 3 | /** 4 | * 무기 5 | */ 6 | interface Weapon { 7 | 8 | fun wield() 9 | 10 | fun swing() 11 | 12 | fun unwield() 13 | 14 | val enchantment: Enchantment 15 | } -------------------------------------------------------------------------------- /bridge/src/test/kotlin/io/kommons/designpatterns/bridge/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.bridge 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | /** 6 | * AppTest 7 | * 8 | * @author debop 9 | */ 10 | class AppTest { 11 | 12 | @Test 13 | fun `run main`() { 14 | main() 15 | } 16 | } -------------------------------------------------------------------------------- /bridge/src/test/kotlin/io/kommons/designpatterns/bridge/HammerTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.bridge 2 | 3 | import io.kommons.designpatterns.bridge.enchantments.FlyingEnchantment 4 | import io.kommons.designpatterns.bridge.weapons.Hammer 5 | import io.mockk.mockk 6 | import io.mockk.spyk 7 | import org.junit.jupiter.api.Test 8 | 9 | class HammerTest: AbstractWeaponTest() { 10 | 11 | @Test 12 | fun `test hammer`() { 13 | val hammer = spyk(Hammer(mockk(relaxUnitFun = true))) 14 | testBasicWeaponActions(hammer) 15 | } 16 | } -------------------------------------------------------------------------------- /bridge/src/test/kotlin/io/kommons/designpatterns/bridge/SwordTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.bridge 2 | 3 | import io.kommons.designpatterns.bridge.enchantments.FlyingEnchantment 4 | import io.kommons.designpatterns.bridge.weapons.Sword 5 | import io.mockk.mockk 6 | import io.mockk.spyk 7 | import org.junit.jupiter.api.Test 8 | 9 | /** 10 | * SwordTest 11 | * 12 | * @author debop 13 | */ 14 | class SwordTest: AbstractWeaponTest() { 15 | 16 | @Test 17 | fun `test sword`() { 18 | val sword = spyk(Sword(mockk(relaxUnitFun = true))) 19 | testBasicWeaponActions(sword) 20 | } 21 | } -------------------------------------------------------------------------------- /bridge/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | repositories { 2 | jcenter() 3 | } 4 | 5 | plugins { 6 | `kotlin-dsl` 7 | } 8 | 9 | kotlinDslPluginOptions { 10 | experimentalWarning.set(false) 11 | } -------------------------------------------------------------------------------- /buildSrc/build/pluginUnderTestMetadata/plugin-under-test-metadata.properties: -------------------------------------------------------------------------------- 1 | implementation-classpath=/Volumes/SanDisk/work/debop/kotlin-design-patterns/buildSrc/build/classes/java/main\:/Volumes/SanDisk/work/debop/kotlin-design-patterns/buildSrc/build/classes/groovy/main\:/Volumes/SanDisk/work/debop/kotlin-design-patterns/buildSrc/build/classes/kotlin/main\:/Volumes/SanDisk/work/debop/kotlin-design-patterns/buildSrc/build/resources/main 2 | -------------------------------------------------------------------------------- /buildSrc/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.caching = true 2 | org.gradle.parallel = true 3 | org.gradle.jvmargs = -Dfile.encoding=UTF-8 -------------------------------------------------------------------------------- /builder/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /builder/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /business-delegate/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /business-delegate/doc/business-delegate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/business-delegate/doc/business-delegate.png -------------------------------------------------------------------------------- /business-delegate/src/main/kotlin/io/kommons/designpatterns/businessdelegate/Client.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.businessdelegate 2 | 3 | class Client(val delegate: BusinessDelegate) { 4 | 5 | fun doTask() { 6 | delegate.doTask() 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /business-delegate/src/main/kotlin/io/kommons/designpatterns/businessdelegate/ServiceType.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.businessdelegate 2 | 3 | enum class ServiceType { 4 | 5 | EJB, 6 | JMS; 7 | } -------------------------------------------------------------------------------- /business-delegate/src/main/kotlin/io/kommons/designpatterns/businessdelegate/services/BusinessService.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.businessdelegate.services 2 | 3 | /** 4 | * BusinessService 5 | * 6 | * @author debop 7 | * @since 27/09/2019 8 | */ 9 | interface BusinessService { 10 | 11 | fun doProcessing() 12 | } -------------------------------------------------------------------------------- /business-delegate/src/main/kotlin/io/kommons/designpatterns/businessdelegate/services/EjbService.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.businessdelegate.services 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | /** 7 | * EjbService 8 | * 9 | * @author debop 10 | * @since 27/09/2019 11 | */ 12 | 13 | class EjbService: BusinessService { 14 | 15 | companion object: KLogging() 16 | 17 | override fun doProcessing() { 18 | log.info { "EjbService is not processing ..." } 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /business-delegate/src/main/kotlin/io/kommons/designpatterns/businessdelegate/services/JmsService.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.businessdelegate.services 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | class JmsService: BusinessService { 7 | 8 | companion object: KLogging() 9 | 10 | override fun doProcessing() { 11 | log.info { "JmsService is processing ..." } 12 | } 13 | } -------------------------------------------------------------------------------- /business-delegate/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /caching/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | api(Libraries.cache2k_core) 4 | api(Libraries.mongo_java_driver) 5 | 6 | implementation(project(":kommons-testcontainers")) 7 | } -------------------------------------------------------------------------------- /caching/etc/caching.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/caching/etc/caching.png -------------------------------------------------------------------------------- /caching/src/main/kotlin/io/kommons/designpatterns/caching/CachingConstants.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.caching 2 | 3 | const val USER_ACCOUNT = "user_accounts" 4 | const val USER_ID = "userID" 5 | const val USER_NAME = "userName" 6 | const val ADD_INFO = "additionalInfo" -------------------------------------------------------------------------------- /caching/src/main/kotlin/io/kommons/designpatterns/caching/CachingPolicy.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.caching 2 | 3 | /** 4 | * CachingPolicy 5 | * 6 | * @author debop 7 | * @since 24/09/2019 8 | */ 9 | enum class CachingPolicy(val policy: String) { 10 | 11 | THROUGH("through"), 12 | AROUND("around"), 13 | BEHIND("behind"), 14 | ASIDE("aside") 15 | 16 | } -------------------------------------------------------------------------------- /caching/src/main/kotlin/io/kommons/designpatterns/caching/UserAccount.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.caching 2 | 3 | import java.io.Serializable 4 | 5 | data class UserAccount(val userId: String, 6 | var userName: String, 7 | var additionalInfo: String): Serializable 8 | -------------------------------------------------------------------------------- /caching/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /callback/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /callback/doc/callback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/callback/doc/callback.png -------------------------------------------------------------------------------- /callback/src/main/kotlin/io/kommons/designpatterns/callback/Callback.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.callback 2 | 3 | @FunctionalInterface 4 | interface Callback { 5 | 6 | fun call() 7 | 8 | } -------------------------------------------------------------------------------- /callback/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /chain/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /chain/etc/chain.urm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/chain/etc/chain.urm.png -------------------------------------------------------------------------------- /chain/src/main/kotlin/io/kommons/designpatterns/chain/OrcKing.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.chain 2 | 3 | /** 4 | * OrcKing makes requests that are handled by the chain. 5 | */ 6 | class OrcKing { 7 | 8 | private val chain: RequestHandler 9 | 10 | init { 11 | chain = buildChain() 12 | } 13 | 14 | private fun buildChain(): RequestHandler { 15 | return OrcCommander(OrcOfficer(OrcSoldier(null))) 16 | } 17 | 18 | fun makeRequest(request: Request) { 19 | chain.handleRequest(request) 20 | } 21 | } -------------------------------------------------------------------------------- /chain/src/main/kotlin/io/kommons/designpatterns/chain/Request.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.chain 2 | 3 | class Request(val requestType: RequestType, val requestDescription: String) { 4 | 5 | private var handled: Boolean = false 6 | 7 | fun markHandled() { 8 | handled = true 9 | } 10 | 11 | val isHandled: Boolean get() = handled 12 | 13 | override fun toString(): String = requestDescription 14 | } -------------------------------------------------------------------------------- /chain/src/main/kotlin/io/kommons/designpatterns/chain/RequestType.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.chain 2 | 3 | enum class RequestType { 4 | 5 | DEFEND_CASTLE, 6 | TORTURE_PRISONER, 7 | COLLECT_TAX 8 | } -------------------------------------------------------------------------------- /chain/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /collection-pipeline/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /collection-pipeline/etc/collection-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/collection-pipeline/etc/collection-pipeline.png -------------------------------------------------------------------------------- /collection-pipeline/src/main/kotlin/io/kommons/designpatterns/collectionpipeline/Car.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.collectionpipeline 2 | 3 | /** 4 | * Car 5 | */ 6 | data class Car(val make: String, 7 | val model: String, 8 | val yearOfMake: Int, 9 | val category: Category) -------------------------------------------------------------------------------- /collection-pipeline/src/main/kotlin/io/kommons/designpatterns/collectionpipeline/CarFactory.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.collectionpipeline 2 | 3 | /** 4 | * CarFactory 5 | * 6 | * @author debop 7 | */ 8 | object CarFactory { 9 | 10 | fun createCars(): List = listOf( 11 | Car("Jeep", "Wrangler", 2011, Category.JEEP), 12 | Car("Jeep", "Comanche", 1990, Category.JEEP), 13 | Car("Dodge", "Avenger", 2010, Category.SEDAN), 14 | Car("Buick", "Cascada", 2016, Category.CONVERTIBLE), 15 | Car("Ford", "Focus", 2012, Category.SEDAN), 16 | Car("Chevrolet", "Geo Metro", 1992, Category.CONVERTIBLE) 17 | ) 18 | } -------------------------------------------------------------------------------- /collection-pipeline/src/main/kotlin/io/kommons/designpatterns/collectionpipeline/Category.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.collectionpipeline 2 | 3 | /** 4 | * Enum for the category of car 5 | */ 6 | enum class Category { 7 | JEEP, 8 | SEDAN, 9 | CONVERTIBLE 10 | } -------------------------------------------------------------------------------- /collection-pipeline/src/main/kotlin/io/kommons/designpatterns/collectionpipeline/Person.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.collectionpipeline 2 | 3 | /** 4 | * Person 5 | * 6 | * @author debop 7 | */ 8 | data class Person(val cars: List) -------------------------------------------------------------------------------- /collection-pipeline/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /command/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /command/etc/command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/command/etc/command.png -------------------------------------------------------------------------------- /command/etc/diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/command/etc/diagram.png -------------------------------------------------------------------------------- /command/src/main/kotlin/io/kommons/designpatterns/command/Command.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.command 2 | 3 | interface Command { 4 | 5 | fun execute(target: Target) 6 | 7 | fun undo() 8 | 9 | fun redo() 10 | } -------------------------------------------------------------------------------- /command/src/main/kotlin/io/kommons/designpatterns/command/Goblin.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.command 2 | 3 | /** 4 | * Goblin is the target of the spells 5 | */ 6 | class Goblin: Target() { 7 | 8 | init { 9 | size = Size.NORMAL 10 | visibility = Visibility.VISIBLE 11 | } 12 | 13 | override fun toString(): String = "Goblin" 14 | } -------------------------------------------------------------------------------- /command/src/main/kotlin/io/kommons/designpatterns/command/Size.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.command 2 | 3 | enum class Size(val title: String) { 4 | 5 | SMALL("small"), 6 | NORMAL("normal"); 7 | 8 | override fun toString(): String = title 9 | } -------------------------------------------------------------------------------- /command/src/main/kotlin/io/kommons/designpatterns/command/Target.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.command 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | /** 7 | * Base class for spell targets 8 | */ 9 | abstract class Target { 10 | 11 | companion object: KLogging() 12 | 13 | var size: Size? = null 14 | var visibility: Visibility? = null 15 | 16 | abstract override fun toString(): String 17 | 18 | fun printStatus() { 19 | log.info { "$this [size=$size] [visibility=$visibility]" } 20 | } 21 | } -------------------------------------------------------------------------------- /command/src/main/kotlin/io/kommons/designpatterns/command/Visibility.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.command 2 | 3 | enum class Visibility(val title: String) { 4 | 5 | VISIBLE("visible"), 6 | INVISIBLE("invisible"); 7 | 8 | override fun toString(): String = title 9 | } -------------------------------------------------------------------------------- /command/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /composite/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | 4 | } -------------------------------------------------------------------------------- /composite/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /converter/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | 4 | } -------------------------------------------------------------------------------- /converter/doc/converter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/converter/doc/converter.png -------------------------------------------------------------------------------- /converter/src/main/kotlin/io/kommons/designpatterns/converter/Converter.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.converter 2 | 3 | /** 4 | * Converter 5 | */ 6 | interface Converter { 7 | 8 | fun convert(source: T): U 9 | 10 | } 11 | 12 | fun converter(block: (T) -> U): Converter { 13 | return object: Converter { 14 | override fun convert(source: T): U = block.invoke(source) 15 | } 16 | } -------------------------------------------------------------------------------- /converter/src/main/kotlin/io/kommons/designpatterns/converter/DomainConverter.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.converter 2 | 3 | /** 4 | * DomainConverter 5 | */ 6 | open class DomainConverter(private val toDto: (E) -> D, 7 | private val toEntity: (D) -> E) { 8 | 9 | fun convertToDto(entity: E): D = toDto.invoke(entity) 10 | 11 | fun convertToEntity(dto: D): E = toEntity.invoke(dto) 12 | 13 | fun convertToDtos(entities: Iterable): List = 14 | entities.map { toDto.invoke(it) } 15 | 16 | fun convertToEntities(dtos: Iterable): List = 17 | dtos.map { toEntity.invoke(it) } 18 | } -------------------------------------------------------------------------------- /converter/src/main/kotlin/io/kommons/designpatterns/converter/User.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.converter 2 | 3 | /** 4 | * User 5 | */ 6 | data class User(val id: String, 7 | val firstName: String, 8 | val lastName: String, 9 | val isActive: Boolean = true) -------------------------------------------------------------------------------- /converter/src/main/kotlin/io/kommons/designpatterns/converter/UserConvertExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.converter 2 | 3 | 4 | fun User.toDto(): UserDto = UserDto(id, firstName, lastName, isActive) 5 | 6 | fun UserDto.toUser(): User = User(email, firstName, lastName, isActive) -------------------------------------------------------------------------------- /converter/src/main/kotlin/io/kommons/designpatterns/converter/UserConverter.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.converter 2 | 3 | /** 4 | * UserConverter 5 | */ 6 | class UserConverter: DomainConverter( 7 | toDto = { it.toDto() }, 8 | toEntity = { it.toUser() } 9 | ) -------------------------------------------------------------------------------- /converter/src/main/kotlin/io/kommons/designpatterns/converter/UserDto.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.converter 2 | 3 | /** 4 | * UserDto 5 | */ 6 | data class UserDto(val email: String, 7 | val firstName: String, 8 | val lastName: String, 9 | val isActive: Boolean = true) -------------------------------------------------------------------------------- /converter/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /cqrs/etc/cqrs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/cqrs/etc/cqrs.png -------------------------------------------------------------------------------- /cqrs/src/main/kotlin/io/kommons/designpatterns/cqrs/domain/model/Author.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.cqrs.domain.model 2 | 3 | import io.kommons.ToStringBuilder 4 | import javax.persistence.Entity 5 | 6 | @Entity 7 | class Author: LongEntity() { 8 | 9 | var username: String? = null 10 | var name: String? = null 11 | var email: String? = null 12 | 13 | override fun buildStringHelper(): ToStringBuilder { 14 | return super.buildStringHelper() 15 | .add("name", name) 16 | .add("email", email) 17 | } 18 | } -------------------------------------------------------------------------------- /cqrs/src/main/kotlin/io/kommons/designpatterns/cqrs/domain/repository/AuthorRepository.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.cqrs.domain.repository 2 | 3 | import io.kommons.designpatterns.cqrs.domain.model.Author 4 | import org.springframework.data.jpa.repository.JpaRepository 5 | import org.springframework.data.jpa.repository.Query 6 | import org.springframework.data.repository.query.Param 7 | import org.springframework.stereotype.Repository 8 | 9 | @Repository 10 | interface AuthorRepository: JpaRepository { 11 | 12 | @Query("select a from Author a where a.username=:username") 13 | fun findByUsername(@Param("username") username: String): Author? 14 | 15 | } -------------------------------------------------------------------------------- /cqrs/src/main/kotlin/io/kommons/designpatterns/cqrs/dto/AuthorDto.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.cqrs.dto 2 | 3 | data class AuthorDto(val name: String, val email: String, val username: String) -------------------------------------------------------------------------------- /cqrs/src/main/kotlin/io/kommons/designpatterns/cqrs/dto/BookDto.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.cqrs.dto 2 | 3 | class BookDto(val title: String, val price: Double) -------------------------------------------------------------------------------- /cqrs/src/main/kotlin/io/kommons/designpatterns/cqrs/queries/QueryService.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.cqrs.queries 2 | 3 | import io.kommons.designpatterns.cqrs.domain.model.Author 4 | import io.kommons.designpatterns.cqrs.domain.model.Book 5 | 6 | interface QueryService { 7 | 8 | fun getAuthorByUsername(username: String): Author? 9 | 10 | fun getBook(title: String): Book? 11 | 12 | fun getAuthorBooks(username: String): List 13 | 14 | fun getAuthorBooksCount(username: String): Long 15 | 16 | fun getAuthorsCount(): Long 17 | } -------------------------------------------------------------------------------- /cqrs/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.show-sql = true -------------------------------------------------------------------------------- /cqrs/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /data-bus/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | 4 | } -------------------------------------------------------------------------------- /data-bus/etc/data-bus.urm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/data-bus/etc/data-bus.urm.png -------------------------------------------------------------------------------- /data-bus/src/main/kotlin/io/kommons/designpatterns/databus/AbstractDataType.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.databus 2 | 3 | /** 4 | * AbstractDataType 5 | * 6 | * @author debop 7 | */ 8 | abstract class AbstractDataType(override var dataBus: DataBus = DataBus.getInstance()): DataType -------------------------------------------------------------------------------- /data-bus/src/main/kotlin/io/kommons/designpatterns/databus/DataType.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.databus 2 | 3 | /** 4 | * Events are sent via the Data-Bus 5 | * 6 | * @author debop 7 | */ 8 | interface DataType { 9 | 10 | var dataBus: DataBus 11 | 12 | } -------------------------------------------------------------------------------- /data-bus/src/main/kotlin/io/kommons/designpatterns/databus/Member.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.databus 2 | 3 | import java.util.function.Consumer 4 | 5 | /** 6 | * Member 7 | * 8 | * @author debop 9 | */ 10 | interface Member: Consumer { 11 | 12 | override fun accept(data: DataType) 13 | 14 | } -------------------------------------------------------------------------------- /data-bus/src/main/kotlin/io/kommons/designpatterns/databus/data/MessageData.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.databus.data 2 | 3 | import io.kommons.designpatterns.databus.AbstractDataType 4 | import io.kommons.logging.KLogging 5 | 6 | /** 7 | * MessageData 8 | * 9 | * @author debop 10 | */ 11 | class MessageData(val message: String): AbstractDataType() { 12 | 13 | companion object: KLogging() { 14 | fun of(message: String) = MessageData(message) 15 | } 16 | } -------------------------------------------------------------------------------- /data-bus/src/main/kotlin/io/kommons/designpatterns/databus/data/StartingData.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.databus.data 2 | 3 | import io.kommons.designpatterns.databus.AbstractDataType 4 | import io.kommons.logging.KLogging 5 | import java.time.LocalDateTime 6 | 7 | /** 8 | * StartingData 9 | * 10 | * @author debop 11 | */ 12 | class StartingData(val startedAt: LocalDateTime = LocalDateTime.now()): AbstractDataType() { 13 | 14 | companion object: KLogging() { 15 | fun of(startedAt: LocalDateTime) = StartingData(startedAt) 16 | } 17 | } -------------------------------------------------------------------------------- /data-bus/src/main/kotlin/io/kommons/designpatterns/databus/data/StoppingData.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.databus.data 2 | 3 | import io.kommons.designpatterns.databus.AbstractDataType 4 | import io.kommons.logging.KLogging 5 | import java.time.LocalDateTime 6 | 7 | /** 8 | * StoppingData 9 | * 10 | * @author debop 11 | */ 12 | class StoppingData(val stoppedAt: LocalDateTime): AbstractDataType() { 13 | 14 | companion object: KLogging() { 15 | fun of(stoppedAt: LocalDateTime) = StoppingData(stoppedAt) 16 | } 17 | } -------------------------------------------------------------------------------- /data-bus/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /data-locality/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | 4 | } -------------------------------------------------------------------------------- /data-locality/etc/data-locality.urm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/data-locality/etc/data-locality.urm.png -------------------------------------------------------------------------------- /data-locality/src/main/kotlin/io/kommons/designpatterns/datalocality/App.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.datalocality 2 | 3 | import io.kommons.designpatterns.datalocality.game.GameEntity 4 | import io.kommons.logging.KotlinLogging 5 | import io.kommons.logging.info 6 | 7 | class App 8 | 9 | private val log = KotlinLogging.logger { } 10 | private const val NUM_ENTITIES = 5 11 | 12 | fun main() { 13 | log.info { "Start Game Application using Data-Locality pattern" } 14 | 15 | val gameEntity = GameEntity(NUM_ENTITIES) 16 | 17 | gameEntity.start() 18 | gameEntity.update() 19 | } -------------------------------------------------------------------------------- /data-locality/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /data-mapper/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /data-mapper/etc/data-mapper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/data-mapper/etc/data-mapper.png -------------------------------------------------------------------------------- /data-mapper/src/main/kotlin/io/kommons/designpatterns/datamapper/DataMapperException.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.datamapper 2 | 3 | class DataMapperException: RuntimeException { 4 | 5 | constructor(): super() 6 | constructor(message: String): super(message) 7 | constructor(message: String, cause: Throwable?): super(message, cause) 8 | constructor(cause: Throwable?): super(cause) 9 | 10 | } -------------------------------------------------------------------------------- /data-mapper/src/main/kotlin/io/kommons/designpatterns/datamapper/StudentDataMapper.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.datamapper 2 | 3 | /** 4 | * StudentDataMapper 5 | * 6 | * @author debop 7 | */ 8 | interface StudentDataMapper { 9 | 10 | fun find(studentId: Int): Student? 11 | 12 | @Throws(DataMapperException::class) 13 | fun insert(student: Student) 14 | 15 | @Throws(DataMapperException::class) 16 | fun update(student: Student) 17 | 18 | @Throws(DataMapperException::class) 19 | fun delete(student: Student) 20 | } -------------------------------------------------------------------------------- /data-transfer-object/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /data-transfer-object/etc/data-transfer-object.urm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/data-transfer-object/etc/data-transfer-object.urm.png -------------------------------------------------------------------------------- /data-transfer-object/src/main/kotlin/io/kommons/designpatterns/dto/CustomerDto.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.dto 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * [CustomerDto] is a data transfer object POJO. Instead of sending individual information to client 7 | * We can send related information together in POJO. 8 | * Dto will not have any business logic in it. 9 | */ 10 | data class CustomerDto(val id: String, 11 | val firstName: String, 12 | val lastName: String): Serializable -------------------------------------------------------------------------------- /decorator/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | 4 | } -------------------------------------------------------------------------------- /decorator/src/main/kotlin/io/kommons/designpatterns/decorator/ClubbedTroll.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.decorator 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | /** 7 | * Kotlin에서 지원하는 class delegation 기능을 활용하면 좀 더 compact하게 구현 할 수 있습니다. 8 | */ 9 | class ClubbedTroll(private val decorated: Troll): Troll by decorated { 10 | 11 | companion object: KLogging() 12 | 13 | override fun attach() { 14 | decorated.attach() 15 | log.info { "The troll swings at you with a club!" } 16 | } 17 | 18 | override fun getAttackPower(): Int { 19 | return decorated.getAttackPower() + 10 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /decorator/src/main/kotlin/io/kommons/designpatterns/decorator/SimpleTroll.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.decorator 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | /** 7 | * SimpleTroll 8 | */ 9 | class SimpleTroll: Troll { 10 | 11 | companion object: KLogging() 12 | 13 | override fun attach() { 14 | log.info { "The troll tries to grab you!" } 15 | } 16 | 17 | override fun getAttackPower(): Int { 18 | return 10 19 | } 20 | 21 | override fun fleeBattle() { 22 | log.info { "The troll shrieks in horror and runs away!" } 23 | } 24 | } -------------------------------------------------------------------------------- /decorator/src/main/kotlin/io/kommons/designpatterns/decorator/Troll.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.decorator 2 | 3 | /** 4 | * Troll 5 | */ 6 | interface Troll { 7 | 8 | fun attach() 9 | 10 | fun getAttackPower(): Int 11 | 12 | fun fleeBattle() 13 | } -------------------------------------------------------------------------------- /decorator/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /delegation/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | 4 | } -------------------------------------------------------------------------------- /delegation/doc/delegation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/delegation/doc/delegation.png -------------------------------------------------------------------------------- /delegation/src/main/kotlin/io/kommons/designpatterns/delegation/Printer.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.delegation 2 | 3 | /** 4 | * Printer 5 | */ 6 | interface Printer { 7 | 8 | fun print(message: String) 9 | } -------------------------------------------------------------------------------- /delegation/src/main/kotlin/io/kommons/designpatterns/delegation/PrinterController.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.delegation 2 | 3 | /** 4 | * Kotlin Class delegation을 활용 5 | */ 6 | class PrinterController(printer: Printer): Printer by printer -------------------------------------------------------------------------------- /delegation/src/main/kotlin/io/kommons/designpatterns/delegation/printers/CanonPrinter.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.delegation.printers 2 | 3 | import io.kommons.designpatterns.delegation.Printer 4 | import io.kommons.logging.KLogging 5 | import io.kommons.logging.info 6 | 7 | /** 8 | * CanonPrinter 9 | */ 10 | class CanonPrinter: Printer { 11 | 12 | companion object: KLogging() 13 | 14 | override fun print(message: String) { 15 | log.info { "Canon Printer : $message" } 16 | } 17 | } -------------------------------------------------------------------------------- /delegation/src/main/kotlin/io/kommons/designpatterns/delegation/printers/EpsonPrinter.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.delegation.printers 2 | 3 | import io.kommons.designpatterns.delegation.Printer 4 | import io.kommons.logging.KLogging 5 | import io.kommons.logging.info 6 | 7 | /** 8 | * EpsonPrinter 9 | */ 10 | class EpsonPrinter: Printer { 11 | 12 | companion object: KLogging() 13 | 14 | override fun print(message: String) { 15 | log.info { "Epson Printer : $message" } 16 | } 17 | } -------------------------------------------------------------------------------- /delegation/src/main/kotlin/io/kommons/designpatterns/delegation/printers/HpPrinter.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.delegation.printers 2 | 3 | import io.kommons.designpatterns.delegation.Printer 4 | import io.kommons.logging.KLogging 5 | import io.kommons.logging.info 6 | 7 | /** 8 | * HpPrinter 9 | */ 10 | class HpPrinter: Printer { 11 | 12 | companion object: KLogging() 13 | 14 | override fun print(message: String) { 15 | log.info { "HP Printer : $message" } 16 | } 17 | } -------------------------------------------------------------------------------- /delegation/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /dirty-flag/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /dirty-flag/etc/dirty-flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/dirty-flag/etc/dirty-flag.png -------------------------------------------------------------------------------- /dirty-flag/src/main/kotlin/io/kommons/designpatterns/dirty/flag/World.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.dirty.flag 2 | 3 | class World { 4 | private val countries: List = ArrayList() 5 | private val df = DataFetcher() 6 | 7 | fun fetch(): List { 8 | val data = df.fetch() 9 | return if (data.isEmpty()) countries else data 10 | } 11 | } -------------------------------------------------------------------------------- /dirty-flag/src/test/kotlin/io/kommons/designpatterns/dirty/flag/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.dirty.flag 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | class AppTest { 6 | 7 | @Test 8 | fun test() { 9 | App.main() 10 | } 11 | } -------------------------------------------------------------------------------- /dirty-flag/src/test/kotlin/io/kommons/designpatterns/dirty/flag/DirtyFlagTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.dirty.flag 2 | 3 | import org.junit.Assert 4 | import org.junit.jupiter.api.Test 5 | 6 | class DirtyFlagTest { 7 | 8 | @Test 9 | fun `Is dirty`() { 10 | val df = DataFetcher() 11 | val countries = df.fetch() 12 | Assert.assertFalse(countries.isEmpty()) 13 | } 14 | 15 | @Test 16 | fun `Is not dirty`() { 17 | val df = DataFetcher() 18 | df.fetch() 19 | val countries = df.fetch() 20 | Assert.assertTrue(countries.isEmpty()) 21 | } 22 | } -------------------------------------------------------------------------------- /dirty-flag/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /double-buffer/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /double-buffer/etc/double-buffer.urm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/double-buffer/etc/double-buffer.urm.png -------------------------------------------------------------------------------- /double-buffer/src/main/kotlin/io/kommons/designpatterns/doublebuffer/Pixel.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.doublebuffer 2 | 3 | enum class Pixel(val color: Int) { 4 | 5 | WHITE(0), BLACK(1) 6 | 7 | } -------------------------------------------------------------------------------- /double-buffer/src/test/kotlin/io/kommons/designpatterns/doublebuffer/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.doublebuffer 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | class AppTest { 6 | 7 | @Test 8 | fun `run main`() { 9 | main() 10 | } 11 | } -------------------------------------------------------------------------------- /double-buffer/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /event-aggregator/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /event-aggregator/etc/classes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/event-aggregator/etc/classes.png -------------------------------------------------------------------------------- /event-aggregator/src/main/kotlin/io/kommons/designpatterns/event/aggregator/Event.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.aggregator 2 | 3 | /** 4 | * Event 5 | * 6 | * @author debop 7 | */ 8 | enum class Event(val description: String) { 9 | 10 | STARK_SIGHTED("Stark sighted"), 11 | WARSHIPS_APPROACHING("Warships approaching"), 12 | TRAITOR_DETECTED("Traitor detected"); 13 | 14 | override fun toString(): String = description 15 | 16 | } -------------------------------------------------------------------------------- /event-aggregator/src/main/kotlin/io/kommons/designpatterns/event/aggregator/EventObserver.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.aggregator 2 | 3 | /** 4 | * Observers of events 5 | * 6 | * @author debop 7 | */ 8 | interface EventObserver { 9 | 10 | fun onEvent(evt: Event?) 11 | 12 | } -------------------------------------------------------------------------------- /event-aggregator/src/main/kotlin/io/kommons/designpatterns/event/aggregator/KingsHand.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.aggregator 2 | 3 | import io.kommons.logging.KLogging 4 | 5 | /** 6 | * KingsHand observes events from multiple sources and delivers them to listeners. 7 | * 8 | * @author debop 9 | */ 10 | class KingsHand(vararg obs: EventObserver): EventEmitter(*obs), EventObserver { 11 | 12 | companion object: KLogging() 13 | 14 | override fun onEvent(evt: Event?) { 15 | notifyObservers(evt) 16 | } 17 | 18 | override fun timePasses(day: Weekday) { 19 | // NOP 20 | } 21 | } -------------------------------------------------------------------------------- /event-aggregator/src/main/kotlin/io/kommons/designpatterns/event/aggregator/Weekday.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.aggregator 2 | 3 | /** 4 | * Weekday enumeration 5 | * 6 | * @author debop 7 | */ 8 | enum class Weekday(val description: String) { 9 | MONDAY("Monday"), 10 | TUESDAY("Tuesday"), 11 | WEDNESDAY("Wednesday"), 12 | THURSDAY("Thursday"), 13 | FRIDAY("Friday"), 14 | SATURDAY("Saturday"), 15 | SUNDAY("Sunday"); 16 | 17 | override fun toString(): String = description 18 | 19 | } -------------------------------------------------------------------------------- /event-aggregator/src/main/kotlin/io/kommons/designpatterns/event/aggregator/observers/KingJoffrey.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.aggregator.observers 2 | 3 | import io.kommons.designpatterns.event.aggregator.Event 4 | import io.kommons.designpatterns.event.aggregator.EventObserver 5 | import io.kommons.logging.KLogging 6 | import io.kommons.logging.info 7 | 8 | /** 9 | * KingJoffrey observes events from [KingsHand]. 10 | * 11 | * @author debop 12 | */ 13 | class KingJoffrey: EventObserver { 14 | 15 | companion object: KLogging() 16 | 17 | override fun onEvent(evt: Event?) { 18 | log.info { "Received event from the King's Hand: $evt" } 19 | } 20 | } -------------------------------------------------------------------------------- /event-aggregator/src/test/kotlin/io/kommons/designpatterns/event/aggregator/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.aggregator 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | /** 6 | * AppTest 7 | * 8 | * @author debop 9 | */ 10 | class AppTest { 11 | 12 | @Test 13 | fun `run app`() { 14 | main() 15 | } 16 | } -------------------------------------------------------------------------------- /event-aggregator/src/test/kotlin/io/kommons/designpatterns/event/aggregator/EventTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.aggregator 2 | 3 | import org.amshove.kluent.shouldEqual 4 | import org.junit.jupiter.api.Test 5 | 6 | class EventTest { 7 | 8 | @Test 9 | fun `event to string`() { 10 | Event.values().forEach { event -> 11 | event.toString() shouldEqual event.name.toLowerCase().replace("_", " ").capitalize() 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /event-aggregator/src/test/kotlin/io/kommons/designpatterns/event/aggregator/WeekdayTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.aggregator 2 | 3 | import org.amshove.kluent.shouldEqual 4 | import org.junit.jupiter.api.Test 5 | 6 | /** 7 | * WeekdayTest 8 | * 9 | * @author debop 10 | */ 11 | class WeekdayTest { 12 | 13 | @Test 14 | fun `weekday toString`() { 15 | Weekday.values().forEach { weekday -> 16 | weekday.toString().toUpperCase() shouldEqual weekday.name 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /event-aggregator/src/test/kotlin/io/kommons/designpatterns/event/aggregator/emitters/LordVarysTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.aggregator.emitters 2 | 3 | import io.kommons.designpatterns.event.aggregator.Event 4 | import io.kommons.designpatterns.event.aggregator.Weekday 5 | 6 | /** 7 | * LoadVarysTest 8 | * 9 | * @author debop 10 | */ 11 | class LordVarysTest: AbstractEventEmitterTest(Weekday.SATURDAY, 12 | Event.TRAITOR_DETECTED, 13 | { LoadVarys(it) }, 14 | { LoadVarys() }) -------------------------------------------------------------------------------- /event-aggregator/src/test/kotlin/io/kommons/designpatterns/event/aggregator/emitters/ScoutTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.aggregator.emitters 2 | 3 | import io.kommons.designpatterns.event.aggregator.Event 4 | import io.kommons.designpatterns.event.aggregator.Weekday 5 | 6 | class ScoutTest: AbstractEventEmitterTest(Weekday.TUESDAY, 7 | Event.WARSHIPS_APPROACHING, 8 | { observer -> Scout(observer) }, 9 | { Scout() }) -------------------------------------------------------------------------------- /event-aggregator/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /event-asynchronous/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | implementation(Libraries.kotlinx_coroutines_jdk8) 4 | implementation(Libraries.kotlinx_coroutines_test) 5 | 6 | } -------------------------------------------------------------------------------- /event-asynchronous/etc/event-asynchronous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/event-asynchronous/etc/event-asynchronous.png -------------------------------------------------------------------------------- /event-asynchronous/src/main/kotlin/io/kommons/designpatterns/event/ThreadCompleteListener.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event 2 | 3 | /** 4 | * Interface with listener behaviour related to Thread Completion. 5 | * 6 | * @author debop 7 | */ 8 | interface ThreadCompleteListener { 9 | 10 | fun completedEventHandler(eventId: Int) 11 | 12 | } -------------------------------------------------------------------------------- /event-asynchronous/src/main/kotlin/io/kommons/designpatterns/event/async/IEvent.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.async 2 | 3 | /** 4 | * Events that fulfill the start stop and list out current status behaviour follow this interface 5 | * 6 | * @author debop 7 | */ 8 | interface IEvent { 9 | 10 | val isSynchronous: Boolean 11 | 12 | fun start() 13 | 14 | fun stop() 15 | 16 | fun status() 17 | 18 | } -------------------------------------------------------------------------------- /event-asynchronous/src/main/kotlin/io/kommons/designpatterns/event/coroutines/ICoEvent.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.coroutines 2 | 3 | /** 4 | * ICoEvent 5 | * 6 | * @author debop 7 | */ 8 | interface ICoEvent { 9 | 10 | suspend fun start() 11 | 12 | suspend fun stop() 13 | 14 | suspend fun status() 15 | } -------------------------------------------------------------------------------- /event-asynchronous/src/main/kotlin/io/kommons/designpatterns/event/exception/EventDoesNotExistException.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.exception 2 | 3 | /** 4 | * Custom Exception Class for Non Existent Event 5 | * 6 | * @author debop 7 | */ 8 | class EventDoesNotExistException: RuntimeException { 9 | 10 | constructor(): super() 11 | constructor(message: String): super(message) 12 | constructor(message: String, cause: Throwable?): super(message, cause) 13 | constructor(cause: Throwable?): super(cause) 14 | 15 | } -------------------------------------------------------------------------------- /event-asynchronous/src/main/kotlin/io/kommons/designpatterns/event/exception/InvalidOperationException.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.exception 2 | 3 | /** 4 | * InvalidOperationException 5 | * 6 | * @author debop 7 | */ 8 | class InvalidOperationException: RuntimeException { 9 | 10 | constructor(): super() 11 | constructor(message: String): super(message) 12 | constructor(message: String, cause: Throwable?): super(message, cause) 13 | constructor(cause: Throwable?): super(cause) 14 | 15 | } -------------------------------------------------------------------------------- /event-asynchronous/src/main/kotlin/io/kommons/designpatterns/event/exception/LongRunningEventException.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.exception 2 | 3 | /** 4 | * Type of Exception raised when the Operation being invoked is Long Running 5 | * 6 | * @author debop 7 | */ 8 | class LongRunningEventException: RuntimeException { 9 | 10 | constructor(): super() 11 | constructor(message: String): super(message) 12 | constructor(message: String, cause: Throwable?): super(message, cause) 13 | constructor(cause: Throwable?): super(cause) 14 | 15 | } -------------------------------------------------------------------------------- /event-asynchronous/src/main/kotlin/io/kommons/designpatterns/event/exception/MaxNumOfEventsAllowedException.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.event.exception 2 | 3 | /** 4 | * Type of Exception raised when the max number of allowed events is exceeded 5 | * 6 | * @author debop 7 | */ 8 | class MaxNumOfEventsAllowedException: RuntimeException { 9 | 10 | constructor(): super() 11 | constructor(message: String): super(message) 12 | constructor(message: String, cause: Throwable?): super(message, cause) 13 | constructor(cause: Throwable?): super(cause) 14 | 15 | } -------------------------------------------------------------------------------- /event-asynchronous/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /event-driven-architecture/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /event-driven-architecture/etc/eda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/event-driven-architecture/etc/eda.png -------------------------------------------------------------------------------- /event-driven-architecture/src/main/kotlin/io/kommons/designpatterns/eda/Events.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.eda 2 | 3 | import io.kommons.designpatterns.eda.framework.Event 4 | 5 | class UserCreatedEvent(val user: User): Event 6 | 7 | class UserUpdatedEvent(val user: User): Event -------------------------------------------------------------------------------- /event-driven-architecture/src/main/kotlin/io/kommons/designpatterns/eda/User.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.eda 2 | 3 | /** 4 | * This {@link User} class is a basic pojo used to demonstrate user data sent along with the {@link 5 | * UserCreatedEvent} and {@link UserUpdatedEvent} events. 6 | */ 7 | data class User(val username: String) -------------------------------------------------------------------------------- /event-driven-architecture/src/main/kotlin/io/kommons/designpatterns/eda/framework/Event.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.eda.framework 2 | 3 | /** 4 | * A [Event] is an object with a specific type that is associated to a specific [Handler] 5 | */ 6 | interface Event { 7 | 8 | /** 9 | * Returns the message type as a {@link Class} object. In this example the message type is used to 10 | * handle events by their type. 11 | * 12 | * @return the message type as a {@link Class}. 13 | */ 14 | @JvmDefault 15 | val type: Class 16 | get() = javaClass 17 | 18 | } -------------------------------------------------------------------------------- /event-driven-architecture/src/test/kotlin/io/kommons/designpatterns/eda/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.eda 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | class AppTest { 6 | 7 | @Test 8 | fun `run event dispatcher`() { 9 | main() 10 | } 11 | } -------------------------------------------------------------------------------- /event-driven-architecture/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /event-queue/etc/Bass-Drum-1.aif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/event-queue/etc/Bass-Drum-1.aif -------------------------------------------------------------------------------- /event-queue/etc/Bass-Drum-1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/event-queue/etc/Bass-Drum-1.wav -------------------------------------------------------------------------------- /event-queue/etc/Closed-Hi-Hat-1.aif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/event-queue/etc/Closed-Hi-Hat-1.aif -------------------------------------------------------------------------------- /event-queue/etc/Closed-Hi-Hat-1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/event-queue/etc/Closed-Hi-Hat-1.wav -------------------------------------------------------------------------------- /event-queue/etc/model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/event-queue/etc/model.png -------------------------------------------------------------------------------- /event-queue/src/main/kotlin/io/kommons/designpatterns/eventqueue/PlayMessage.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.eventqueue 2 | 3 | import javax.sound.sampled.AudioInputStream 4 | 5 | class PlayMessage(var stream: AudioInputStream, 6 | var volume: Float = 12.0F) -------------------------------------------------------------------------------- /event-queue/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /event-sourcing/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | implementation(Libraries.gson) 4 | 5 | } -------------------------------------------------------------------------------- /event-sourcing/etc/event-sourcing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/event-sourcing/etc/event-sourcing.png -------------------------------------------------------------------------------- /event-sourcing/src/main/kotlin/io/kommons/designpatterns/eventsourcing/App.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.eventsourcing 2 | 3 | import io.kommons.logging.KLogging 4 | 5 | /** 6 | * App 7 | * 8 | * @author debop 9 | * @since 19. 9. 18. 10 | */ 11 | class App { 12 | 13 | companion object: KLogging() { 14 | 15 | const val ACCOUNT_OF_DAENERYS = 1 16 | const val ACCOUNT_OF_JON = 2 17 | } 18 | } -------------------------------------------------------------------------------- /event-sourcing/src/main/kotlin/io/kommons/designpatterns/eventsourcing/event/AbstractDomainEvent.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.eventsourcing.event 2 | 3 | /** 4 | * AbstractDomainEvent 5 | * 6 | * @author debop 7 | * @since 19. 9. 18. 8 | */ 9 | abstract class AbstractDomainEvent(override val sequenceId: Long, 10 | override val createdTime: Long, 11 | override val eventClassName: String): DomainEvent { 12 | 13 | override var isRealTime: Boolean = true 14 | 15 | } -------------------------------------------------------------------------------- /event-sourcing/src/main/kotlin/io/kommons/designpatterns/eventsourcing/event/DomainEvent.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.eventsourcing.event 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * DomainEvent 7 | * 8 | * @author debop 9 | * @since 19. 9. 18. 10 | */ 11 | interface DomainEvent: Serializable { 12 | 13 | val sequenceId: Long 14 | 15 | val createdTime: Long 16 | 17 | val eventClassName: String 18 | 19 | var isRealTime: Boolean 20 | 21 | fun process() 22 | 23 | } -------------------------------------------------------------------------------- /event-sourcing/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /execute-around/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | 4 | } -------------------------------------------------------------------------------- /execute-around/etc/execute-around.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/execute-around/etc/execute-around.png -------------------------------------------------------------------------------- /execute-around/src/main/kotlin/io/kommons/designpatterns/execute/around/App.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.execute.around 2 | 3 | class App 4 | 5 | fun main() { 6 | 7 | SimpleFileWriter("testfile.txt") { writer -> 8 | writer.write("Hello") 9 | writer.append(" ") 10 | writer.append("there!") 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /execute-around/src/main/kotlin/io/kommons/designpatterns/execute/around/FileWriterAction.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.execute.around 2 | 3 | import java.io.FileWriter 4 | 5 | /** 6 | * Interface for specifying what to do with the file resource. 7 | * 8 | * @author debop 9 | */ 10 | @FunctionalInterface 11 | interface FileWriterAction { 12 | 13 | fun writeFile(writer: FileWriter) 14 | 15 | } -------------------------------------------------------------------------------- /execute-around/src/main/kotlin/io/kommons/designpatterns/execute/around/SimpleFileWriter.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.execute.around 2 | 3 | import java.io.FileWriter 4 | 5 | /** 6 | * SimpleFileWriter handles opening and closing file for the user. The user only has to specify what 7 | * to do with the file resource through {@link FileWriterAction} parameter. 8 | * 9 | * @author debop 10 | */ 11 | class SimpleFileWriter(filename: String, action: (FileWriter) -> Unit) { 12 | 13 | init { 14 | FileWriter(filename).use { writer -> 15 | action(writer) 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /execute-around/src/main/kotlin/io/kommons/designpatterns/execute/around/WithFileWriter.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.execute.around 2 | 3 | import java.io.FileWriter 4 | 5 | /** 6 | * Kotlin의 receiver를 이용한 함수를 이용하여 execute-around 패턴을 구현합니다. 7 | * 8 | * @author debop 9 | */ 10 | fun withFileWriter(filename: String, action: FileWriter.() -> Unit) { 11 | FileWriter(filename).use { 12 | action(it) 13 | } 14 | } -------------------------------------------------------------------------------- /execute-around/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /extension-objects/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | api(Libraries.logback) 3 | } -------------------------------------------------------------------------------- /extension-objects/etc/extension-objects.urm.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | @enduml -------------------------------------------------------------------------------- /extension-objects/etc/extension_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/extension-objects/etc/extension_obj.png -------------------------------------------------------------------------------- /extension-objects/src/main/kotlin/io/kommons/designpatterns/extensionobjects/Extensions.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.extensionobjects 2 | 3 | interface UnitExtension 4 | 5 | interface SoldierExtension: UnitExtension { 6 | fun soldierReady() 7 | } 8 | 9 | interface SergeantExtension: UnitExtension { 10 | fun sergeantReady() 11 | } 12 | 13 | interface CommanderExtension: UnitExtension { 14 | fun commanderReady() 15 | } -------------------------------------------------------------------------------- /extension-objects/src/main/kotlin/io/kommons/designpatterns/extensionobjects/KotlinExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.extensionobjects 2 | 3 | import io.kommons.logging.KotlinLogging 4 | import io.kommons.logging.info 5 | 6 | private val log = KotlinLogging.logger { } 7 | 8 | fun Soldier.ready() { 9 | log.info { "[Soldier] ${unit.name} is ready in Kotlin extension method." } 10 | } 11 | 12 | fun Sergeant.ready() { 13 | log.info { "[Sergeant] ${unit.name} is ready in Kotlin extension method." } 14 | } 15 | 16 | fun Commander.ready() { 17 | log.info { "[Commander] ${unit.name} is ready in Kotlin extension method." } 18 | } -------------------------------------------------------------------------------- /extension-objects/src/test/kotlin/io/kommons/designpatterns/extensionobjects/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.extensionobjects 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | class AppTest { 6 | 7 | @Test 8 | fun `run app`() { 9 | main() 10 | } 11 | } -------------------------------------------------------------------------------- /extension-objects/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /facade/etc/facade.urm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/facade/etc/facade.urm.png -------------------------------------------------------------------------------- /facade/src/main/kotlin/io/kommons/designpatterns/facade/App.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.facade 2 | 3 | class App 4 | 5 | fun main() { 6 | DwarvenGoldmineFacade().apply { 7 | startNewDay() 8 | digOutGold() 9 | endDay() 10 | } 11 | } -------------------------------------------------------------------------------- /facade/src/main/kotlin/io/kommons/designpatterns/facade/DwarvenCartOperator.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.facade 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | class DwarvenCartOperator: DwarvenMineWorker { 7 | 8 | companion object: KLogging() 9 | 10 | override val name: String = "Dwarf cart operator" 11 | 12 | 13 | override fun work() { 14 | log.info { "$name moves gold chunks out of the mine." } 15 | } 16 | } -------------------------------------------------------------------------------- /facade/src/main/kotlin/io/kommons/designpatterns/facade/DwarvenGoldDigger.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.facade 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | class DwarvenGoldDigger: DwarvenMineWorker { 7 | 8 | companion object: KLogging() 9 | 10 | override val name: String = "Dwarf gold digger" 11 | 12 | 13 | override fun work() { 14 | log.info { "$name digs for gold." } 15 | } 16 | } -------------------------------------------------------------------------------- /facade/src/main/kotlin/io/kommons/designpatterns/facade/DwarvenTunnelDigger.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.facade 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | class DwarvenTunnelDigger: DwarvenMineWorker { 7 | 8 | companion object: KLogging() 9 | 10 | override val name: String = "Dwarven tunnel digger" 11 | 12 | override fun work() { 13 | log.info { "$name creates another promising tunnel." } 14 | } 15 | } -------------------------------------------------------------------------------- /facade/src/test/kotlin/io/kommons/designpatterns/facade/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.facade 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | class AppTest { 6 | 7 | @Test 8 | fun `run app`() { 9 | main() 10 | } 11 | } -------------------------------------------------------------------------------- /facade/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /factory-kit/etc/factory-kit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/factory-kit/etc/factory-kit.png -------------------------------------------------------------------------------- /factory-kit/src/main/kotlin/io/kommons/designpatterns/factorykit/App.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.factorykit 2 | 3 | import io.kommons.logging.KotlinLogging 4 | import io.kommons.logging.info 5 | 6 | class App 7 | 8 | private val log = KotlinLogging.logger { } 9 | 10 | fun main() { 11 | val factory = WeaponFactory.factory { builder -> 12 | builder.add(WeaponType.SWORD, ::Sword) 13 | builder.add(WeaponType.AXE, ::Axe) 14 | builder.add(WeaponType.SPEAR, ::Spear) 15 | builder.add(WeaponType.BOW, ::Bow) 16 | } 17 | 18 | val axe = factory.create(WeaponType.AXE) 19 | log.info { "$axe" } 20 | } -------------------------------------------------------------------------------- /factory-kit/src/main/kotlin/io/kommons/designpatterns/factorykit/Builder.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.factorykit 2 | 3 | interface Builder { 4 | 5 | fun add(name: WeaponType, supplier: () -> Weapon) 6 | 7 | } 8 | 9 | fun builderOf(adder: (name: WeaponType, supplier: () -> Weapon) -> Unit): Builder { 10 | return object: Builder { 11 | override fun add(name: WeaponType, supplier: () -> Weapon) { 12 | adder.invoke(name, supplier) 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /factory-kit/src/main/kotlin/io/kommons/designpatterns/factorykit/Weapons.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.factorykit 2 | 3 | enum class WeaponType { 4 | SWORD, AXE, BOW, SPEAR 5 | } 6 | 7 | interface Weapon 8 | 9 | class Sword: Weapon { 10 | override fun toString(): String = "Sword" 11 | } 12 | 13 | class Axe: Weapon { 14 | override fun toString(): String = "Axe" 15 | } 16 | 17 | class Bow: Weapon { 18 | override fun toString(): String = "Bow" 19 | } 20 | 21 | class Spear: Weapon { 22 | override fun toString(): String = "Spear" 23 | } 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /factory-kit/src/test/kotlin/io/kommons/designpatterns/factorykit/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.factorykit 2 | 3 | import io.kommons.logging.KLogging 4 | import org.junit.jupiter.api.Test 5 | 6 | class AppTest { 7 | 8 | companion object: KLogging() 9 | 10 | @Test 11 | fun `run app`() { 12 | main() 13 | } 14 | } -------------------------------------------------------------------------------- /factory-kit/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /factory-method/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /factory-method/etc/diagram1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/factory-method/etc/diagram1.png -------------------------------------------------------------------------------- /factory-method/src/main/kotlin/io/kommons/designpatterns/factory/method/blacksmith/Blacksmith.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.factory.method.blacksmith 2 | 3 | import io.kommons.designpatterns.factory.method.weapon.Weapon 4 | import io.kommons.designpatterns.factory.method.weapon.WeaponType 5 | 6 | /** 7 | * Blacksmith 8 | * 9 | * @author debop 10 | */ 11 | interface Blacksmith { 12 | 13 | fun manufactureWeapon(weaponType: WeaponType): Weapon 14 | } -------------------------------------------------------------------------------- /factory-method/src/main/kotlin/io/kommons/designpatterns/factory/method/weapon/ElfWeapon.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.factory.method.weapon 2 | 3 | /** 4 | * ElfWeapon 5 | * 6 | * @author debop 7 | */ 8 | class ElfWeapon(override val weaponType: WeaponType): Weapon { 9 | 10 | override fun toString(): String = "Elven $weaponType" 11 | 12 | } -------------------------------------------------------------------------------- /factory-method/src/main/kotlin/io/kommons/designpatterns/factory/method/weapon/OrcWeapon.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.factory.method.weapon 2 | 3 | /** 4 | * OrcWeapon 5 | * 6 | * @author debop 7 | */ 8 | class OrcWeapon(override val weaponType: WeaponType): Weapon { 9 | 10 | override fun toString(): String = "Orc $weaponType" 11 | 12 | } -------------------------------------------------------------------------------- /factory-method/src/main/kotlin/io/kommons/designpatterns/factory/method/weapon/Weapon.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.factory.method.weapon 2 | 3 | /** 4 | * Weapon 5 | * 6 | * @author debop 7 | */ 8 | interface Weapon { 9 | 10 | val weaponType: WeaponType 11 | } -------------------------------------------------------------------------------- /factory-method/src/main/kotlin/io/kommons/designpatterns/factory/method/weapon/WeaponType.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.factory.method.weapon 2 | 3 | /** 4 | * WeaponType 5 | * 6 | * @author debop 7 | */ 8 | enum class WeaponType(val title: String) { 9 | 10 | SHORT_SWORD("short sword"), 11 | SPEAR("spear"), 12 | AXE("axe"), 13 | UNDEFINED(""); 14 | 15 | override fun toString(): String = title 16 | } -------------------------------------------------------------------------------- /factory-method/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /feature-toggle/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /feature-toggle/etc/feature-toggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/feature-toggle/etc/feature-toggle.png -------------------------------------------------------------------------------- /feature-toggle/src/main/kotlin/io/kommons/designpatterns/featuretoggle/pattern/Service.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.featuretoggle.pattern 2 | 3 | import io.kommons.designpatterns.featuretoggle.User 4 | 5 | interface Service { 6 | 7 | /** 8 | * Generates a welcome message for the passed user. 9 | * 10 | * @param user the [User] to be used if the message is to be personalised. 11 | * @return Generated string welcome message 12 | */ 13 | fun getWelcomeMessage(user: User): String 14 | 15 | /** 16 | * Returns if the welcome message to be displayed will be the enhanced version. 17 | */ 18 | val isEnhanced: Boolean 19 | } -------------------------------------------------------------------------------- /feature-toggle/src/main/kotlin/io/kommons/designpatterns/featuretoggle/pattern/TieredFeatureToggleVersion.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.featuretoggle.pattern 2 | 3 | import io.kommons.designpatterns.featuretoggle.User 4 | import io.kommons.designpatterns.featuretoggle.UserGroup 5 | 6 | class TieredFeatureToggleVersion: Service { 7 | 8 | override fun getWelcomeMessage(user: User): String = when { 9 | UserGroup.isPaid(user) -> "You're amazing ${user.name}. Thanks for paying for this awesome software." 10 | else -> "I suppose you can use this software." 11 | } 12 | 13 | override val isEnhanced: Boolean = true 14 | 15 | } -------------------------------------------------------------------------------- /feature-toggle/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.daemon = true 2 | org.gradle.parallel = true 3 | org.gradle.caching = true 4 | org.gradle.jvmargs = -server -Xms1g -Xmx4g -XX:ReservedCodeCacheSize=240m -Dfile.encoding=UTF-8 5 | 6 | kotlin.incremental = true 7 | kotlin.parallel.tasks.in.project = true 8 | kapt.use.worker.api = true 9 | java.incremental = true 10 | 11 | # 12 | # project version 13 | # 14 | projectGroup = io.kommons 15 | baseVersion = 0.1.0 16 | snapshotVersion = -SNAPSHOT -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase = GRADLE_USER_HOME 2 | distributionPath = wrapper/dists 3 | distributionUrl = https\://services.gradle.org/distributions/gradle-7.0-all.zip 4 | zipStoreBase = GRADLE_USER_HOME 5 | zipStorePath = wrapper/dists 6 | -------------------------------------------------------------------------------- /guarded-suspension/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pattern 3 | title: Guarded Suspension 4 | folder: guarded-suspension 5 | permalink: /patterns/guarded-suspension/ 6 | categories: Concurrency 7 | tags: 8 | - Java 9 | - Difficulty-Beginner 10 | --- 11 | 12 | ## Intent 13 | Use Guarded suspension pattern to handle a situation when you want to execute a method on object which is not in a proper state. 14 | 15 | ![Guarded Suspension diagram](./doc/guarded-suspension.png) 16 | 17 | ## Applicability 18 | Use Guarded Suspension pattern when the developer knows that the method execution will be blocked for a finite period of time 19 | 20 | ## Related patterns 21 | * Balking 22 | -------------------------------------------------------------------------------- /guarded-suspension/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | implementation(Libraries.kotlinx_coroutines_jdk8) 4 | 5 | } -------------------------------------------------------------------------------- /guarded-suspension/doc/guarded-suspension.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/guarded-suspension/doc/guarded-suspension.png -------------------------------------------------------------------------------- /guarded-suspension/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /interpreter/etc/interpreter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/interpreter/etc/interpreter.png -------------------------------------------------------------------------------- /interpreter/etc/interpreter_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/interpreter/etc/interpreter_1.png -------------------------------------------------------------------------------- /interpreter/src/main/kotlin/io/kommons/designpatterns/interpreter/Expression.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.interpreter 2 | 3 | abstract class Expression { 4 | 5 | abstract fun interpret(): Int 6 | 7 | abstract override fun toString(): String 8 | } -------------------------------------------------------------------------------- /interpreter/src/main/kotlin/io/kommons/designpatterns/interpreter/MinusExpression.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.interpreter 2 | 3 | class MinusExpression(private val leftExpr: Expression, 4 | private val rightExpr: Expression): Expression() { 5 | 6 | override fun interpret(): Int = 7 | leftExpr.interpret() - rightExpr.interpret() 8 | 9 | override fun toString(): String = "-" 10 | 11 | } -------------------------------------------------------------------------------- /interpreter/src/main/kotlin/io/kommons/designpatterns/interpreter/MultiplyExpression.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.interpreter 2 | 3 | class MultiplyExpression(private val leftExpr: Expression, 4 | private val rightExpr: Expression): Expression() { 5 | 6 | override fun interpret(): Int = 7 | leftExpr.interpret() * rightExpr.interpret() 8 | 9 | override fun toString(): String = "*" 10 | } -------------------------------------------------------------------------------- /interpreter/src/main/kotlin/io/kommons/designpatterns/interpreter/NumberExpression.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.interpreter 2 | 3 | class NumberExpression(private val number: Int): Expression() { 4 | 5 | constructor(s: String): this(s.toInt()) 6 | 7 | override fun interpret(): Int = number 8 | 9 | override fun toString(): String = "number" 10 | } -------------------------------------------------------------------------------- /interpreter/src/main/kotlin/io/kommons/designpatterns/interpreter/PlusExpression.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.interpreter 2 | 3 | class PlusExpression(private val leftExpr: Expression, 4 | private val rightExpr: Expression): Expression() { 5 | 6 | override fun interpret(): Int = 7 | leftExpr.interpret() + rightExpr.interpret() 8 | 9 | override fun toString(): String = "+" 10 | } -------------------------------------------------------------------------------- /interpreter/src/test/kotlin/io/kommons/designpatterns/interpreter/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.interpreter 2 | 3 | import io.kommons.logging.KLogging 4 | import org.junit.jupiter.api.Test 5 | 6 | class AppTest { 7 | 8 | companion object: KLogging() 9 | 10 | @Test 11 | fun `run main`() { 12 | main() 13 | } 14 | } -------------------------------------------------------------------------------- /interpreter/src/test/kotlin/io/kommons/designpatterns/interpreter/MinusExpressionTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.interpreter 2 | 3 | import org.junit.jupiter.params.provider.Arguments 4 | import java.util.stream.Stream 5 | 6 | class MinusExpressionTest: ExpressionTest("-", ::MinusExpression) { 7 | 8 | override fun expressionProvider(): Stream = 9 | prepareParameters { left, right -> left - right } 10 | 11 | } -------------------------------------------------------------------------------- /interpreter/src/test/kotlin/io/kommons/designpatterns/interpreter/MultiplyExpressionTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.interpreter 2 | 3 | import org.junit.jupiter.params.provider.Arguments 4 | import java.util.stream.Stream 5 | 6 | class MultiplyExpressionTest: ExpressionTest("*", ::MultiplyExpression) { 7 | 8 | override fun expressionProvider(): Stream = 9 | prepareParameters { left, right -> left * right } 10 | 11 | } -------------------------------------------------------------------------------- /interpreter/src/test/kotlin/io/kommons/designpatterns/interpreter/PlusExpressionTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.interpreter 2 | 3 | import org.junit.jupiter.params.provider.Arguments 4 | import java.util.stream.Stream 5 | 6 | class PlusExpressionTest: ExpressionTest("+", ::PlusExpression) { 7 | 8 | override fun expressionProvider(): Stream = 9 | prepareParameters { left, right -> left + right } 10 | 11 | } -------------------------------------------------------------------------------- /interpreter/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /kommons-core/src/main/kotlin/io/kommons/BinaryStringFormat.kt: -------------------------------------------------------------------------------- 1 | package io.kommons 2 | 3 | /** 4 | * BinaryStringFormat 5 | * 6 | * @author debop 7 | */ 8 | enum class BinaryStringFormat { 9 | 10 | /** Base64 encoding */ 11 | Base64, 12 | 13 | /** HexDecimal encoding */ 14 | HexDecimal; 15 | 16 | 17 | companion object { 18 | 19 | fun valueOf(ordinal: Int): BinaryStringFormat = when (ordinal) { 20 | 0 -> Base64 21 | 1 -> HexDecimal 22 | else -> throw IllegalArgumentException("Not supported ordianl value. ordinal=$ordinal") 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /kommons-core/src/main/kotlin/io/kommons/KommonsException.kt: -------------------------------------------------------------------------------- 1 | package io.kommons 2 | 3 | /** 4 | * KommonsException 5 | * 6 | * @author debop 7 | */ 8 | open class KommonsException: RuntimeException { 9 | constructor(): super() 10 | constructor(msg: String): super(msg) 11 | constructor(msg: String, cause: Throwable?): super(msg, cause) 12 | constructor(cause: Throwable?): super(cause) 13 | } -------------------------------------------------------------------------------- /kommons-core/src/main/kotlin/io/kommons/NotSupportedException.kt: -------------------------------------------------------------------------------- 1 | package io.kommons 2 | 3 | /** 4 | * NotSupportedException 5 | * 6 | * @author debop 7 | */ 8 | open class NotSupportedException: KommonsException { 9 | constructor(): super() 10 | constructor(msg: String): super(msg) 11 | constructor(msg: String, cause: Throwable?): super(msg, cause) 12 | constructor(cause: Throwable?): super(cause) 13 | } -------------------------------------------------------------------------------- /kommons-core/src/main/kotlin/io/kommons/ObjectWrapper.kt: -------------------------------------------------------------------------------- 1 | package io.kommons 2 | 3 | /** 4 | * Serializable 이 아닌 객체를 Wrapping 하여 직렬화가 가능하도록 합니다. 5 | */ 6 | data class ObjectWrapper(val value: Any?): AbstractValueObject() { 7 | 8 | override fun equalProperties(other: Any): Boolean { 9 | return other is ObjectWrapper && value == other.value 10 | } 11 | 12 | override fun hashCode(): Int = value?.hashCode() ?: 0 13 | 14 | override fun buildStringHelper(): ToStringBuilder { 15 | return super.buildStringHelper() 16 | .add("value", value) 17 | } 18 | } -------------------------------------------------------------------------------- /kommons-core/src/main/kotlin/io/kommons/SortDirection.kt: -------------------------------------------------------------------------------- 1 | package io.kommons 2 | 3 | /** 4 | * SortDirection 5 | * 6 | * @author debop 7 | */ 8 | enum class SortDirection(val direction: Int) { 9 | 10 | ASC(1), DESC(-1); 11 | 12 | companion object { 13 | @JvmStatic 14 | fun of(dir: Int): SortDirection = if (dir > 0) ASC else DESC 15 | } 16 | } -------------------------------------------------------------------------------- /kommons-core/src/main/kotlin/io/kommons/StringBuilderExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.kommons 2 | 3 | 4 | fun StringBuilder.appendln(msg: String): StringBuilder = 5 | this.append(msg).appendln() 6 | 7 | fun StringBuilder.appendln(msg: () -> String): StringBuilder = 8 | this.append(msg.invoke()).appendln() -------------------------------------------------------------------------------- /kommons-core/src/main/kotlin/io/kommons/utils/codec/StringEncoder.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.utils.codec 2 | 3 | /** 4 | * 바이트 배열을 문자열로 인코딩/디코딩 하는 Interface 5 | * 6 | * @author debop 7 | */ 8 | interface StringEncoder { 9 | 10 | /** 11 | * 바이트 배열을 인코딩하여 문자열로 만든다. 12 | * @param bytes 인코딩할 바이트 배열 13 | * @return 인코딩된 문자열 14 | */ 15 | fun encode(bytes: ByteArray?): String 16 | 17 | /** 18 | * 인코딩된 문자열을 분해하여 바이트 배열로 만든다. 19 | * @param encoded 인코딩된 문자열 20 | * @return 디코딩된 바이트 배열 21 | */ 22 | fun decode(encoded: String?): ByteArray 23 | } -------------------------------------------------------------------------------- /kommons-core/src/main/kotlin/io/kommons/utils/memorizer/AsyncMemorizer.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.utils.memorizer 2 | 3 | import java.util.concurrent.CompletionStage 4 | 5 | /** 6 | * 비동기 함수 결과를 기록하여, 재시도 시에는 빠르게 결과를 응답할 수 있도록 해주는 Memorizer 입니다. 7 | * 8 | * @author debop 9 | */ 10 | interface AsyncMemorizer: (T) -> CompletionStage { 11 | 12 | /** 13 | * 저장된 기존 수행 결과를 clear 합니다. 14 | */ 15 | fun clear() 16 | 17 | } -------------------------------------------------------------------------------- /kommons-core/src/main/kotlin/io/kommons/utils/memorizer/Memorizer.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.utils.memorizer 2 | 3 | /** 4 | * 메소드의 실행 결과를 기억하여, 재 실행 시에 빠르게 응닫할 수 있도록 합니다. 5 | * 6 | * @author debop 7 | */ 8 | interface Memorizer: (T) -> R { 9 | 10 | /** 11 | * 저장된 기존 수행 결과를 clear 합니다. 12 | */ 13 | fun clear() 14 | 15 | fun put(key: T, value: R) 16 | 17 | } -------------------------------------------------------------------------------- /kommons-core/src/main/kotlin/io/kommons/utils/resizablearray/ArrayBlock.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.utils.resizablearray 2 | 3 | import io.kommons.utils.resizablearray.ResizableArrayBuffer.Companion.KB 4 | 5 | data class ArrayBlock(val size: Int = KB, val count: Int = 1) { 6 | val capacity: Int get() = size * count 7 | } -------------------------------------------------------------------------------- /kommons-core/src/test/kotlin/io/kommons/utils/codec/Base64StringEncoderTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.utils.codec 2 | 3 | class Base64StringEncoderTest: AbstractStringEncoderTest() { 4 | 5 | override val encoder: StringEncoder = Base64StringEncoder() 6 | 7 | } -------------------------------------------------------------------------------- /kommons-core/src/test/kotlin/io/kommons/utils/codec/HexStringEncoderTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.utils.codec 2 | 3 | class HexStringEncoderTest: AbstractStringEncoderTest() { 4 | 5 | override val encoder: StringEncoder = HexStringEncoder() 6 | 7 | } -------------------------------------------------------------------------------- /kommons-core/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /kommons-core/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | true 7 | 8 | %d{ISO8601} %highlight(%-5level) [%blue(%t)] %yellow(%logger):%method:%line: %msg%n%throwable 9 | UTF-8 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /kommons-junit-jupiter/src/main/kotlin/io/kommons/junit/jupiter/JupiterExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.junit.jupiter 2 | 3 | import org.junit.jupiter.api.extension.ExtensionContext 4 | 5 | 6 | internal fun ExtensionContext.namespace(clazz: Class<*>): ExtensionContext.Namespace = 7 | ExtensionContext.Namespace.create(clazz, this) 8 | 9 | internal fun ExtensionContext.store(clazz: Class<*>): ExtensionContext.Store = 10 | getStore(namespace(clazz)) -------------------------------------------------------------------------------- /kommons-junit-jupiter/src/main/kotlin/io/kommons/junit/jupiter/folder/TempFolderTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.junit.jupiter.folder 2 | 3 | import org.junit.jupiter.api.extension.ExtendWith 4 | 5 | /** 6 | * TemporaryFolderTest 7 | * 8 | * @author debop 9 | */ 10 | @Retention(AnnotationRetention.RUNTIME) 11 | @Target(AnnotationTarget.CLASS, 12 | AnnotationTarget.FILE, 13 | AnnotationTarget.FUNCTION) 14 | @MustBeDocumented 15 | @Repeatable 16 | @ExtendWith(TempFolderExtension::class) 17 | annotation class TempFolderTest -------------------------------------------------------------------------------- /kommons-junit-jupiter/src/main/kotlin/io/kommons/junit/jupiter/stopwatch/StopWatchTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.junit.jupiter.stopwatch 2 | 3 | import org.junit.jupiter.api.extension.ExtendWith 4 | 5 | /** 6 | * StopWatchTest 7 | * 8 | * @author debop 9 | */ 10 | @Retention(AnnotationRetention.RUNTIME) 11 | @Target(AnnotationTarget.CLASS, 12 | AnnotationTarget.FILE, 13 | AnnotationTarget.FUNCTION) 14 | @MustBeDocumented 15 | @Repeatable 16 | @ExtendWith(StopWatchExtension::class) 17 | annotation class StopWatchTest -------------------------------------------------------------------------------- /kommons-junit-jupiter/src/test/kotlin/io/kommons/junit/jupiter/JupiterExtensionsTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.junit.jupiter 2 | 3 | import io.kommons.logging.KLogging 4 | 5 | class JupiterExtensionsTest { 6 | 7 | companion object: KLogging() 8 | } -------------------------------------------------------------------------------- /kommons-junit-jupiter/src/test/kotlin/io/kommons/junit/jupiter/random/DomainObject.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.junit.jupiter.random 2 | 3 | class DomainObject { 4 | 5 | var id: Int = 0 6 | var name: String? = null 7 | var value: Long = 0L 8 | var price: Double = 0.0 9 | val nestedDomainObject: NestedDomainObject? = null 10 | val wotsits: List? = null 11 | val objectLists: List = emptyList() 12 | } -------------------------------------------------------------------------------- /kommons-junit-jupiter/src/test/kotlin/io/kommons/junit/jupiter/random/NestedDomainObject.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.junit.jupiter.random 2 | 3 | class NestedDomainObject { 4 | 5 | var address: String? = null 6 | var category: String? = null 7 | } -------------------------------------------------------------------------------- /kommons-junit-jupiter/src/test/kotlin/io/kommons/junit/jupiter/stopwatch/StopWatchExtensionTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.junit.jupiter.stopwatch 2 | 3 | import org.junit.jupiter.api.Test 4 | import org.junit.jupiter.api.TestInstance 5 | import org.junit.jupiter.api.TestInstance.Lifecycle 6 | 7 | @TestInstance(Lifecycle.PER_METHOD) 8 | @StopWatchTest 9 | class StopWatchExtensionTest { 10 | 11 | @Test 12 | fun `테스트 후 실행시간을 로그애 씁니다`() { 13 | Thread.sleep(10) 14 | } 15 | 16 | @StopWatchTest 17 | @Test 18 | fun `메소드 별로 실행 시간을 측정합니다`() { 19 | Thread.sleep(1) 20 | } 21 | } -------------------------------------------------------------------------------- /kommons-junit-jupiter/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /kommons-logging/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | api(Libraries.slf4j_api) 4 | 5 | testImplementation(Libraries.logback) 6 | } -------------------------------------------------------------------------------- /kommons-logging/src/main/kotlin/io/kommons/logging/KLogging.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.logging 2 | 3 | import io.kommons.logging.internal.KLoggerFactory 4 | import org.slf4j.Logger 5 | 6 | /** 7 | * KLogging 8 | * 9 | * @author debop 10 | */ 11 | open class KLogging { 12 | 13 | val log: Logger = KLoggerFactory.logger(this.javaClass) 14 | 15 | } -------------------------------------------------------------------------------- /kommons-logging/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /kommons-testcontainers/src/main/kotlin/io/kommons/testcontainers/databases/JdbcDatabaseServer.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.testcontainers.databases 2 | 3 | import io.kommons.testcontainers.GenericServer 4 | 5 | /** 6 | * Jdbc Database Server의 기본 속성을 표현하는 Interface 7 | * 8 | * @author debop 9 | */ 10 | interface JdbcDatabaseServer: GenericServer { 11 | 12 | fun getDriverClassName(): String 13 | 14 | fun getJdbcUrl(): String 15 | 16 | fun getUsername(): String? 17 | 18 | fun getPassword(): String? 19 | 20 | fun getDatabaseName(): String? 21 | 22 | } -------------------------------------------------------------------------------- /kommons-testcontainers/src/test/kotlin/io/kommons/testcontainers/generic/ArangoDBServerTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.testcontainers.generic 2 | 3 | import io.kommons.logging.KLogging 4 | import org.amshove.kluent.shouldBeTrue 5 | import org.junit.jupiter.api.Test 6 | 7 | class ArangoDBServerTest { 8 | 9 | companion object: KLogging() 10 | 11 | @Test 12 | fun `launch arangodb server`() { 13 | ArangoDBServer() 14 | .apply { start() } 15 | .use { 16 | it.isRunning.shouldBeTrue() 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /kommons-testcontainers/src/test/resources/hazelcast-client.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | TCInstance 10 | hazelcast! 11 | 12 | 13 | -------------------------------------------------------------------------------- /kommons-testcontainers/src/test/resources/initial.cql: -------------------------------------------------------------------------------- 1 | CREATE KEYSPACE keySpaceTest WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1}; 2 | 3 | USE keySpaceTest; 4 | 5 | CREATE TABLE catalog_category (id bigint primary key, name text); 6 | 7 | INSERT INTO catalog_category (id, name) VALUES (1, 'test_category'); -------------------------------------------------------------------------------- /kommons-testcontainers/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | # \uC11C\uBC84 \uC2E4\uD589\uC5D0 \uBD80\uD558\uAC00 \uD06C\uAE30 \uB54C\uBB38\uC5D0 \uBCD1\uB82C\uB85C \uC218\uD589\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 4 | junit.jupiter.execution.parallel.enabled = true 5 | junit.jupiter.execution.parallel.mode.default = same_thread -------------------------------------------------------------------------------- /lazy-loading/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | implementation(Libraries.kotlinx_coroutines_jdk8) 4 | 5 | } -------------------------------------------------------------------------------- /lazy-loading/doc/lazy-loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/lazy-loading/doc/lazy-loading.png -------------------------------------------------------------------------------- /lazy-loading/src/main/kotlin/io/kommons/designpatterns/lazy/loading/Heavy.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.lazy.loading 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | /** 7 | * 생성에 많은 비용이 들어가는 클래스 8 | * 9 | * @author debop 10 | * @since 28/09/2019 11 | */ 12 | class Heavy { 13 | 14 | companion object: KLogging() 15 | 16 | init { 17 | log.info { "Creating Heavy ... " } 18 | 19 | Thread.sleep(1000) 20 | 21 | log.info { "... Heavy created" } 22 | } 23 | } -------------------------------------------------------------------------------- /lazy-loading/src/main/kotlin/io/kommons/designpatterns/lazy/loading/HolderThreadSafe.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.lazy.loading 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | /** 7 | * Thread safe하게 지연 생성을 수행 8 | */ 9 | class HolderThreadSafe { 10 | 11 | companion object: KLogging() 12 | 13 | init { 14 | log.info { "HolderThreadSafe created." } 15 | } 16 | 17 | private lateinit var heavy: Heavy 18 | 19 | @Synchronized 20 | fun getHeavy(): Heavy { 21 | if (!this::heavy.isInitialized) { 22 | heavy = Heavy() 23 | } 24 | return heavy 25 | } 26 | } -------------------------------------------------------------------------------- /lazy-loading/src/main/kotlin/io/kommons/designpatterns/lazy/loading/KotlinHolder.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.lazy.loading 2 | 3 | import io.kommons.logging.KLogging 4 | 5 | /** 6 | * Kotlin property delegate 기능 중 `by lazy`를 이용하여 지연 로딩을 수행합니다. 7 | */ 8 | class KotlinHolder { 9 | 10 | companion object: KLogging() 11 | 12 | private val _heavy: Heavy by lazy { Heavy() } 13 | 14 | fun getHeavy(): Heavy = _heavy 15 | } -------------------------------------------------------------------------------- /lazy-loading/src/test/kotlin/io/kommons/designpatterns/lazy/loading/HolderNaiveTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.lazy.loading 2 | 3 | /** 4 | * LazyLoadingTest 5 | */ 6 | class HolderNaiveTest: AbstractHolderTest() { 7 | 8 | private val holder = HolderNaive() 9 | 10 | override fun getInternalHeavyValue(): Heavy? { 11 | val field = HolderNaive::class.java.getDeclaredField("heavy") 12 | field.isAccessible = true 13 | 14 | return field.get(holder) as? Heavy 15 | } 16 | 17 | override fun getHeavy(): Heavy? { 18 | return holder.getHeavy() 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /lazy-loading/src/test/kotlin/io/kommons/designpatterns/lazy/loading/HolderThreadSafeTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.lazy.loading 2 | 3 | class HolderThreadSafeTest: AbstractHolderTest() { 4 | 5 | private val holder = HolderThreadSafe() 6 | 7 | override fun getInternalHeavyValue(): Heavy? { 8 | val field = HolderThreadSafe::class.java.getDeclaredField("heavy") 9 | field.isAccessible = true 10 | 11 | return field.get(holder) as? Heavy 12 | } 13 | 14 | override fun getHeavy(): Heavy? { 15 | return holder.getHeavy() 16 | } 17 | } -------------------------------------------------------------------------------- /lazy-loading/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /poison-pill/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /poison-pill/etc/poison-pill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/poison-pill/etc/poison-pill.png -------------------------------------------------------------------------------- /poison-pill/src/test/kotlin/io/kommons/designpatterns/poisonpill/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.poisonpill 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | class AppTest { 6 | 7 | @Test 8 | fun test() { 9 | main() 10 | } 11 | } -------------------------------------------------------------------------------- /poison-pill/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /producer-consumer/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | api(Libraries.commons_lang3) 4 | implementation(Libraries.logback) 5 | 6 | } 7 | -------------------------------------------------------------------------------- /producer-consumer/etc/producer-consumer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/producer-consumer/etc/producer-consumer.png -------------------------------------------------------------------------------- /producer-consumer/src/main/kotlin/io/kommons/designpatterns/producer/consumer/Consumer.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.producer.consumer 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | class Consumer(private val name: String, private val queue: ItemQueue) { 7 | 8 | companion object: KLogging() 9 | 10 | @Throws(InterruptedException::class) 11 | fun consume() { 12 | val item = queue.take() 13 | log.info { "Consumer [$name] consume item[${item.id}] produced by[${item.producer}]" } 14 | } 15 | } -------------------------------------------------------------------------------- /producer-consumer/src/main/kotlin/io/kommons/designpatterns/producer/consumer/Item.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.producer.consumer 2 | 3 | data class Item(val id: Int, val producer: String) -------------------------------------------------------------------------------- /producer-consumer/src/main/kotlin/io/kommons/designpatterns/producer/consumer/ItemQueue.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.producer.consumer 2 | 3 | import java.util.concurrent.BlockingQueue 4 | import java.util.concurrent.LinkedBlockingQueue 5 | 6 | class ItemQueue { 7 | 8 | private val queue: BlockingQueue = LinkedBlockingQueue(5) 9 | 10 | @Throws(InterruptedException::class) 11 | fun put(item: Item) { 12 | queue.put(item) 13 | } 14 | 15 | @Throws(InterruptedException::class) 16 | fun take(): Item { 17 | return queue.take() 18 | } 19 | } -------------------------------------------------------------------------------- /producer-consumer/src/test/kotlin/io/kommons/designpatterns/producer/consumer/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.producer.consumer 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | class AppTest { 6 | 7 | @Test 8 | fun test() { 9 | main() 10 | } 11 | } -------------------------------------------------------------------------------- /producer-consumer/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /promise/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | api(Libraries.commons_lang3) 4 | implementation(Libraries.logback) 5 | 6 | } 7 | -------------------------------------------------------------------------------- /promise/etc/promise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/promise/etc/promise.png -------------------------------------------------------------------------------- /promise/src/test/kotlin/io/kommons/designpatterns/promise/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.promise 2 | 3 | import io.kommons.logging.KLogging 4 | import org.junit.jupiter.api.Test 5 | 6 | class AppTest { 7 | 8 | companion object: KLogging() 9 | 10 | @Test 11 | fun `run main`() { 12 | main() 13 | } 14 | } -------------------------------------------------------------------------------- /promise/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /queue-load-leveling/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /queue-load-leveling/etc/queue-load-leveling.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/queue-load-leveling/etc/queue-load-leveling.gif -------------------------------------------------------------------------------- /queue-load-leveling/src/main/kotlin/io/kommons/designpatterns/queueloadleveling/Message.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.queueloadleveling 2 | 3 | data class Message(val msg: String) -------------------------------------------------------------------------------- /queue-load-leveling/src/main/kotlin/io/kommons/designpatterns/queueloadleveling/MessageQueue.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.queueloadleveling 2 | 3 | import io.kommons.logging.KLogging 4 | import java.util.concurrent.ArrayBlockingQueue 5 | import java.util.concurrent.BlockingQueue 6 | 7 | class MessageQueue { 8 | 9 | companion object: KLogging() 10 | 11 | private val queue: BlockingQueue = ArrayBlockingQueue(1024) 12 | 13 | fun submit(msg: Message) { 14 | queue.add(msg) 15 | } 16 | 17 | fun retrieve(): Message? = queue.poll() 18 | } -------------------------------------------------------------------------------- /queue-load-leveling/src/main/kotlin/io/kommons/designpatterns/queueloadleveling/Task.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.queueloadleveling 2 | 3 | interface Task { 4 | 5 | fun submit(msg: Message) 6 | } -------------------------------------------------------------------------------- /queue-load-leveling/src/test/kotlin/io/kommons/designpatterns/queueloadleveling/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.queueloadleveling 2 | 3 | import io.kommons.logging.KLogging 4 | import org.junit.jupiter.api.Test 5 | 6 | class AppTest { 7 | 8 | companion object: KLogging() 9 | 10 | @Test 11 | fun `queue load leveling`() { 12 | main() 13 | } 14 | } -------------------------------------------------------------------------------- /queue-load-leveling/src/test/kotlin/io/kommons/designpatterns/queueloadleveling/MessageQueueTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.queueloadleveling 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | class MessageQueueTest { 7 | 8 | @Test 9 | fun `submit message to MessageQueeu`() { 10 | 11 | val expected = Message("Test Message") 12 | 13 | val msgQueue = MessageQueue() 14 | msgQueue.submit(expected) 15 | 16 | msgQueue.retrieve() shouldBeEqualTo expected 17 | } 18 | } -------------------------------------------------------------------------------- /queue-load-leveling/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /resource-acquisition-is-initialization/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.png -------------------------------------------------------------------------------- /resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.urm.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | package com.iluwatar.resource.acquisition.is.initialization { 3 | class App { 4 | - LOGGER : Logger {static} 5 | + App() 6 | + main(args : String[]) {static} 7 | } 8 | class SlidingDoor { 9 | - LOGGER : Logger {static} 10 | + SlidingDoor() 11 | + close() 12 | } 13 | class TreasureChest { 14 | - LOGGER : Logger {static} 15 | + TreasureChest() 16 | + close() 17 | } 18 | } 19 | @enduml -------------------------------------------------------------------------------- /resource-acquisition-is-initialization/src/main/kotlin/io/kommons/designpatterns/resource/acquisition/is/initialization/App.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.resource.acquisition.`is`.initialization 2 | 3 | import io.kommons.logging.KotlinLogging 4 | import io.kommons.logging.info 5 | 6 | class App 7 | 8 | private val log = KotlinLogging.logger { } 9 | 10 | fun main() { 11 | 12 | SlidingDoor().use { 13 | log.info { "Walking in." } 14 | } 15 | 16 | TreasureChest().use { 17 | log.info { "Looting contents." } 18 | } 19 | } -------------------------------------------------------------------------------- /resource-acquisition-is-initialization/src/main/kotlin/io/kommons/designpatterns/resource/acquisition/is/initialization/SlidingDoor.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.resource.acquisition.`is`.initialization 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | import java.io.Closeable 6 | 7 | class SlidingDoor: Closeable { 8 | 9 | companion object: KLogging() 10 | 11 | init { 12 | log.info { "Sliding door opens." } 13 | } 14 | 15 | override fun close() { 16 | log.info { "Sliding door closes." } 17 | } 18 | } -------------------------------------------------------------------------------- /resource-acquisition-is-initialization/src/main/kotlin/io/kommons/designpatterns/resource/acquisition/is/initialization/TreasureChest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.resource.acquisition.`is`.initialization 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | import java.io.Closeable 6 | 7 | class TreasureChest: Closeable { 8 | 9 | companion object: KLogging() 10 | 11 | init { 12 | log.info { "Treasure chest opens." } 13 | } 14 | 15 | override fun close() { 16 | log.info { "Treasure chest closes." } 17 | } 18 | } -------------------------------------------------------------------------------- /resource-acquisition-is-initialization/src/test/kotlin/io/kommons/designpatterns/resource/acquisition/is/initialization/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.resource.acquisition.`is`.initialization 2 | 3 | import io.kommons.logging.KLogging 4 | import org.junit.jupiter.api.Test 5 | 6 | class AppTest { 7 | 8 | companion object: KLogging() 9 | 10 | @Test 11 | fun `run main`() { 12 | main() 13 | } 14 | } -------------------------------------------------------------------------------- /resource-acquisition-is-initialization/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /retry/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | api(Libraries.resilience4j_all) 4 | api(Libraries.resilience4j_kotlin) 5 | } -------------------------------------------------------------------------------- /retry/etc/retry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/retry/etc/retry.png -------------------------------------------------------------------------------- /retry/src/main/kotlin/io/kommons/designpatterns/retry/BusinessOperation.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.retry 2 | 3 | @FunctionalInterface 4 | interface BusinessOperation { 5 | 6 | @Throws(BusinessException::class) 7 | fun perform(): T 8 | } 9 | 10 | fun businessOperationOf(action: () -> T): BusinessOperation = 11 | object: BusinessOperation { 12 | override fun perform(): T { 13 | return action.invoke() 14 | } 15 | } -------------------------------------------------------------------------------- /retry/src/main/kotlin/io/kommons/designpatterns/retry/FindCustomer.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.retry 2 | 3 | import java.util.ArrayDeque 4 | 5 | class FindCustomer(private val customerId: String, 6 | vararg _errors: BusinessException): BusinessOperation { 7 | 8 | private val errors = ArrayDeque(_errors.toList()) 9 | 10 | override fun perform(): String { 11 | if (errors.isNotEmpty()) { 12 | throw this.errors.pop() 13 | } 14 | return this.customerId 15 | } 16 | } -------------------------------------------------------------------------------- /retry/src/test/kotlin/io/kommons/designpatterns/retry/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.retry 2 | 3 | import io.kommons.logging.KLogging 4 | 5 | class AppTest { 6 | 7 | companion object: KLogging() 8 | 9 | fun `run main`() { 10 | main() 11 | } 12 | } -------------------------------------------------------------------------------- /role-object/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /role-object/etc/role-object.urm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/role-object/etc/role-object.urm.png -------------------------------------------------------------------------------- /role-object/src/main/kotlin/io/kommons/designpatterns/roleobject/BorrowerRole.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.roleobject 2 | 3 | class BorrowerRole: CustomerRole() { 4 | 5 | var name: String = "" 6 | 7 | fun borrow(): String { 8 | return "Borrower $name wants to get some money." 9 | } 10 | } -------------------------------------------------------------------------------- /role-object/src/main/kotlin/io/kommons/designpatterns/roleobject/Customer.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.roleobject 2 | 3 | interface Customer { 4 | 5 | fun addRole(role: Role): Boolean 6 | 7 | fun hasRole(role: Role): Boolean 8 | 9 | fun removeRole(role: Role): Boolean 10 | 11 | fun getRole(role: Role, expectedRole: Class): T? 12 | 13 | companion object { 14 | fun newCustomer(): CustomerCore = CustomerCore() 15 | 16 | fun newCustomer(vararg roles: Role): CustomerCore = 17 | newCustomer().apply { 18 | roles.forEach { addRole(it) } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /role-object/src/main/kotlin/io/kommons/designpatterns/roleobject/CustomerRole.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.roleobject 2 | 3 | abstract class CustomerRole: CustomerCore() -------------------------------------------------------------------------------- /role-object/src/main/kotlin/io/kommons/designpatterns/roleobject/InvestorRole.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.roleobject 2 | 3 | class InvestorRole: CustomerRole() { 4 | 5 | var name: String = "" 6 | var amountToInvest: Long = 0L 7 | 8 | fun invest(): String = 9 | "Investor $name has invested $amountToInvest dollars" 10 | } -------------------------------------------------------------------------------- /role-object/src/main/kotlin/io/kommons/designpatterns/roleobject/Role.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.roleobject 2 | 3 | enum class Role(val typeCast: Class) { 4 | 5 | Borrower(BorrowerRole::class.java), 6 | Investor(InvestorRole::class.java); 7 | 8 | @Suppress("UNCHECKED_CAST") 9 | fun instance(): T? = 10 | runCatching { typeCast.newInstance() as? T }.getOrNull() 11 | } -------------------------------------------------------------------------------- /role-object/src/test/kotlin/io/kommons/designpatterns/roleobject/ApplicationRoleObjectTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.roleobject 2 | 3 | import io.kommons.logging.KLogging 4 | import org.junit.jupiter.api.Test 5 | 6 | class ApplicationRoleObjectTest { 7 | 8 | companion object: KLogging() 9 | 10 | @Test 11 | fun `run main`() { 12 | main() 13 | } 14 | } -------------------------------------------------------------------------------- /role-object/src/test/kotlin/io/kommons/designpatterns/roleobject/BorrowerRoleTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.roleobject 2 | 3 | import org.amshove.kluent.shouldEqual 4 | import org.junit.jupiter.api.Test 5 | 6 | class BorrowerRoleTest { 7 | 8 | @Test 9 | fun `run borrow`() { 10 | val borrowerRole = BorrowerRole().apply { name = "test" } 11 | borrowerRole.borrow() shouldEqual "Borrower test wants to get some money." 12 | } 13 | } -------------------------------------------------------------------------------- /role-object/src/test/kotlin/io/kommons/designpatterns/roleobject/InvestorRoleTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.roleobject 2 | 3 | import org.amshove.kluent.shouldEqual 4 | import org.junit.jupiter.api.Test 5 | 6 | class InvestorRoleTest { 7 | 8 | @Test 9 | fun `test investor role`() { 10 | val investorRole = InvestorRole().apply { 11 | name = "test" 12 | amountToInvest = 10 13 | } 14 | 15 | investorRole.invest() shouldEqual "Investor test has invested 10 dollars" 16 | } 17 | } -------------------------------------------------------------------------------- /role-object/src/test/kotlin/io/kommons/designpatterns/roleobject/RoleTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.roleobject 2 | 3 | import org.amshove.kluent.shouldBeInstanceOf 4 | import org.amshove.kluent.shouldNotBeNull 5 | import org.junit.jupiter.params.ParameterizedTest 6 | import org.junit.jupiter.params.provider.EnumSource 7 | 8 | class RoleTest { 9 | 10 | @ParameterizedTest 11 | @EnumSource(value = Role::class) 12 | fun `instancing role`(role: Role) { 13 | val instance: CustomerRole? = role.instance() 14 | instance.shouldNotBeNull() 15 | instance shouldBeInstanceOf role.typeCast 16 | } 17 | } -------------------------------------------------------------------------------- /role-object/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /semaphore/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | api(Libraries.commons_lang3) 4 | implementation(Libraries.logback) 5 | 6 | } 7 | -------------------------------------------------------------------------------- /semaphore/etc/semaphore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/semaphore/etc/semaphore.png -------------------------------------------------------------------------------- /semaphore/src/main/kotlin/io/kommons/designpatterns/semaphore/App.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.semaphore 2 | 3 | class App 4 | 5 | fun main() { 6 | val shop = FruitShop() 7 | val customerNames = listOf("Peter", "Paul", "Mary", "John", "Ringo", "George") 8 | 9 | val customers = customerNames.map { Customer(it, shop) } 10 | customers.forEach { it.start() } 11 | customers.forEach { it.join() } 12 | } -------------------------------------------------------------------------------- /semaphore/src/main/kotlin/io/kommons/designpatterns/semaphore/Lock.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.semaphore 2 | 3 | /** 4 | * Lock is an interface for a lock which can be acquired and released. 5 | */ 6 | interface Lock { 7 | 8 | fun acquire() 9 | 10 | fun release() 11 | } -------------------------------------------------------------------------------- /semaphore/src/test/kotlin/io/kommons/designpatterns/semaphore/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.semaphore 2 | 3 | import io.kommons.logging.KLogging 4 | import org.junit.jupiter.api.Test 5 | 6 | class AppTest { 7 | 8 | companion object: KLogging() 9 | 10 | @Test 11 | fun `customer buy fruit`() { 12 | val shop = FruitShop() 13 | val customerNames = listOf("Peter", "Paul", "Mary", "John", "Ringo", "George") 14 | 15 | val customers = customerNames.map { Customer(it, shop) } 16 | customers.forEach { it.start() } 17 | customers.map { it.join() } 18 | } 19 | } -------------------------------------------------------------------------------- /semaphore/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /servant/etc/servant-pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/servant/etc/servant-pattern.png -------------------------------------------------------------------------------- /servant/src/main/kotlin/io/kommons/designpatterns/servant/Royalty.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.servant 2 | 3 | interface Royalty { 4 | 5 | fun getFed() 6 | 7 | fun getDrink() 8 | 9 | fun changeMood() 10 | 11 | fun receiveCompliments() 12 | 13 | fun getMood(): Boolean 14 | } -------------------------------------------------------------------------------- /servant/src/main/kotlin/io/kommons/designpatterns/servant/Servant.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.servant 2 | 3 | class Servant(val name: String) { 4 | 5 | fun feed(r: Royalty) { 6 | r.getFed() 7 | } 8 | 9 | fun giveWine(r: Royalty) { 10 | r.getDrink() 11 | } 12 | 13 | fun giveCompliments(r: Royalty) { 14 | r.receiveCompliments() 15 | } 16 | 17 | fun checkIfYouWillBeHanged(tableGuests: List): Boolean { 18 | return tableGuests.all { it.getMood() } 19 | } 20 | } -------------------------------------------------------------------------------- /servant/src/test/kotlin/io/kommons/designpatterns/servant/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.servant 2 | 3 | import io.kommons.logging.KLogging 4 | import org.junit.jupiter.api.Test 5 | 6 | class AppTest { 7 | 8 | companion object: KLogging() 9 | 10 | @Test 11 | fun `run main`() { 12 | main() 13 | } 14 | } -------------------------------------------------------------------------------- /servant/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /service-locator/etc/service-locator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/service-locator/etc/service-locator.png -------------------------------------------------------------------------------- /service-locator/src/test/kotlin/io/kommons/designpatterns/servicelocator/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.servicelocator 2 | 3 | import io.kommons.logging.KLogging 4 | import org.junit.jupiter.api.Test 5 | 6 | class AppTest { 7 | 8 | companion object: KLogging() 9 | 10 | @Test 11 | fun `run main`() { 12 | main() 13 | } 14 | } -------------------------------------------------------------------------------- /service-locator/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /sharding/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | api(Libraries.commons_lang3) 4 | implementation(Libraries.logback) 5 | 6 | } 7 | -------------------------------------------------------------------------------- /sharding/etc/sharding.urm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/sharding/etc/sharding.urm.png -------------------------------------------------------------------------------- /sharding/src/main/kotlin/io/kommons/designpatterns/sharding/Shard.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.sharding 2 | 3 | enum class DataType { 4 | TYPE1, TYPE2, TYPE3 5 | } 6 | 7 | data class Data(var key: Int, var value: String, var type: DataType) 8 | 9 | data class Shard(val id: Int) { 10 | 11 | private val dataStore = LinkedHashMap() 12 | 13 | fun storeData(data: Data) { 14 | dataStore[data.key] = data 15 | } 16 | 17 | fun clearData() { 18 | dataStore.clear() 19 | } 20 | 21 | fun getDataById(id: Int): Data? { 22 | return dataStore[id] 23 | } 24 | } -------------------------------------------------------------------------------- /sharding/src/test/kotlin/io/kommons/designpatterns/sharding/HashShardManagerTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.sharding 2 | 3 | import io.kommons.designpatterns.sharding.managers.HashShardManager 4 | import io.kommons.designpatterns.sharding.managers.ShardManager 5 | import io.kommons.logging.KLogging 6 | 7 | class HashShardManagerTest: AbstractShardManagerTest() { 8 | 9 | companion object: KLogging() 10 | 11 | override val shardManager: ShardManager = HashShardManager() 12 | 13 | 14 | } -------------------------------------------------------------------------------- /sharding/src/test/kotlin/io/kommons/designpatterns/sharding/RangeShardManagerTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.sharding 2 | 3 | import io.kommons.designpatterns.sharding.managers.RangeShardManager 4 | import io.kommons.designpatterns.sharding.managers.ShardManager 5 | import io.kommons.logging.KLogging 6 | 7 | class RangeShardManagerTest: AbstractShardManagerTest() { 8 | 9 | companion object: KLogging() 10 | 11 | override val shardManager: ShardManager = RangeShardManager() 12 | 13 | } -------------------------------------------------------------------------------- /sharding/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /singleton/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | implementation(Libraries.kotlinx_coroutines_core) 4 | implementation(Libraries.kotlinx_coroutines_jdk8) 5 | } -------------------------------------------------------------------------------- /singleton/src/main/kotlin/io/kommons/designpatterns/singleton/EnumIvoryTower.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.singleton 2 | 3 | /** 4 | * Enum based singleton implementation. Effective Java 2nd Edition (Joshua Bloch) p. 18 5 | * 6 | * This implementation is thread safe, however adding any other method and its thread safety 7 | * is developers responsibility. 8 | */ 9 | enum class EnumIvoryTower { 10 | 11 | INSTANCE; 12 | 13 | override fun toString(): String = javaClass.canonicalName + "@" + hashCode() 14 | 15 | } -------------------------------------------------------------------------------- /singleton/src/main/kotlin/io/kommons/designpatterns/singleton/IvoryTower.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.singleton 2 | 3 | /** 4 | * Singleton class. Eagerly initialized static instance guarantees thread safety. 5 | */ 6 | class IvoryTower private constructor() { 7 | 8 | companion object { 9 | 10 | private val INSTANCE: IvoryTower = IvoryTower() 11 | 12 | @JvmStatic 13 | fun getInstance(): IvoryTower = INSTANCE 14 | } 15 | } -------------------------------------------------------------------------------- /singleton/src/main/kotlin/io/kommons/designpatterns/singleton/IvoryTowerObject.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.singleton 2 | 3 | /** 4 | * IvoryTowerObject 5 | * 6 | * @author debop 7 | */ 8 | object IvoryTowerObject { 9 | 10 | fun getInstance(): IvoryTowerObject = this 11 | 12 | } -------------------------------------------------------------------------------- /singleton/src/main/kotlin/io/kommons/designpatterns/singleton/KotlinSingleton.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.singleton 2 | 3 | /** 4 | * Kotlin lazy delegator를 이용하여 singleton 을 생성합니다. 5 | * 6 | * @author debop 7 | */ 8 | class KotlinSingleton { 9 | 10 | companion object { 11 | 12 | @JvmStatic 13 | val INSTANCE: KotlinSingleton by lazy { KotlinSingleton() } 14 | } 15 | } -------------------------------------------------------------------------------- /singleton/src/test/kotlin/io/kommons/designpatterns/singleton/EnumIvoryTowerTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.singleton 2 | 3 | class EnumIvoryTowerTest: AbstractSingletonTest({ EnumIvoryTower.INSTANCE }) -------------------------------------------------------------------------------- /singleton/src/test/kotlin/io/kommons/designpatterns/singleton/InitializingOnDemandHolderIdiomTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.singleton 2 | 3 | class InitializingOnDemandHolderIdiomTest 4 | : AbstractSingletonTest({ InitializingOnDemandHolderIdiom.getInstance() }) -------------------------------------------------------------------------------- /singleton/src/test/kotlin/io/kommons/designpatterns/singleton/IvoryTowerTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.singleton 2 | 3 | import io.kommons.designpatterns.singleton.IvoryTower.Companion 4 | 5 | 6 | class IvoryTowerTest: AbstractSingletonTest(Companion::getInstance) -------------------------------------------------------------------------------- /singleton/src/test/kotlin/io/kommons/designpatterns/singleton/ThreadSafeLazyLoadedIvoryTowerTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.singleton 2 | 3 | class ThreadSafeLazyLoadedIvoryTowerTest 4 | : AbstractSingletonTest({ ThreadSafeLazyLoadedIvoryTower.getInstance() }) -------------------------------------------------------------------------------- /singleton/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /specification/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | api(Libraries.commons_lang3) 4 | implementation(Libraries.logback) 5 | 6 | } 7 | -------------------------------------------------------------------------------- /specification/etc/specification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/specification/etc/specification.png -------------------------------------------------------------------------------- /specification/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /state/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | 4 | } -------------------------------------------------------------------------------- /state/etc/state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/state/etc/state.png -------------------------------------------------------------------------------- /state/etc/state_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/state/etc/state_1.png -------------------------------------------------------------------------------- /state/src/main/kotlin/io/kommons/designpatterns/state/AngreState.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.state 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.debug 5 | 6 | /** 7 | * Angre state 8 | */ 9 | class AngreState(private val mammoth: Mammoth): State { 10 | 11 | companion object: KLogging() 12 | 13 | override fun observe() { 14 | log.debug { "$mammoth is furious!" } 15 | } 16 | 17 | override fun onEtnerState() { 18 | log.debug { "$mammoth gets angry!" } 19 | } 20 | } -------------------------------------------------------------------------------- /state/src/main/kotlin/io/kommons/designpatterns/state/PeacefulState.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.state 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.debug 5 | 6 | /** 7 | * PeacefulState 8 | * 9 | * @author debop 10 | */ 11 | class PeacefulState(val mammoth: Mammoth): State { 12 | 13 | companion object: KLogging() 14 | 15 | override fun observe() { 16 | log.debug { "$mammoth is calm and peaceful." } 17 | } 18 | 19 | override fun onEtnerState() { 20 | log.debug { "$mammoth calms down." } 21 | } 22 | } -------------------------------------------------------------------------------- /state/src/main/kotlin/io/kommons/designpatterns/state/State.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.state 2 | 3 | /** 4 | * State 5 | */ 6 | interface State { 7 | 8 | fun onEtnerState() 9 | 10 | fun observe() 11 | } -------------------------------------------------------------------------------- /state/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /step-builder/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | 4 | } -------------------------------------------------------------------------------- /step-builder/etc/step-builder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/step-builder/etc/step-builder.png -------------------------------------------------------------------------------- /step-builder/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /strategy/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | 4 | } -------------------------------------------------------------------------------- /strategy/etc/strategy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/strategy/etc/strategy.png -------------------------------------------------------------------------------- /strategy/etc/strategy_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/strategy/etc/strategy_1.png -------------------------------------------------------------------------------- /strategy/src/main/kotlin/io/kommons/designpatterns/strategy/DragonSlayer.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.strategy 2 | 3 | /** 4 | * DragonSlayer 5 | * 6 | * @author debop 7 | */ 8 | class DragonSlayer(private var strategy: DragonSlayingStrategy) { 9 | 10 | fun changeStrategy(strategy: DragonSlayingStrategy) { 11 | this.strategy = strategy 12 | } 13 | 14 | fun goToBattle() { 15 | strategy.execute() 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /strategy/src/main/kotlin/io/kommons/designpatterns/strategy/DragonSlayingStrategy.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.strategy 2 | 3 | @FunctionalInterface 4 | interface DragonSlayingStrategy { 5 | 6 | fun execute() 7 | 8 | } -------------------------------------------------------------------------------- /strategy/src/main/kotlin/io/kommons/designpatterns/strategy/MeleeStrategy.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.strategy 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.debug 5 | 6 | /** 7 | * MelleStrategy 8 | * 9 | * @author debop 10 | */ 11 | class MeleeStrategy: DragonSlayingStrategy { 12 | 13 | companion object: KLogging() 14 | 15 | override fun execute() { 16 | log.debug { 17 | "너의 엑스칼리버로 용의 머리를 잘라라!" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /strategy/src/main/kotlin/io/kommons/designpatterns/strategy/ProjectileStrategy.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.strategy 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.debug 5 | 6 | /** 7 | * ProjectieStrategy 8 | * 9 | * @author debop 10 | */ 11 | class ProjectileStrategy: DragonSlayingStrategy { 12 | 13 | companion object: KLogging() 14 | 15 | override fun execute() { 16 | log.debug { 17 | "당신이 마법의 석궁으로 용을 쏘면 용은 땅에 쓰러져 죽는다." 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /strategy/src/main/kotlin/io/kommons/designpatterns/strategy/SpellStrategy.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.strategy 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | /** 7 | * SpellStrategy 8 | * 9 | * @author debop 10 | */ 11 | class SpellStrategy: DragonSlayingStrategy { 12 | 13 | companion object: KLogging() 14 | 15 | override fun execute() { 16 | log.info { 17 | "당신은 파괴의 주문을 하고, 용은 먼지 더미 속으로 증발해버린다!" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /strategy/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /subclass-sandbox/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | 4 | } -------------------------------------------------------------------------------- /subclass-sandbox/etc/subclass-sandbox.urm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/subclass-sandbox/etc/subclass-sandbox.urm.png -------------------------------------------------------------------------------- /subclass-sandbox/src/main/kotlin/io/kommons/designpatterns/subclasssandbox/GroundDive.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.subclasssandbox 2 | 3 | import io.kommons.logging.KLogging 4 | 5 | class GroundDive: Superpower { 6 | 7 | companion object: KLogging() 8 | 9 | override fun activate() { 10 | move(0.0, 0.0, -20.0) 11 | playSound("GROUNDDIVE_SOUND", 5) 12 | spawnParticles("GROUNDDIVE_PARTICLE", 20) 13 | } 14 | } -------------------------------------------------------------------------------- /subclass-sandbox/src/main/kotlin/io/kommons/designpatterns/subclasssandbox/SkyLauncher.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.subclasssandbox 2 | 3 | import io.kommons.logging.KLogging 4 | 5 | class SkyLauncher: Superpower { 6 | 7 | companion object: KLogging() 8 | 9 | override fun activate() { 10 | move(0.0, 0.0, 20.0) 11 | playSound("SKYLAUNCH_SOUND", 1) 12 | spawnParticles("SKYLAUNCH_PARTICLE", 100) 13 | } 14 | } -------------------------------------------------------------------------------- /subclass-sandbox/src/test/kotlin/io/kommons/designpatterns/subclasssandbox/SuperpowerTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.subclasssandbox 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | import org.junit.jupiter.api.Test 6 | 7 | class SuperpowerTest { 8 | 9 | companion object: KLogging() 10 | 11 | @Test 12 | fun `superpower example`() { 13 | log.info { "Use superpower: sky launch" } 14 | val skyLauncher = SkyLauncher() 15 | skyLauncher.activate() 16 | 17 | log.info { "Use superpower: ground dive" } 18 | val groundDive = GroundDive() 19 | groundDive.activate() 20 | } 21 | } -------------------------------------------------------------------------------- /subclass-sandbox/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /template-method/etc/template-method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/template-method/etc/template-method.png -------------------------------------------------------------------------------- /template-method/etc/template-method_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/template-method/etc/template-method_1.png -------------------------------------------------------------------------------- /template-method/src/main/kotlin/io/kommons/designpatterns/templatemethod/HalflingThief.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.templatemethod 2 | 3 | /** 4 | * Halfling thief uses [StealingMethod] to steal. 5 | */ 6 | class HalflingThief(private var method: StealingMethod) { 7 | 8 | fun steal() { 9 | method.steal() 10 | } 11 | 12 | fun changeMethod(method: StealingMethod) { 13 | this.method = method 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /template-method/src/test/kotlin/io/kommons/designpatterns/templatemethod/HitAndRunMethodTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.templatemethod 2 | 3 | /** 4 | * HitAndRunMethodTest 5 | * 6 | * @author debop 7 | */ 8 | class HitAndRunMethodTest: StealingMethodTest( 9 | HitAndRunMethod(), 10 | "old goblin woman", 11 | "The target has been chosen as old goblin woman.", 12 | "Approach the old goblin woman from behind.", 13 | "Grab the handbag and run away fast!" 14 | ) -------------------------------------------------------------------------------- /template-method/src/test/kotlin/io/kommons/designpatterns/templatemethod/SubtleMethodTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.templatemethod 2 | 3 | /** 4 | * SubtleMethodTest 5 | * 6 | * @author debop 7 | */ 8 | class SubtleMethodTest: StealingMethodTest( 9 | SubtleMethod(), 10 | "shop keeper", 11 | "The target has been chosen as shop keeper.", 12 | "Approach the shop keeper with tears running and hug him!", 13 | "While in close contact grab the shop keeper's wallet." 14 | ) -------------------------------------------------------------------------------- /template-method/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /thread-pool/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /thread-pool/etc/thread-pool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/thread-pool/etc/thread-pool.png -------------------------------------------------------------------------------- /thread-pool/src/main/kotlin/io/kommons/designpatterns/threadpool/Worker.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.threadpool 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.error 5 | import io.kommons.logging.info 6 | 7 | class Worker(private val task: Task): () -> Unit { 8 | 9 | companion object: KLogging() 10 | 11 | override fun invoke() { 12 | log.info { "${Thread.currentThread().name} processing $task" } 13 | try { 14 | Thread.sleep(task.timeMs.toLong()) 15 | } catch (e: InterruptedException) { 16 | log.error(e) { "Fail to run task." } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /thread-pool/src/test/kotlin/io/kommons/designpatterns/threadpool/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.threadpool 2 | 3 | import io.kommons.logging.KLogging 4 | import org.junit.jupiter.api.Test 5 | 6 | class AppTest { 7 | 8 | companion object: KLogging() 9 | 10 | @Test 11 | fun `run main`() { 12 | main() 13 | } 14 | } -------------------------------------------------------------------------------- /thread-pool/src/test/kotlin/io/kommons/designpatterns/threadpool/CoffeeMakingTaskTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.threadpool 2 | 3 | class CoffeeMakingTaskTest: TaskTest(::CoffeeMakingTask, 100) { 4 | } -------------------------------------------------------------------------------- /thread-pool/src/test/kotlin/io/kommons/designpatterns/threadpool/PotatoPeelingTaskTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.threadpool 2 | 3 | class PotatoPeelingTaskTest: TaskTest(::PotatoPeelingTask, 200) { 4 | } -------------------------------------------------------------------------------- /thread-pool/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /throttling/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pattern 3 | title: Throttling 4 | folder: throttling 5 | permalink: /patterns/throttling/ 6 | categories: Behavioral 7 | tags: 8 | - Java 9 | - Difficulty-Beginner 10 | --- 11 | 12 | ## Intent 13 | Ensure that a given client is not able to access service resources more than the assigned limit. 14 | 15 | ## Applicability 16 | The Throttling pattern should be used: 17 | 18 | * when a service access needs to be restricted to not have high impacts on the performance of the service. 19 | * when multiple clients are consuming the same service resources and restriction has to be made according to the usage per client. 20 | -------------------------------------------------------------------------------- /throttling/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /throttling/etc/throttling-pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/throttling/etc/throttling-pattern.png -------------------------------------------------------------------------------- /throttling/src/main/kotlin/io/kommons/designpatterns/throttling/Tenant.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.throttling 2 | 3 | /** 4 | * Tenant 5 | * 6 | * @author debop 7 | */ 8 | data class Tenant(val name: String, 9 | val allowedCallsPerSecond: Long, 10 | private val callsCount: CallsCount) { 11 | init { 12 | require(allowedCallsPerSecond >= 0L) { "Number of calls less than 0 not allowed." } 13 | callsCount.addTenant(name) 14 | } 15 | } -------------------------------------------------------------------------------- /throttling/src/main/kotlin/io/kommons/designpatterns/throttling/timer/Throttler.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.throttling.timer 2 | 3 | /** 4 | * An interface for defining the structure of different types of throttling ways. 5 | */ 6 | @FunctionalInterface 7 | interface Throttler { 8 | 9 | /** 10 | * A timer is initiated with this method. The timer runs every second and resets the counter. 11 | */ 12 | fun start() 13 | 14 | } 15 | 16 | fun throttller(block: () -> Unit): Throttler = 17 | object: Throttler { 18 | override fun start() { 19 | block.invoke() 20 | } 21 | } -------------------------------------------------------------------------------- /throttling/src/test/kotlin/io/kommons/designpatterns/throttling/TenantTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.throttling 2 | 3 | import org.junit.jupiter.api.Test 4 | import org.junit.jupiter.api.assertThrows 5 | 6 | class TenantTest { 7 | 8 | @Test 9 | fun `create tenant with invalid parameter`() { 10 | assertThrows { 11 | Tenant("FailTenant", -1, CallsCount()) 12 | } 13 | } 14 | 15 | @Test 16 | fun `create tenant with valid parameter`() { 17 | Tenant("SuccessTenant", 100, CallsCount()) 18 | } 19 | } -------------------------------------------------------------------------------- /throttling/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /tls/etc/tls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/tls/etc/tls.png -------------------------------------------------------------------------------- /tls/src/main/kotlin/io/kommons/designpatterns/tls/Result.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.tls 2 | 3 | import java.util.Date 4 | 5 | /** 6 | * Result object that will be returned by the Callable [DateFormatCallable] used in [App] 7 | * 8 | */ 9 | class Result { 10 | 11 | // A list to collect the date values created in one thread 12 | val dateList = mutableListOf() 13 | 14 | // A list to collect Exceptions thrown in one threads (should be none in this example) 15 | val exceptionList = mutableListOf() 16 | 17 | } -------------------------------------------------------------------------------- /tls/src/test/kotlin/io/kommons/designpatterns/tls/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.tls 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | class AppTest { 6 | 7 | @Test 8 | fun `run main`() { 9 | main() 10 | } 11 | } -------------------------------------------------------------------------------- /tls/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /tolerant-reader/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | api(project(":kommons-core")) 3 | } -------------------------------------------------------------------------------- /tolerant-reader/etc/tolerant-reader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/tolerant-reader/etc/tolerant-reader.png -------------------------------------------------------------------------------- /tolerant-reader/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /update-method/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /update-method/etc/update-method.urm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/update-method/etc/update-method.urm.png -------------------------------------------------------------------------------- /update-method/src/test/kotlin/io/kommons/designpatterns/updatemethod/AppTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.updatemethod 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | class AppTest { 6 | 7 | @Test 8 | fun `run main`() { 9 | main() 10 | } 11 | } -------------------------------------------------------------------------------- /update-method/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /value-object/etc/value-object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/value-object/etc/value-object.png -------------------------------------------------------------------------------- /value-object/etc/value-object.urm.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | package com.iluwatar.value.object { 3 | class App { 4 | - LOGGER : Logger {static} 5 | + App() 6 | + main(args : String[]) {static} 7 | } 8 | class HeroStat { 9 | - intelligence : int 10 | - luck : int 11 | - strength : int 12 | - HeroStat(strength : int, intelligence : int, luck : int) 13 | + equals(obj : Object) : boolean 14 | + getIntelligence() : int 15 | + getLuck() : int 16 | + getStrength() : int 17 | + hashCode() : int 18 | + toString() : String 19 | + valueOf(strength : int, intelligence : int, luck : int) : HeroStat {static} 20 | } 21 | } 22 | @enduml -------------------------------------------------------------------------------- /value-object/src/main/kotlin/io/kommons/designpatterns/valueobject/App.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.valueobject 2 | 3 | import io.kommons.logging.KotlinLogging 4 | import io.kommons.logging.info 5 | 6 | class App 7 | 8 | private val log = KotlinLogging.logger { } 9 | 10 | fun main() { 11 | val statA = HeroStat(10, 5, 0) 12 | val statB = HeroStat(10, 5, 0) 13 | val statC = HeroStat(5, 1, 8) 14 | 15 | log.info { "$statA" } 16 | 17 | log.info { "Is statA and statB equal: ${statA == statB}" } 18 | log.info { "Is statA and statC equal: ${statA == statC}" } 19 | } -------------------------------------------------------------------------------- /value-object/src/main/kotlin/io/kommons/designpatterns/valueobject/HeroStat.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.valueobject 2 | 3 | data class HeroStat(val strength: Int, 4 | val intelligence: Int, 5 | val luck: Int) -------------------------------------------------------------------------------- /value-object/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread -------------------------------------------------------------------------------- /visitor/build.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | } -------------------------------------------------------------------------------- /visitor/doc/visitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/visitor/doc/visitor.png -------------------------------------------------------------------------------- /visitor/doc/visitor_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debop/kotlin-design-patterns/c00bcc0542985bbcfc4652d0045f31e5c1304a70/visitor/doc/visitor_1.png -------------------------------------------------------------------------------- /visitor/src/main/kotlin/io/kommons/designpatterns/visitor/Commander.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | /** 4 | * Commander 5 | * 6 | * @author debop 7 | * @since 29/09/2019 8 | */ 9 | class Commander(override val children: MutableList = mutableListOf()): Node { 10 | 11 | override fun accept(visitor: NodeVisitor) { 12 | visitor.visit(this) 13 | super.accept(visitor) 14 | } 15 | 16 | override fun toString(): String = "commander" 17 | } -------------------------------------------------------------------------------- /visitor/src/main/kotlin/io/kommons/designpatterns/visitor/CommanderVisitor.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | /** 7 | * CommanderVisitor 8 | * 9 | * @author debop 10 | * @since 29/09/2019 11 | */ 12 | class CommanderVisitor: NodeVisitor { 13 | 14 | companion object: KLogging() 15 | 16 | override fun visit(node: Node) { 17 | when (node) { 18 | is Commander -> log.info { "Good to see you $node" } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /visitor/src/main/kotlin/io/kommons/designpatterns/visitor/Node.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | /** 4 | * Interface for the nodes in hierachy 5 | */ 6 | interface Node { 7 | 8 | val children: MutableList 9 | 10 | @JvmDefault 11 | fun accept(visitor: NodeVisitor) { 12 | children.forEach { 13 | it.accept(visitor) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /visitor/src/main/kotlin/io/kommons/designpatterns/visitor/NodeVisitor.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | /** 4 | * Visitor interface 5 | * 6 | * @author debop 7 | * @since 29/09/2019 8 | */ 9 | interface NodeVisitor { 10 | 11 | /** 12 | * Visit to node 13 | * 14 | * @param node 15 | */ 16 | fun visit(node: Node) 17 | 18 | } -------------------------------------------------------------------------------- /visitor/src/main/kotlin/io/kommons/designpatterns/visitor/Sergeant.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | /** 4 | * Sergeant 5 | * 6 | * @author debop 7 | * @since 29/09/2019 8 | */ 9 | class Sergeant(override val children: MutableList = mutableListOf()): Node { 10 | 11 | override fun accept(visitor: NodeVisitor) { 12 | visitor.visit(this) 13 | super.accept(visitor) 14 | } 15 | 16 | override fun toString(): String = "sergeant" 17 | } -------------------------------------------------------------------------------- /visitor/src/main/kotlin/io/kommons/designpatterns/visitor/SergeantVisitor.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | /** 7 | * SergeantVisitor 8 | * 9 | * @author debop 10 | * @since 29/09/2019 11 | */ 12 | class SergeantVisitor: NodeVisitor { 13 | 14 | companion object: KLogging() 15 | 16 | override fun visit(node: Node) { 17 | when (node) { 18 | is Sergeant -> log.info { "Hello $node" } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /visitor/src/main/kotlin/io/kommons/designpatterns/visitor/Soldier.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | /** 4 | * Soldier 5 | * 6 | * @author debop 7 | * @since 29/09/2019 8 | */ 9 | class Soldier(override val children: MutableList = mutableListOf()): Node { 10 | 11 | override fun accept(visitor: NodeVisitor) { 12 | visitor.visit(this) 13 | super.accept(visitor) 14 | } 15 | 16 | override fun toString(): String = "soldier" 17 | } -------------------------------------------------------------------------------- /visitor/src/main/kotlin/io/kommons/designpatterns/visitor/SoldierVisitor.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | import io.kommons.logging.KLogging 4 | import io.kommons.logging.info 5 | 6 | /** 7 | * SoldierVisitor 8 | * 9 | * @author debop 10 | * @since 29/09/2019 11 | */ 12 | class SoldierVisitor: NodeVisitor { 13 | 14 | companion object: KLogging() 15 | 16 | override fun visit(node: Node) { 17 | when (node) { 18 | is Soldier -> log.info { "Greetings $node" } 19 | else -> { 20 | // Nothing to do 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /visitor/src/test/kotlin/io/kommons/designpatterns/visitor/CommanderTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | /** 4 | * CommanderTest 5 | * 6 | * @author debop 7 | * @since 29/09/2019 8 | */ 9 | class CommanderTest: AbstractNodeTest(::Commander) -------------------------------------------------------------------------------- /visitor/src/test/kotlin/io/kommons/designpatterns/visitor/CommanderVisitorTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | /** 4 | * CommanderVisitorTest 5 | * 6 | * @author debop 7 | * @since 29/09/2019 8 | */ 9 | class CommanderVisitorTest: AbstractVisitorTest( 10 | visitor = CommanderVisitor(), 11 | commanderResponse = "Good to see you commander" 12 | ) -------------------------------------------------------------------------------- /visitor/src/test/kotlin/io/kommons/designpatterns/visitor/SergeantTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | /** 4 | * SergeantTest 5 | * 6 | * @author debop 7 | * @since 29/09/2019 8 | */ 9 | class SergeantTest: AbstractNodeTest(::Sergeant) -------------------------------------------------------------------------------- /visitor/src/test/kotlin/io/kommons/designpatterns/visitor/SergeantVisitorTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | /** 4 | * SergeantVisitorTest 5 | * 6 | * @author debop 7 | * @since 29/09/2019 8 | */ 9 | class SergeantVisitorTest: AbstractVisitorTest( 10 | visitor = SergeantVisitor(), 11 | sergeantResponse = "Hello sergeant" 12 | ) -------------------------------------------------------------------------------- /visitor/src/test/kotlin/io/kommons/designpatterns/visitor/SoldierTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | /** 4 | * SoldierTest 5 | * 6 | * @author debop 7 | * @since 29/09/2019 8 | */ 9 | class SoldierTest: AbstractNodeTest(::Soldier) -------------------------------------------------------------------------------- /visitor/src/test/kotlin/io/kommons/designpatterns/visitor/SoldierVisitorTest.kt: -------------------------------------------------------------------------------- 1 | package io.kommons.designpatterns.visitor 2 | 3 | /** 4 | * SoldierVisitorTest 5 | * 6 | * @author debop 7 | * @since 29/09/2019 8 | */ 9 | class SoldierVisitorTest 10 | : AbstractVisitorTest(visitor = SoldierVisitor(), 11 | soldierResponse = "Greetings soldier") -------------------------------------------------------------------------------- /visitor/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testinstance.lifecycle.default = per_class 2 | 3 | junit.jupiter.execution.parallel.enabled = true 4 | junit.jupiter.execution.parallel.mode.default = concurrent 5 | junit.jupiter.execution.parallel.mode.classes.default = same_thread --------------------------------------------------------------------------------