クラス、モジュール、関数などのソフトウェアのぶひんは拡張に対しては開いており、修正に対しては閉じていなければならないとする原則です。
# 開放閉鎖の原則1
# open_closed.py
# 開放閉鎖の原則を守った記述するには、、
from abc import ABCMeta, abstractmethod
class UserInfo(object):
"""ユーザ情報の保持"""
def __init__(self, user_name, job_name, nationality):
self.user_name = user_name
self.job_name = job_name
self.nationality = nationality
def __str__(self):
return "{} {} {}".format(
self.user_name, self.job_name, self.nationality
)
"""開放閉鎖の原則を守った作り方
以下のように定義すると、機能拡張をしたい場合は継承クラスによって行うことができる。
つまり、作成ずみのクラスを編集して汚す必要がなくなる。
"""
class Comparation(metaclass=ABCMeta):
@abstractmethod
def is_equal(self, other):
pass
# 応用編
def __and__(self, other):
return AndComparation(self, other)
def __or__(self, other):
return OrComparation(self, other)
class AndComparation(Comparation):
def __init__(self, *args):
# 可変長の引数をとる
self.comparations = args
def is_equal(self, other):
return all(
map(
lambda comparation: comparation.is_equal(other),
self.comparations
)
)
class OrComparation(Comparation):
def __init__(self, *args):
# 可変長の引数をとる
self.comparations = args
def is_equal(self, other):
return any(
map(
lambda comparation: comparation.is_equal(other),
self.comparations
)
)
class Filter(metaclass=ABCMeta):
@abstractmethod
def filter(self, comparation, item):
pass
class JobNameComparation(Comparation):
def __init__(self, job_name):
self.job_name = job_name
def is_equal(self, other):
return self.job_name == other.job_name
class NationalityComparation(Comparation):
def __init__(self, nationality):
self.nationality = nationality
def is_equal(self, other):
return self.nationality == other.nationality
class UserInfoFilter(Filter):
def filter(self, comparation, items):
for item in items:
if comparation.is_equal(item):
yield item
taro = UserInfo('taro', 'salary man', 'Japan')
jiro = UserInfo('jiro', 'police man', 'Japan')
john = UserInfo('john', 'salary man', 'USA')
user_list = [taro, jiro, john]
salary_man_comparation = JobNameComparation('salary man')
user_info_filter = UserInfoFilter()
print(' --- job name --- ')
for user in user_info_filter.filter(salary_man_comparation, user_list):
print(user)
print(' --- nationarity --- ')
japan_comparation = NationalityComparation('Japan')
for user in user_info_filter.filter(japan_comparation, user_list):
print(user)
#AndComparationを使ってみる。 & をつかつ
print('-'*10)
salary_man_and_japan = salary_man_comparation & japan_comparation
for user in user_info_filter.filter(salary_man_and_japan, user_list):
print(user)
#OrComparationを使ってみる。| (パイプ)でつなぐ
print('-'*10)
salary_man_or_japan = salary_man_comparation | japan_comparation
for user in user_info_filter.filter(salary_man_or_japan, user_list):
print(user)
# for man in UserInfoFilter.filter_users_job(user_list, 'police man'):
# print(man)
#
# for man in UserInfoFilter.filter_users_nationality(user_list, 'Japan'):
# print(man)