@startuml
skinparam arrowThickness 1.1
'I wasn't able to find a consistent standard for bound elements, so I just picked one
package storage {
    interface Storage <T extends Object> {
        --
        + writeData(T object, String path): void
        + loadData(String path): T
        + createTargetFile(String path): void

    }

    abstract class JsonStorage <T extends Object> implements Storage {
       --
       + writeData(T object, String path): void
       + {abstract} loadData(String path): T
       + createTargetFile(String path): void
    }

    abstract class ListStorage <ModHappyT extends Object> extends JsonStorage {
       --
       + {abstract} loadData(String path): ArrayList<ModHappyT>
    }

    ListStorage ..> JsonStorage : <<bind>>\nT -> ArrayList<ModHappyT>

    class ConfigurationStorage extends JsonStorage {
       --
       + loadData(String path): Configuration
    }

    ConfigurationStorage ..> JsonStorage : <<bind>>\nT -> Configuration

    class ModuleListStorage extends ListStorage {
       --
       + loadData(String path): ArrayList<Module>
    }

    ModuleListStorage ..> ListStorage : <<bind>>\nModHappyT -> Module

    class TaskListStorage extends ListStorage {
       --
       + loadData(String path):ArrayList<Task>
    }

    TaskListStorage ..> ListStorage : <<bind>>\nModHappyT -> Task
}

note top of storage
To avoid clutter, inherited methods
are not displayed in child classes.
end note

Class Main
hide Main circle
hide Main attributes
hide Main methods

Class SaveCommand
hide SaveCommand circle
hide SaveCommand attributes
hide SaveCommand methods

Main--> Storage
SaveCommand --> Storage




@enduml