享元模式

正文:https://refactoringguru.cn/design-patterns/flyweight

Go代码:https://zhuanlan.zhihu.com/p/343999246

module cache_module

    implicit none
    private

    public :: cache_type, cache_factory_type

    type, abstract :: cache_type
    contains
        procedure(cache_type_operation), deferred :: operation
    end type cache_type

    abstract interface
        subroutine cache_type_operation(self)
            import cache_type
            class(cache_type), intent(inout) :: self
        end subroutine cache_type_operation
    end interface

    type, extends(cache_type) :: concrete_cache_type
        character(:), allocatable :: key
    contains
        procedure :: operation => concrete_cache_type_operation
    end type concrete_cache_type

    type node_type
        class(cache_type), allocatable :: cache
    end type node_type

    type cache_factory_type
        type(node_type), allocatable :: cache_list(:)
    contains
        procedure :: get_cache => cache_factory_type_get_cache
    end type cache_factory_type

contains

    subroutine concrete_cache_type_operation(self)
        class(concrete_cache_type), intent(inout) :: self
        print *, self%key
    end subroutine concrete_cache_type_operation

    function cache_factory_type_get_cache(self, key) result(cache)
        class(cache_factory_type), intent(inout), target :: self
        character(*), intent(in) :: key
        class(cache_type), pointer :: cache
        integer :: i

        if (allocated(self%cache_list)) then
            do i = 1, size(self%cache_list)
                associate (cache_ => self%cache_list(i)%cache)
                
                    select type (cache_)
                    type is (concrete_cache_type)
                        if (cache_%key == key) then
                            cache => self%cache_list(i)%cache
                            return
                        end if
                    end select
                    
                end associate
            end do
        end if

        self%cache_list = append_slice(self%cache_list, key)
        cache => self%cache_list(size(self%cache_list))%cache

    end function cache_factory_type_get_cache

    !> Date structure
    function append_slice(cache_list_in, key) result(cache_list_out)
        type(node_type), intent(inout), allocatable :: cache_list_in(:)
        character(*), intent(in) :: key
        type(node_type), allocatable :: cache_list_out(:)
        integer :: i

        if (.not. allocated(cache_list_in)) then
            allocate (cache_list_out(1))
            allocate (cache_list_out(1)%cache, source=concrete_cache_type(key=key))
        else
            i = size(cache_list_in)
            allocate (cache_list_out(i + 1))
            cache_list_out(1:i) = cache_list_in
            allocate (cache_list_out(i + 1)%cache, source=concrete_cache_type(key=key))
        end if
    end function append_slice

end module cache_module
program cache_main

    use cache_module, only: cache_factory_type, cache_type
    implicit none
    type(cache_factory_type) factory
    class(cache_type), pointer :: cache

    cache => factory%get_cache("A")
    call cache%operation()

    cache => factory%get_cache("A")
    call cache%operation()

    cache => factory%get_cache("B")
    call cache%operation()

    cache => factory%get_cache("C")
    call cache%operation()

    print *, "List length: ", size(factory%cache_list)

end program cache_main

!> Results shall be:

!  A
!  A
!  B
!  C
!  List length:            3