程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python design pattern behavioral pattern visitor pattern

編輯:Python

Catalog

List of articles

  • Catalog
  • Visitor mode (Visitor Pattern)
  • Application scenarios
  • Code example

Visitor mode (Visitor Pattern)

Many elements are stored in the data structure , When we want to change a way of dealing with elements , Avoid modifying the data structure repeatedly . Then we are required to implement the code , Separate the processing of data , namely : The data class only provides an interface for data processing , The data processing interface is called visitor . that , When data with the same structure is faced with different processing results , We just need to create different visitors .

Visitor mode , Refers to the operation of elements acting on an object structure . Visitors can enable users to define a new operation without changing the classes in the structure .

advantage

  • It makes it easier to add new methods to a class in a complex class structure in the visitor class , namely : Simply add a new visitor method . If you don't use visitor mode , This requires adding a new method to each class .

  • The visitor concentrates the relevant methods in a specific visitor class , Other related methods are concentrated in another specific visitor class . in other words , Visitor subclasses are classified according to the type of method .

shortcoming

  • Add a specific new ConcreteElement Class is difficult . Because at this time, we need to be in every ConcreteVisitor Class ConcreteElement Class access method .

Application scenarios

  1. When the structure of an object , There are many types of objects with different interfaces , And when users want to perform operations that depend on specific classes on these objects , You need to use visitor mode . This is why the visitor pattern designs a different interface for each subclass being visited . in fact , If each accessed subclass has the same interface , Including construction method 、 Other methods 、 The parameters are consistent , Then the visitor class only needs to design an access method , This method contains a parameter used to distinguish different subclasses being accessed . for example : You can use the accessee base class as the parameter type . When the structure of an object contains many types of objects with different interfaces , Different access methods may provide different parameter types for the corresponding classes .

  2. When there are multiple different and unrelated operations that will act on these objects , When users don't want these operations to confuse these classes , You can use the visitor pattern to put related operations into separate classes , for example : In order to realize the calculation price method in each node class , You can put all the price calculation methods into one VisitPrice Class .

  3. The data type of the object rarely changes , But when operations need to be changed frequently or new operations need to be added , You can use visitor mode . conversely , If Element Subclasses of often change structure , for example : Need to add a new tax , This requires adding new access methods to the visitor class , therefore , Using visitor mode in this case is more expensive , Try not to use visitor mode .

Code example


The class diagram contains two series of classes :“Element class ” and “ Visitor class ”, The visitor class defines what is imposed on Element Operations on classes , by Element Class provides some functions . There can be many specific visitor classes , Each accomplishes a specific purpose , For example, a visitor class is to calculate the price , Another visitor class is to calculate the inventory quantity . Therefore, you need to define an abstract visitor parent Visitor And specific subclasses for various special purposes .Visitor Class must provide an operation for each node class , Access method , For example, get the price of the commodity object represented by each node .

Entity role composition :

  • Visitor: For each Element Object of declares an access operation . The name of the access operation should preferably include the name of the class being accessed , To confirm which specific class the access operation is specific to , Such as :visitFamilyNoChildren It is dedicated to service FamilyNoChildren Of .
  • ConcreteVisitor: Realization Visitor Declared operation . Each operation is implemented as part of the algorithm defined for the object of the corresponding class .ConcreteVisitor Provide the environment of the algorithm and store its local state .
  • Element: Some basic methods are defined , It contains methods to provide basic data , For example, some get() And set() Method . It is important to , Every Element Subclasses must define a receiver method , This method uses Visitor Is the parameter type :Accept(Visitor), Its function is to provide an interface for the interaction between the visited object and the visitor object .
  • ConcreteElement: Concrete Element Subclasses of , for example ElementA, This class contains a accept Method to receive the visitor object . in addition , This class may also define some other methods to help visitors realize some functions .
  • ObjectStructure: Provide a high-level interface , Allow visitors to visit Element Subclasses of . This class can contain a structure , for example ArrayList、Vector etc. , Provide what you want to access element A list of .

Example : The original financial data of listed companies :

  1. For accountants, we need to make various statements
  2. For the financial controller, it is necessary to analyze the company's performance
  3. For strategic consultants, we need to analyze industry changes
class Finance:
""" Financial data structure """
def __init__(self):
self.salesvolume = None # sales 
self.cost = None # cost 
self.history_salesvolume = None # Historical sales 
self.history_cost = None # Historical cost 
def set_salesvolume(self, value):
self.salesvolume = value
def set_cost(self, value):
self.cost = value
def set_history_salesvolume(self, value):
self.history_salesvolume = value
def set_history_cost(self, value):
self.history_cost = value
def accept(self, visitor):
pass
class Finance_year(Finance):
"""2018 Annual financial data """
def __init__(self, year):
Finance.__init__(self)
self.work = [] # Arrange the list of staff 
self.year = year
def add_work(self, work):
self.work.append(work)
def accept(self):
for obj in self.work:
obj.visit(self)
class Accounting:
""" Accounting """
def __init__(self):
self.ID = " accounting "
self.Duty = " Calculation report "
def visit(self, table):
print(' Fiscal year : {}'.format(table.year))
print(" My identity is : {} duty : {}".format(self.ID, self.Duty))
print(' Net profit for the year : {}'.format(table.salesvolume - table.cost))
print('------------------')
class Audit:
""" Chief financial officer """
def __init__(self):
self.ID = " Chief financial officer "
self.Duty = " Analyze performance "
def visit(self, table):
print(' Accounting Director year : {}'.format(table.year))
print(" My identity is : {} duty : {}".format(self.ID, self.Duty))
if table.salesvolume - table.cost > table.history_salesvolume - table.history_cost:
msg = " Up from the same period "
else:
msg = " Compared with the same period "
print(' The company's performance this year : {}'.format(msg))
print('------------------')
class Adviser:
""" Strategic adviser """
def __init__(self):
self.ID = " Strategic adviser "
self.Duty = " Formulate next year's strategy "
def visit(self, table):
print(' Strategic Advisor year : {}'.format(table.year))
print(" My identity is : {} duty : {}".format(self.ID, self.Duty))
if table.salesvolume > table.history_salesvolume:
msg = " The industry goes up , Expand production scale "
else:
msg = " Industry down , Reduce production scale "
print(' The company's performance this year : {}'.format(msg))
print('------------------')
class Work:
""" Work class """
def __init__(self):
self.works = [] # List of annual data to be processed 
def add_work(self, obj):
self.works.append(obj)
def remove_work(self, obj):
self.works.remove(obj)
def visit(self):
for obj in self.works:
obj.accept()
if __name__ == '__main__':
work = Work() # Plan and arrange finance 、 director 、 Consultant right 2018 Annual data processing 
# Instantiation 2018 Annual data structure 
finance_2018 = Finance_year(2018)
finance_2018.set_salesvolume(200)
finance_2018.set_cost(100)
finance_2018.set_history_salesvolume(180)
finance_2018.set_history_cost(90)
accounting = Accounting() # Instantiate accounting 
audit = Audit() # Instantiate the director 
adviser = Adviser() # Instantiate consultants 
finance_2018.add_work(accounting) # The accountant is arranged to 2018 Analysis schedule 
finance_2018.add_work(audit) # The director is arranged to 2018 Analysis schedule 
finance_2018.add_work(adviser) # The consultant arranged to 2018 Analysis schedule 
work.add_work(finance_2018) # add to 2018 Annual financial work arrangement 
work.visit()

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved