Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a FortranPattern: CoR(Chain of Responsibility) #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Tested on: GNU Fortran (GCC) 4.8.
- [ ] Proxy

#### Behavioral Patterns
- [ ] Chain of Responsibility
- [x] Chain of Responsibility
- [ ] Command
- [ ] Interpreter
- [ ] Iterator
Expand Down
33 changes: 33 additions & 0 deletions behavioral/chain_of_responsibility/CoR_main.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
!> CoR: Patient visiting hospital
program test_CoR

use hospital_CoR

type(cashier) :: c
type(medical) :: m
type(doctor) :: d
type(reception) :: r

type(patient) :: p1, p2

!> Set next for departments
call m%set_next(c)
call d%set_next(m)
call r%set_next(d)

p1 = patient("abc",.true.,.true.,.true.,.true.)
!> Patient visiting
print *, "> Patient `"//p1%name//"` : "
call r%execute(p1)

p2 = patient("def",.true.,.false.,.false.,.false.)
!> Patient visiting
print *, "> Patient `"//p2%name//"` : "
call r%execute(p2)

!> Optional statements
deallocate(m%next)
deallocate(d%next)
deallocate(r%next)

end program test_CoR
160 changes: 160 additions & 0 deletions behavioral/chain_of_responsibility/CoR_module.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
!> CoR: Hospital departments
module hospital_CoR

implicit none
private

public :: patient, department, reception, doctor, medical, cashier

type patient
character(:), allocatable :: name
logical :: registration_done
logical :: doctor_check_up_done
logical :: medicine_done
logical :: payment_done
end type patient

type, abstract :: department
contains
procedure(execute_procedure), deferred :: execute
procedure(set_next_procedure), deferred :: set_next
end type department

abstract interface
subroutine execute_procedure(self, p)
import department, patient
class(department), intent(inout) :: self
type(patient), intent(inout) :: p
end subroutine execute_procedure
subroutine set_next_procedure(self, next)
import department
class(department), intent(inout) :: self
class(department), intent(inout) :: next
end subroutine set_next_procedure
end interface

type, extends(department) :: reception
class(department), pointer :: next
contains
procedure :: execute => reception_execute
procedure :: set_next => reception_set_next
end type reception

type, extends(department) :: doctor
class(department), pointer :: next
contains
procedure :: execute => doctor_execute
procedure :: set_next => doctor_set_next
end type doctor

type, extends(department) :: medical
class(department), pointer :: next
contains
procedure :: execute => medicine_execute
procedure :: set_next => medicine_set_next
end type medical

type, extends(department) :: cashier
class(department), pointer :: next
contains
procedure :: execute => cashier_execute
procedure :: set_next => cashier_set_next
end type cashier

contains

subroutine reception_execute(self, p)
class(reception), intent(inout) :: self
type(patient), intent(inout) :: p

if (p%registration_done) then
print *, "Patient registration already done.✔️"
call self%next%execute(p)
return
end if

print *, "Reception registering patient."
p%registration_done = .true.
call self%next%execute(p)

end subroutine reception_execute

subroutine reception_set_next(self, next)
class(reception), intent(inout) :: self
class(department), intent(inout) :: next

allocate(self%next, source=next)

end subroutine reception_set_next

subroutine doctor_execute(self, p)
class(doctor), intent(inout) :: self
type(patient), intent(inout) :: p

if (p%doctor_check_up_done) then
print *, "Doctor checkup already done.✔️"
call self%next%execute(p)
return
end if

print *, "Doctor checking patient."
p%doctor_check_up_done = .true.
call self%next%execute(p)

end subroutine doctor_execute

subroutine doctor_set_next(self, next)
class(doctor), intent(inout) :: self
class(department), intent(inout) :: next

allocate(self%next, source=next)

end subroutine doctor_set_next

subroutine medicine_execute(self, p)
class(medical), intent(inout) :: self
type(patient), intent(inout) :: p

if (p%medicine_done) then
print *, "Medicine already given to patient.✔️"
call self%next%execute(p)
return
end if

print *, "Medical giving medicine to patient."
p%medicine_done = .true.
call self%next%execute(p)

end subroutine medicine_execute

subroutine medicine_set_next(self, next)
class(medical), intent(inout) :: self
class(department), intent(inout) :: next

allocate(self%next, source=next)

end subroutine medicine_set_next

subroutine cashier_execute(self, p)
class(cashier), intent(inout) :: self
type(patient), intent(inout) :: p

if (p%payment_done) then
print *, "Payment Done.✔️"
return
end if

print *, "Cashier getting money from patient."
p%payment_done = .true.

end subroutine cashier_execute

subroutine cashier_set_next(self, next)
class(cashier), intent(inout) :: self
class(department), intent(inout) :: next

allocate(self%next, source=next)

end subroutine cashier_set_next

end module hospital_CoR