抽象工厂模式
正文:https://refactoringguru.cn/design-patterns/abstract-factory
Go代码:https://refactoringguru.cn/design-patterns/abstract-factory/go/example
点评:显然易见,抽象工厂设计模式缺点之一是,向应用中引入众多的接口和类,代码可能会因此变得更加复杂。
module abstract_factory_module
use, intrinsic :: iso_fortran_env, only: int8
implicit none
private
public :: isports_factory_type, erke_type, lining_type, get_sports_factory, erke_shoe_type, &
erke_shirt_type, lining_shoe_type, lining_shirt_type, ishoe_type, ishirt_type
!> Abstract classes
type, abstract :: isports_factory_type
contains
procedure(isports_factory_type_make_shoe), deferred :: make_shoe
procedure(isports_factory_type_make_shirt), deferred :: make_shirt
end type isports_factory_type
type, abstract :: ishoe_type
contains
procedure(ishoe_type_set_logo), deferred :: set_logo
procedure(ishoe_type_set_size), deferred :: set_size
procedure(ishoe_type_get_logo), deferred :: get_logo
procedure(ishoe_type_get_size), deferred :: get_size
end type ishoe_type
type, abstract :: ishirt_type
contains
procedure(ishirt_type_set_logo), deferred :: set_logo
procedure(ishirt_type_set_size), deferred :: set_size
procedure(ishirt_type_get_logo), deferred :: get_logo
procedure(ishirt_type_get_size), deferred :: get_size
end type ishirt_type
abstract interface
function isports_factory_type_make_shoe(self) result(shoe)
import isports_factory_type, ishoe_type
class(isports_factory_type), intent(inout) :: self
class(ishoe_type), allocatable :: shoe
end function isports_factory_type_make_shoe
function isports_factory_type_make_shirt(self) result(shirt)
import isports_factory_type, ishirt_type
class(isports_factory_type), intent(inout) :: self
class(ishirt_type), allocatable :: shirt
end function isports_factory_type_make_shirt
subroutine ishoe_type_set_logo(self, logo)
import ishoe_type
class(ishoe_type), intent(inout) :: self
character(*), intent(in) :: logo
end subroutine ishoe_type_set_logo
subroutine ishoe_type_set_size(self, size)
import ishoe_type, int8
class(ishoe_type), intent(inout) :: self
integer(int8), intent(in) :: size
end subroutine ishoe_type_set_size
function ishoe_type_get_logo(self) result(logo)
import ishoe_type
class(ishoe_type), intent(inout) :: self
character(:), allocatable :: logo
end function ishoe_type_get_logo
function ishoe_type_get_size(self) result(size)
import ishoe_type, int8
class(ishoe_type), intent(inout) :: self
integer(int8) :: size
end function ishoe_type_get_size
subroutine ishirt_type_set_logo(self, logo)
import ishirt_type
class(ishirt_type), intent(inout) :: self
character(*), intent(in) :: logo
end subroutine ishirt_type_set_logo
subroutine ishirt_type_set_size(self, size)
import ishirt_type, int8
class(ishirt_type), intent(inout) :: self
integer(int8), intent(in) :: size
end subroutine ishirt_type_set_size
function ishirt_type_get_logo(self) result(logo)
import ishirt_type
class(ishirt_type), intent(inout) :: self
character(:), allocatable :: logo
end function ishirt_type_get_logo
function ishirt_type_get_size(self) result(size)
import ishirt_type, int8
class(ishirt_type), intent(inout) :: self
integer(int8) :: size
end function ishirt_type_get_size
end interface
!> Specific objects
type, extends(isports_factory_type) :: erke_type
contains
procedure :: make_shoe => erke_type_make_shoe
procedure :: make_shirt => erke_type_make_shirt
end type erke_type
type, extends(isports_factory_type) :: lining_type
contains
procedure :: make_shoe => lining_type_make_shoe
procedure :: make_shirt => lining_type_make_shirt
end type lining_type
type, extends(ishoe_type) :: shoe_type
character(:), allocatable :: logo
integer(int8) :: size
contains
procedure :: set_logo => shoe_type_set_logo
procedure :: set_size => shoe_type_set_size
procedure :: get_logo => shoe_type_get_logo
procedure :: get_size => shoe_type_get_size
end type shoe_type
type, extends(ishirt_type) :: shirt_type
character(:), allocatable :: logo
integer(int8) :: size
contains
procedure :: set_logo => shirt_type_set_logo
procedure :: set_size => shirt_type_set_size
procedure :: get_logo => shirt_type_get_logo
procedure :: get_size => shirt_type_get_size
end type shirt_type
type, extends(shoe_type) :: erke_shoe_type
end type erke_shoe_type
type, extends(shoe_type) :: lining_shoe_type
end type lining_shoe_type
type, extends(shirt_type) :: erke_shirt_type
end type erke_shirt_type
type, extends(shirt_type) :: lining_shirt_type
end type lining_shirt_type
contains
function get_sports_factory(brand) result(isports_factory)
character(*), intent(in) :: brand
class(isports_factory_type), allocatable :: isports_factory
select case (brand)
case ("erke")
isports_factory = erke_type()
case ("lining")
isports_factory = lining_type()
case default
error stop "*<ERROR>* Brand not supported."
end select
end function get_sports_factory
function erke_type_make_shoe(self) result(shoe)
class(erke_type), intent(inout) :: self
class(ishoe_type), allocatable :: shoe
shoe = erke_shoe_type(logo="erke", size=15_int8)
end function erke_type_make_shoe
function erke_type_make_shirt(self) result(shirt)
class(erke_type), intent(inout) :: self
class(ishirt_type), allocatable :: shirt
shirt = erke_shirt_type(logo="erke", size=84_int8)
end function erke_type_make_shirt
function lining_type_make_shoe(self) result(shoe)
class(lining_type), intent(inout) :: self
class(ishoe_type), allocatable :: shoe
shoe = lining_shoe_type(logo="lining", size=14_int8)
end function lining_type_make_shoe
function lining_type_make_shirt(self) result(shirt)
class(lining_type), intent(inout) :: self
class(ishirt_type), allocatable :: shirt
shirt = lining_shirt_type(logo="lining", size=85_int8)
end function lining_type_make_shirt
subroutine shoe_type_set_logo(self, logo)
class(shoe_type), intent(inout) :: self
character(*), intent(in) :: logo
self%logo = logo
end subroutine shoe_type_set_logo
subroutine shoe_type_set_size(self, size)
class(shoe_type), intent(inout) :: self
integer(int8), intent(in) :: size
self%size = size
end subroutine shoe_type_set_size
function shoe_type_get_logo(self) result(logo)
class(shoe_type), intent(inout) :: self
character(:), allocatable :: logo
logo = self%logo
end function shoe_type_get_logo
function shoe_type_get_size(self) result(size)
class(shoe_type), intent(inout) :: self
integer(int8) :: size
size = self%size
end function shoe_type_get_size
subroutine shirt_type_set_logo(self, logo)
class(shirt_type), intent(inout) :: self
character(*), intent(in) :: logo
self%logo = logo
end subroutine shirt_type_set_logo
subroutine shirt_type_set_size(self, size)
class(shirt_type), intent(inout) :: self
integer(int8), intent(in) :: size
self%size = size
end subroutine shirt_type_set_size
function shirt_type_get_logo(self) result(logo)
class(shirt_type), intent(inout) :: self
character(:), allocatable :: logo
logo = self%logo
end function shirt_type_get_logo
function shirt_type_get_size(self) result(size)
class(shirt_type), intent(inout) :: self
integer(int8) :: size
size = self%size
end function shirt_type_get_size
end module abstract_factory_module
program abstract_factory_main
use, intrinsic :: iso_fortran_env, only: int8
use abstract_factory_module, only: isports_factory_type, erke_type, lining_type, get_sports_factory, erke_shoe_type, &
erke_shirt_type, lining_shoe_type, lining_shirt_type, ishoe_type, ishirt_type
class(isports_factory_type), allocatable :: erke_factory, lining_factory
class(ishoe_type), allocatable :: erke_shoe
class(ishirt_type), allocatable :: erke_shirt
class(ishoe_type), allocatable :: lining_shoe
class(ishirt_type), allocatable :: lining_shirt
! allocate (erke_t :: erke_factory)
! allocate (lining_t :: lining_factory)
erke_factory = get_sports_factory("erke")
lining_factory = get_sports_factory("lining")
! allocate (erke_shoe_t :: erke_shoe)
! allocate (erke_shirt_t :: erke_shirt)
! allocate (lining_shoe_t :: lining_shoe)
! allocate (lining_shirt_t :: lining_shirt)
erke_shoe = erke_factory%make_shoe()
erke_shirt = erke_factory%make_shirt()
lining_shoe = lining_factory%make_shoe()
lining_shirt = lining_factory%make_shirt()
call print_shoe_details(erke_shoe)
call print_shirt_details(erke_shirt)
call print_shoe_details(lining_shoe)
call print_shirt_details(lining_shirt)
contains
subroutine print_shoe_details(ishoe)
class(ishoe_type), intent(inout) :: ishoe
print *, "This is a pair of shoes👟."
print *, "Logo: ", ishoe%get_logo()
print *, "Size: ", ishoe%get_size()
end subroutine print_shoe_details
subroutine print_shirt_details(ishirt)
class(ishirt_type), intent(inout) :: ishirt
print *, "This is a T-shirt👕."
print *, "Logo: ", ishirt%get_logo()
print *, "Size: ", ishirt%get_size()
end subroutine print_shirt_details
end program abstract_factory_main
!> Results shall be:
! This is a pair of shoes👟.
! Logo: erke
! Size: 14
! This is a T-shirt👕.
! Logo: erke
! Size: 14
! This is a pair of shoes👟.
! Logo: lining
! Size: 14
! This is a T-shirt👕.
! Logo: lining
! Size: 14