Visitor.cs
class Visitor: # abstract # Visitor::Visitor def visit_Employee(self, emp): raise NotImplementedError("%s.visit_Employee" %self.__class__.__name__) def visit_Boss(self, bos): raise NotImplementedError("%s.visit_Boss" %self.__class__.__name__)
- abstract に代えて、例外 NotImplementedError を生成しています。
VacationVisitor.cs
class VacationVisitor(Visitor): # Visitor::ConcreteVisitor def __init__(self): self.totalDays = 0 def visit_Employee(self, emp): # visit(Employee emp) self.totalDays += emp.vacDays def visit_Boss(self, bos): # visit(Boss bos) self.totalDays += bos.vacDays
《Note》参考文献との違い
- 引数の型で処理を選択する代わりに、メソッド名に実行時の型情報を埋め込みます。
bVacationVisitor.cs
class bVacationVisitor(Visitor): # Visitor::ConcreteVisitor def __init__(self): self.totalDays = 0 def visit_Employee(self, emp): # visit(Employee emp) self.totalDays += emp.vacDays def visit_Boss(self, bos): # visit(Boss bos) self.totalDays += bos.vacDays self.totalDays += bos.bonusDays
《Note》参考文献との違い
- 引数の型で処理を選択する代わりに、メソッド名に実行時の型情報を埋め込みます。
Form1.cs
class Visitor_WPF(Window): # Form # Visitor::ObjectStructure
- Form に代えて、Window を拡張しています。
def __init__(self, **args): self.InitializeComponent() self.init()
def init(self):
self.empls = # Employee
for e in [
Employee("Susan Bear", 55000, 12, 1),
Employee("Adam Gehr", 150000, 9, 0),
Employee("Fred Harris", 50000, 15, 2),
Employee("David Oakley", 57000, 12, 2),
Employee("Larry Thomas", 100000, 20, 6),
Boss("Leslie Susi", 175000, 16, 4, bonusDays=12),
Boss("Laurence Byerly", 35000, 17, 6, bonusDays=17),
]:
self.empls.append(e)
- 配列に代えて、list を利用しています。
def InitializeComponent(self): self.lsVac = self._lsVac() self.btCompute = self._btCompute() self._Controls()
def _lsVac(self): e = ListBox( Width=216, Height=156, # Size = Size(216, 186) ) Canvas.SetLeft(e, 32) # Location = Point(32, 32) Canvas.SetTop (e, 32) return e
- System.Windows.Forms.ListBox に代えて、System.Windows.Controls.ListBox を利用しています。
- Size に代えて、Width/Height に値を設定しています。
- Location に代えて、SetLeft/SetTop を利用しています。
def _btCompute(self): e = Button( Width=72, Height=24, # Size = Size(72, 24) Content="Compute", # Text ) Canvas.SetLeft(e, 88) # Location = Point(88, 232) Canvas.SetTop (e, 202) e.Click += self.btCompute_Click return e
- System.Windows.Forms.Button に代えて、System.Windows.Controls.Button を利用しています。
- Size に代えて、Width/Height に値を設定しています。
- Location に代えて、SetLeft/SetTop を利用しています。
def _Controls(self): self.Content = Canvas() self.Width = 292 # ClientSize = Size(292, 273) self.Height = 273 for e in self.lsVac, self.btCompute: self.Content.Children.Add(e) # .Controls self.Text = "Visitor demo"
- Canvas 内に、各コントロールを配置します。
- ClientSize に代えて、Width/Height に値を設定しています。
- Controls に代えて、Children に子要素を追加しています。
def btCompute_Click(self, sender, e): vac = VacationVisitor() bvac = bVacationVisitor() for e in self.empls: e.accept(vac) e.accept(bvac) self.lsVac.Items.Add("Total vacation days=%s" %vac.totalDays) self.lsVac.Items.Add("Total boss vacation days=%s"%bvac.totalDays)
Visitor_WPF.py
- WPF アプリケーションとして、IronPython で実現した事例を紹介します。
# -*- coding: utf-8 -*- #=============================================================================== # Copyright (C) 2000-2008, 小泉ひよ子とタマゴ倶楽部 # # History: Design Pattern # 2008/01/25, IronPython 1.1.1 (download) # 2008/08/22, IronPython 1.1.2 (download) # 2008/01/15, ver.1.0, Windows Forms # 2008/03/21, ver.2.0, WPF # 2008/09/28, ver.2.1, IronPython 1.1.2 #=============================================================================== import clr # clr.AddReference("PresentationFramework") clr.AddReference("WindowsBase") from System.Windows import * from System.Windows.Controls import *
Employee.cs
class Employee: # Visitor::ConcreteElement def __init__(self, name, salary, vDays, sDays): self.name = name self.salary = salary self.sickDays = sDays self.vacDays = vDays
def accept(self, v):
source = "v.visit_%s(self)"%self.__class__.__name__
eval(source) ; print source
《Note》参考文献との違い
- 引数の型で処理を選択する代わりに、メソッド名に実行時の型情報を埋め込みます。
Boss.cs
class Boss(Employee): # Visitor::ConcreteElement def __init__(self, name, salary, vdays, sdays, bonusDays=None): Employee.__init__(self, name, salary, vdays, sdays) self.bonusDays = bonusDays
def accept(self, v):
source = "v.visit_%s(self)"%self.__class__.__name__
eval(source) ; print source
《Note》参考文献との違い
- 引数の型で処理を選択する代わりに、メソッド名に実行時の型情報を埋め込みます。
《参考文献》
- C# Design Patterns 31. The Visitor Pattern.