Search code examples
javaandroidkotlincompanion-object

Could be a good example of using a companion object (static) this way?


In my application there are some actions that users can take, including redo support.

Therefore, I felt the need to manage by objectizing Action, and I implemented it as follows.

1. Implement RecoverableAction

abstract class RecoverableAction {
    abstract fun getActionName(): String
    abstract fun run()
    abstract fun undoActionName(): String

    enum class List(val action: RecoverableAction) {
        CONTAINER_CREATE(ContainerActions.CREATE), 
        CONTAINER_COPY(ContainerActions.COPY), 
        CONTAINER_DELETE(ContainerActions.DELETE)
    }
}

2. Implement Actions for Redo

    class ContainerActions private constructor() {
        companion object {
            val CREATE = object : RecoverableAction {
                override fun run() {
                    //do create
                }
                override fun getActionName() = List.CONTAINER_CREATE.name
                override fun undoActionName() = List.CONTAINER_DELETE.name
            }

            val DELETE = object : RecoverableAction {
                override fun run() {
                    //do create
                }
                override fun getActionName() = List.CONTAINER_CREATE.name
                override fun undoActionName() = List.CONTAINER_DELETE.name
            }

            val COPY = object : RecoverableAction {
                override fun run() {
                    //do copy
                }
                override fun getActionName() = List.CONTAINER_CREATE.name
                override fun undoActionName() = List.CONTAINER_DELETE.name
            }
        }
    }

3. Do Action anywhere 2 way

    CotainerActions.CREATE.run()
    RecoverableAction.List.CONTAINER_COPY.action.run()

I do not like using static variables, but I do not want each Action to be instantiated each time it is executed from the user. I also implemented it as a companion so that I could run the corresponding Action directly from several different classes.

In addition, I need to implement the redo function by managing the actions executed by the user as a stack. The reason I implemented the Action supported by RecoverableAction as an enum is because I want to manage it in the Action record stack by name rather than Action object.

I have been thinking a lot about designing the structure to implement these requirements, but I think this can be a good structure. Could this be a "good way"?


Solution

  • To me,

    RecoverableAction.List.CONTAINER_COPY.action.run()

    Seems messy.


    Why not:

    sealed class RecoverableActions {
        abstract val actionName: String
    
        abstract val undoActionName: String
    
        abstract fun run()
    
        object CreateAction : RecoverableActions() {
            override fun run() {
                //do create
            }
            override val actionName = CreateAction::class.java.simpleName
            override val undoActionName = DeleteAction::class.java.simpleName
        }
    
        object DeleteAction : RecoverableActions() {
            override fun run() {
                //do create
            }
            override val actionName = DeleteAction::class.java.simpleName
            override val undoActionName = CreateAction::class.java.simpleName
        }
    
        object CopyAction : RecoverableActions() {
            override fun run() {
                //do create
            }
            override val actionName = CopyAction::class.java.simpleName
            override val undoActionName = CopyAction::class.java.simpleName // ?
        }
    }
    

    And

    RecoverableActions.CreateAction.run()