中介者模式
正文:https://refactoringguru.cn/design-patterns/mediator
Go代码:https://refactoringguru.cn/design-patterns/mediator/go/example
module mediator_module
implicit none
private
public :: station_manager_type, passenger_train_type, freight_train_type
type, abstract :: train_type
contains
procedure(train_type_arrive), deferred :: arrive
procedure(train_type_depart), deferred :: depart
procedure(train_type_permit_arrival), deferred :: permit_arrival
end type train_type
type, abstract :: mediator_t
contains
procedure(mediator_type_can_arrive), deferred :: can_arrive
procedure(mediator_type_notify_about_departure), deferred :: notify_about_departure
end type mediator_t
abstract interface
subroutine train_type_arrive(self)
import train_type
class(train_type), intent(inout) :: self
end subroutine train_type_arrive
subroutine train_type_depart(self)
import train_type
class(train_type), intent(inout) :: self
end subroutine train_type_depart
subroutine train_type_permit_arrival(self)
import train_type
class(train_type), intent(inout) :: self
end subroutine train_type_permit_arrival
logical function mediator_type_can_arrive(self, train) result(can)
import mediator_t, train_type
class(mediator_t), intent(inout) :: self
class(train_type), intent(in), target :: train
end function mediator_type_can_arrive
subroutine mediator_type_notify_about_departure(self)
import mediator_t
class(mediator_t), intent(inout) :: self
end subroutine mediator_type_notify_about_departure
end interface
type, extends(train_type) :: passenger_train_type
class(mediator_t), pointer :: mediator
contains
procedure :: arrive => passenger_train_type_arrive
procedure :: depart => passenger_train_type_depart
procedure :: permit_arrival => passenger_train_type_permit_arrival
end type passenger_train_type
type, extends(train_type) :: freight_train_type
class(mediator_t), pointer :: mediator
contains
procedure :: arrive => freight_train_type_arrive
procedure :: depart => freight_train_type_depart
procedure :: permit_arrival => freight_train_type_permit_arrival
end type freight_train_type
type node_t
class(train_type), pointer :: train
end type node_t
type, extends(mediator_t) :: station_manager_type
logical :: is_platform_free = .true.
type(node_t), allocatable :: list(:)
contains
procedure :: can_arrive => station_manager_type_can_arrive
procedure :: notify_about_departure => station_manager_type_notify_about_departure
end type station_manager_type
contains
subroutine passenger_train_type_arrive(self)
class(passenger_train_type), intent(inout) :: self
if (.not. self%mediator%can_arrive(self)) then
print *, "Passenger train: arrival blocked, waiting"
return
end if
print *, "Passenger train: arrived"
end subroutine passenger_train_type_arrive
subroutine passenger_train_type_depart(self)
class(passenger_train_type), intent(inout) :: self
print *, "Passenger train: leaving"
call self%mediator%notify_about_departure()
end subroutine passenger_train_type_depart
subroutine passenger_train_type_permit_arrival(self)
class(passenger_train_type), intent(inout) :: self
print *, "Passenger train: arrival permitted, arriving"
call self%arrive()
end subroutine passenger_train_type_permit_arrival
subroutine freight_train_type_arrive(self)
class(freight_train_type), intent(inout) :: self
if (.not. self%mediator%can_arrive(self)) then
print *, "Freight train: arrival blocked, waiting"
return
end if
print *, "Freight train: arrived"
end subroutine freight_train_type_arrive
subroutine freight_train_type_depart(self)
class(freight_train_type), intent(inout) :: self
print *, "freight train: leaving"
call self%mediator%notify_about_departure()
end subroutine freight_train_type_depart
subroutine freight_train_type_permit_arrival(self)
class(freight_train_type), intent(inout) :: self
print *, "Freight train: arrival permitted, arriving"
call self%arrive()
end subroutine freight_train_type_permit_arrival
logical function station_manager_type_can_arrive(self, train) result(can)
class(station_manager_type), intent(inout) :: self
class(train_type), intent(in), target :: train
if (self%is_platform_free) then
self%is_platform_free = .false.
can = .true.
return
end if
self%list = [self%list, node_t(train)]
can = .false.
end function station_manager_type_can_arrive
subroutine station_manager_type_notify_about_departure(self)
class(station_manager_type), intent(inout) :: self
class(train_type), pointer :: train
if (.not. self%is_platform_free) then
self%is_platform_free = .true.
end if
if (size(self%list) > 0) then
train => self%list(1)%train
!> 内存泄露
self%list = self%list(2:)
call train%permit_arrival()
end if
end subroutine station_manager_type_notify_about_departure
end module mediator_module
program mediator_main
use mediator_module, only: station_manager_type,passenger_train_type,freight_train_type
implicit none
type(station_manager_type), target :: station_manager
type(passenger_train_type) :: passenger_train
type(freight_train_type) :: freight_train
allocate(station_manager%list(0))
passenger_train%mediator => station_manager
freight_train%mediator => station_manager
call passenger_train%arrive()
call freight_train%arrive()
call passenger_train%depart()
end program mediator_main
!> Results shall be:
! Passenger train: arrived
! Freight train: arrival blocked, waiting
! Passenger train: leaving
! Freight train: arrival permitted, arriving
! Freight train: arrived