1.全称
open close principle 缩写为:COP
2.解释
一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
3.实例
1.场景:购买衣服,根据某些要求挑选符合的服装
from abc import ABC, abstractmethod
from enum import Enum
class Color ( Enum) :
RED = 1
GREEN = 2
BLUE = 3
class Size ( Enum) :
SMALL = 1
MEDIUM = 2
LARGE = 3
class Product :
def __init__ ( self, name, color, size) :
self. name = name
self. color = color
self. size = size
class ProductFilter :
@staticmethod
def filter_by_color ( products: [ Product] , color) :
for p in products:
if p. color == color:
yield p
@staticmethod
def filter_by_size ( products: [ Product] , size) :
for p in products:
if p. size == size:
yield p
if __name__ == '__main__' :
p1 = Product( "衬衫" , Color. RED, Size. MEDIUM)
p2 = Product( "牛仔裤" , Color. BLUE, Size. MEDIUM)
p3 = Product( "帽子" , Color. RED, Size. LARGE)
product_list = [ p1, p2, p3]
result = ProductFilter. filter_by_color( product_list, Color. RED)
for r in result:
print ( r. name)
2.问题
目前规则实现了,按照颜色、尺寸去挑选衣服 如果需要新增一个按照颜色和尺寸同时挑选,此时就需要修改ProductFilter
这个类,违背了开闭原则
的初衷
3.优化
将挑选规则抽离出来,形成一个抽象类,这样一来,需要增加挑选规则时,只需要继承抽象类,并具体实现其匹配规则即可,不会影响原有的匹配规则 符合开闭原则
from abc import ABC, abstractmethod
from enum import Enum
class Color ( Enum) :
RED = 1
GREEN = 2
BLUE = 3
class Size ( Enum) :
SMALL = 1
MEDIUM = 2
LARGE = 3
class Product :
def __init__ ( self, name, color, size) :
self. name = name
self. color = color
self. size = size
class Specification ( ABC) :
@abstractmethod
def is_satisfied ( self, item) :
pass
def __and__ ( self, other) :
return AndSpecification( self, other)
def __or__ ( self, other) :
return AnySpecification( self, other)
class Filter ( ABC) :
@abstractmethod
def filter ( self, items, spec) :
pass
class ColorSpecification ( Specification) :
def __init__ ( self, color) :
self. color = color
def is_satisfied ( self, item: Product) :
return item. color == self. color
class SizeSpecification ( Specification) :
def __init__ ( self, size) :
self. size = size
def is_satisfied ( self, item: Product) :
return item. size == self. size
class ColorAndSizeSpecification ( Specification) :
def __init__ ( self, color, size) :
self. color = color
self. size = size
def is_satisfied ( self, item: Product) :
return item. size == self. size and item. color == self. color
class AndSpecification ( Specification) :
def __init__ ( self, * args) :
self. specs = args
def is_satisfied ( self, item: Product) :
return all ( map ( lambda spec: spec. is_satisfied( item) , self. specs) )
class AnySpecification ( Specification) :
def __init__ ( self, * args) :
self. specs = args
def is_satisfied ( self, item: Product) :
return any ( map ( lambda spec: spec. is_satisfied( item) , self. specs) )
class BetterFilter ( Filter) :
def filter ( self, items: [ Product] , spec: Specification) :
for item in items:
if spec. is_satisfied( item) :
yield item
if __name__ == '__main__' :
p1 = Product( "衬衫" , Color. RED, Size. MEDIUM)
p2 = Product( "牛仔裤" , Color. BLUE, Size. MEDIUM)
p3 = Product( "帽子" , Color. RED, Size. LARGE)
product_list = [ p1, p2, p3]
bf = BetterFilter( )
cs_spec = ColorAndSizeSpecification( color= Color. RED, size= Size. MEDIUM)
result = bf. filter ( items= product_list, spec= cs_spec)
for r in result:
print ( r. name, '-------->' , r. color)
c_spec = ColorSpecification( color= Color. RED)
s_spec = SizeSpecification( size= Size. MEDIUM)
print ( '---------------------------And组合-------------------' )
and_spec = AndSpecification( c_spec, s_spec)
result = bf. filter ( items= product_list, spec= and_spec)
for r in result:
print ( r. name, '-------->' , r. color)
print ( '---------------------------Or组合-------------------' )
and_spec = AnySpecification( c_spec, s_spec)
result = bf. filter ( items= product_list, spec= and_spec)
for r in result:
print ( r. name, '-------->' , r. color)
print ( '---------------------------__and__-------------------' )
sc_spec = c_spec & s_spec
result = bf. filter ( items= product_list, spec= sc_spec)
for r in result:
print ( r. name, '-------->' , r. color)
print ( '---------------------------__or__-------------------' )
sc_spec = c_spec | s_spec
result = bf. filter ( items= product_list, spec= sc_spec)
for r in result:
print ( r. name, '-------->' , r. color)
衬衫 - - - - - - - - > Color. RED
- - - - - - - - - - - - - - - - - - - - - - - - - - - And组合- - - - - - - - - - - - - - - - - - -
衬衫 - - - - - - - - > Color. RED
- - - - - - - - - - - - - - - - - - - - - - - - - - - Or组合- - - - - - - - - - - - - - - - - - -
衬衫 - - - - - - - - > Color. RED
牛仔裤 - - - - - - - - > Color. BLUE
帽子 - - - - - - - - > Color. RED
- - - - - - - - - - - - - - - - - - - - - - - - - - - __and__- - - - - - - - - - - - - - - - - - -
衬衫 - - - - - - - - > Color. RED
- - - - - - - - - - - - - - - - - - - - - - - - - - - __or__- - - - - - - - - - - - - - - - - - -
衬衫 - - - - - - - - > Color. RED
牛仔裤 - - - - - - - - > Color. BLUE
帽子 - - - - - - - - > Color. RED