设计模式 - 17.状态模式 [行为型模式]
2020-03-27 本文已影响0人
Zszen
大纲 | 小结 |
---|---|
基础准则 | 基础准则 |
创建型模式 | 单例模式 |
- | 原型模式 |
- | 简单工厂模式 |
- | 抽象工厂模式 |
- | 建造者模式 |
结构型模式 | 代理模式 |
- | 适配器模式 |
- | 桥接模式 |
- | 装饰器模式 |
- | 门面/外观模式 |
- | 享元模式 |
- | 组合模式 |
行为型模式 | 模板方法模式 |
- | 策略模式 |
- | 命令模式 |
- | 职责链模式 |
- | 状态模式 |
- | 观察者模式 |
- | 中介者模式 |
- | 迭代器模式 |
- | 访问者模式 |
- | 备忘录模式 |
- | 解释器模式 |
对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
这次做的复杂了一点点, 结合了责任链模式和状态模式共同完成了特殊日期展示
通过责任链, 查找复杂条件下对应日期的描述, 也通过它可以反复使用和切换状态, 避免了反复创建的问题
通过状态机得到当前日期对应的日期描述
( 状态模式通过状态来改变依赖关系, 有点违背了依赖倒置原则
, 所以这里我改成了责任链, 所以这里不是完整的状态模式)
import abc
import datetime
class DateMean:
def __init__(self):
d1 = DateDes_f_11()
self._datedesc_def = d1
self._datedesc_cur = d1
d2 = DateDes_f_38()
d1.next = d2
d1 = d2
d2 = DateDes_f_51()
d1.next = d2
d1 = d2
d2 = DateDes_f_61()
d1.next = d2
d1 = d2
d2 = DateDes_f_101()
d1.next = d2
d1 = d2
d2 = DateDes_f_1111()
d1.next = d2
d1 = d2
d2 = DateDes_each1wes()
d1.next = d2
d1 = d2
d2 = DateDes_weekend()
d1.next = d2
d1 = d2
d2 = DateDes_Normal()
d1.next = d2
d1 = d2
def setDate(self, year, month, day):
self._datedesc_cur = self._datedesc_def.find(year,month,day)
def descript(self):
return self._datedesc_cur.name
class IDateDes(metaclass=abc.ABCMeta):
def __init__(self):
self._next:IDateDes = None
self.year = 0
self.month = 0
self.day = 0
self.name = None
pass
@property
def next(self):
return self._next
@next.setter
def next(self,nexter):
self._next = nexter
@abc.abstractmethod
def find(self, year,month,day):
pass
class DateDes_Normal(IDateDes):
def __init__(self):
super().__init__()
self.name = '普通的一天'
def find(self, year, month, day):
return self
class DateDes_festival(IDateDes):
def __init__(self):
super().__init__()
self.name = '节日'
def find(self, year, month, day):
if month==self.month and day==self.day:
return self
else:
return self.next.find(year, month, day)
class DateDes_f_11(DateDes_festival):
def __init__(self):
super().__init__()
self.name = '元旦'
self.month = 1
self.day = 1
class DateDes_f_38(DateDes_festival):
def __init__(self):
super().__init__()
self.name = '三八妇女节'
self.month = 3
self.day = 8
class DateDes_f_51(DateDes_festival):
def __init__(self):
super().__init__()
self.name = '五一劳动节'
self.month = 5
self.day = 1
class DateDes_f_61(DateDes_festival):
def __init__(self):
super().__init__()
self.name = '儿童节'
self.month = 6
self.day = 1
class DateDes_f_101(DateDes_festival):
def __init__(self):
super().__init__()
self.name = '十一劳动节'
self.month = 10
self.day = 1
class DateDes_f_1111(DateDes_festival):
def __init__(self):
super().__init__()
self.name = '双十一'
self.month = 11
self.day = 11
class DateDes_f_1225(DateDes_festival):
def __init__(self):
super().__init__()
self.name = '圣诞节'
self.month = 12
self.day = 25
class DateDes_weekend(IDateDes):
def __init__(self):
super().__init__()
self.name = '周末'
def find(self, year, month, day):
if year == None:
year = datetime.datetime.now().year
d = datetime.datetime.strptime('%d-%d-%d'%(year,month,day),'%Y-%m-%d')
if d.weekday() >= 5 :
return self
else:
return self.next.find(year, month, day)
class DateDes_each1wes(IDateDes):
def __init__(self):
super().__init__()
self.name = '每月第一个周三'
def find(self, year, month, day):
if day<7 :
if year == None:
year = datetime.datetime.now().year
d = datetime.datetime.strptime('%d-%d-%d'%(year,month,day),'%Y-%m-%d')
if d.weekday()==2:
return self
else:
return self.next.find(year, month, day)
else:
return self.next.find(year, month, day)
if __name__ == '__main__':
# dt = datetime.datetime(year=2020,month=1,day=1)
dt = datetime.datetime.now()
for k in range(20):
dt_cur = dt+datetime.timedelta(k)
d = DateMean()
d.setDate(dt_cur.year,dt_cur.month,dt_cur.day)
print(dt_cur.strftime('%Y-%m-%d'), d.descript())
输出
2020-03-27 普通的一天
2020-03-28 周末
2020-03-29 周末
2020-03-30 普通的一天
2020-03-31 普通的一天
2020-04-01 每月第一个周三
2020-04-02 普通的一天
2020-04-03 普通的一天
2020-04-04 周末
2020-04-05 周末
2020-04-06 普通的一天
2020-04-07 普通的一天
2020-04-08 普通的一天
2020-04-09 普通的一天
2020-04-10 普通的一天
2020-04-11 周末
2020-04-12 周末
2020-04-13 普通的一天
2020-04-14 普通的一天
2020-04-15 普通的一天
再进一步扩在, 你会发现, 要添加特殊日期, 也要在责任链中去添加, 修改的地方过多
使用抽象工厂+枚举的方案来解决这个问题