<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7513445162961451638</id><updated>2024-08-29T13:35:48.348+09:00</updated><category term="python"/><category term="デザインパターン"/><category term="iPhone"/><category term="その他"/><category term="Cocoa"/><category term="MacOSX"/><category term="Xcode"/><category term="ゴミ"/><category term="書評"/><category term="Android"/><category term="R/RStan"/><category term="haskell"/><category term="javascript"/><category term="subversion"/><category term="vim"/><category term="コード進行"/><title type='text'>BLOG.</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>42</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-7163944671704908656</id><published>2018-07-07T14:25:00.001+09:00</published><updated>2018-07-07T14:25:43.488+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="書評"/><title type='text'>水やりはいつも深夜だけど / 窪美澄</title><content type='html'>&lt;u&gt;水やりはいつも深夜だけど / 窪美澄（2014.11）&lt;/u&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;5篇の短編集で、どの作品も家族を主題としたありがちな内容であるが、時々ぐっと心臓を押されるようなリアルさがある。2篇目の「サボテンの咆哮」が個人的に一番好き。&lt;br /&gt;
&lt;br /&gt;
&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as4&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;ref=as_ss_li_til&amp;amp;asins=4041021340&amp;amp;linkId=8c4eef2af9a5ea444dd37ad7d0af51a9&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
以下、Amazon.comより&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;h3 style=&quot;background-color: white; box-sizing: border-box; clear: left; color: #333333; font-family: &amp;quot;Hiragino Kaku Gothic Pro W3&amp;quot;, &amp;quot;Hiragino Kaku Gothic ProN&amp;quot;, Meiryo, sans-serif; font-size: 1.23em; font-weight: normal; line-height: 1.255; margin: 0.75em 0px 0.375em -15px; padding: 0px 0px 4px;&quot;&gt;
内容（「BOOK」データベースより）&lt;/h3&gt;
&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: &amp;quot;Hiragino Kaku Gothic Pro W3&amp;quot;, &amp;quot;Hiragino Kaku Gothic ProN&amp;quot;, Meiryo, sans-serif; font-size: small; margin-bottom: 1em; margin-left: 1em; margin-top: 0em; padding: 0px;&quot;&gt;
セレブママとしてブログを更新しながら、周囲の評価に怯える主婦。仕事が忙しく子育てに参加できず、妻や義理の両親からうとまれる夫。自分の娘の発達障害を疑い、自己嫌悪に陥る主婦。出産を経て変貌した妻に違和感を覚え、若い女に傾いてしまう男。父の再婚により突然やってきた義母に戸惑う、高一女子。同じ幼稚園に子どもを通わせる家々の、もがきながらも前を向いて生きる姿を描いた、魂ゆさぶる5つの物語。&lt;/div&gt;
&lt;h3 style=&quot;background-color: white; box-sizing: border-box; clear: left; color: #333333; font-family: &amp;quot;Hiragino Kaku Gothic Pro W3&amp;quot;, &amp;quot;Hiragino Kaku Gothic ProN&amp;quot;, Meiryo, sans-serif; font-size: 1.23em; font-weight: normal; line-height: 1.255; margin: 0.75em 0px 0.375em -15px; padding: 0px 0px 4px;&quot;&gt;
著者略歴 (「BOOK著者紹介情報」より)&lt;/h3&gt;
&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: &amp;quot;Hiragino Kaku Gothic Pro W3&amp;quot;, &amp;quot;Hiragino Kaku Gothic ProN&amp;quot;, Meiryo, sans-serif; font-size: small; margin-bottom: 1em; margin-left: 1em; margin-top: 0em; padding: 0px;&quot;&gt;
窪/美澄&lt;br style=&quot;box-sizing: border-box;&quot; /&gt;1965年、東京都生まれ。短大中退後、広告制作会社、フリーの編集ライターを経て、2009年、「ミクマリ」で第8回女による女のためのR‐18文学賞大賞を受賞しデビュー。11年、受賞作を収録した『ふがいない僕は空を見た』で第24回山本周五郎賞を受賞、本屋大賞第2位に選ばれた。12年、『晴天の迷いクジラ』で第3回山田風太郎賞受賞(本データはこの書籍が刊行された当時に掲載されていたものです)&lt;/div&gt;
&lt;/blockquote&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/7163944671704908656/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2018/07/blog-post.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/7163944671704908656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/7163944671704908656'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2018/07/blog-post.html' title='水やりはいつも深夜だけど / 窪美澄'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-9177490934024390927</id><published>2018-07-06T21:37:00.001+09:00</published><updated>2018-07-06T21:37:49.668+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="書評"/><title type='text'>仕事ができる人は「負け方」がうまい / 宋文洲</title><content type='html'>&lt;u&gt;仕事ができる人は「負け方」がうまい / 宋文洲（2009.9）&lt;/u&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;著者が人間として出来た方であることが伝わります。「モチベーションは業績次第」など気づきが得られたテーマも多くありました。&lt;br /&gt;
&lt;br /&gt;
&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as4&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;ref=as_ss_li_til&amp;amp;asins=4046214872&amp;amp;linkId=cb6df2c1cd522f4bb9d5fa985f681e48&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;

&lt;br /&gt;
&lt;br /&gt;
以下、amazon.comより&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;h3 style=&quot;background-color: white; box-sizing: border-box; clear: left; color: #333333; font-family: &amp;quot;Hiragino Kaku Gothic Pro W3&amp;quot;, &amp;quot;Hiragino Kaku Gothic ProN&amp;quot;, Meiryo, sans-serif; font-size: 1.23em; font-weight: normal; line-height: 1.255; margin: 0.75em 0px 0.375em -15px; padding: 0px 0px 4px;&quot;&gt;
内容紹介&lt;/h3&gt;
&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: &amp;quot;Hiragino Kaku Gothic Pro W3&amp;quot;, &amp;quot;Hiragino Kaku Gothic ProN&amp;quot;, Meiryo, sans-serif; font-size: small; margin-bottom: 1em; margin-left: 1em; margin-top: 0em; padding: 0px;&quot;&gt;
「失業は怖くない」「世論を信じるな」「面白さは『マナー』」「差別が全部悪いとは限らない」――。ソフトブレーン創業者の著者が送る、歯に衣着せぬ人生指南。現代人の仕事に、人生に必読の1冊!&lt;/div&gt;
&lt;h3 style=&quot;background-color: white; box-sizing: border-box; clear: left; color: #333333; font-family: &amp;quot;Hiragino Kaku Gothic Pro W3&amp;quot;, &amp;quot;Hiragino Kaku Gothic ProN&amp;quot;, Meiryo, sans-serif; font-size: 1.23em; font-weight: normal; line-height: 1.255; margin: 0.75em 0px 0.375em -15px; padding: 0px 0px 4px;&quot;&gt;
著者について&lt;/h3&gt;
&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: &amp;quot;Hiragino Kaku Gothic Pro W3&amp;quot;, &amp;quot;Hiragino Kaku Gothic ProN&amp;quot;, Meiryo, sans-serif; font-size: small; margin-bottom: 1em; margin-left: 1em; margin-top: 0em; padding: 0px;&quot;&gt;
ソフトブレーン(株)マネージメント・アドバイザー。1963年中国山東省生まれ。85年に北海道大学大学院に国費留学。92年28歳の時にソフトブレーンを創業。2005年6月に同社東証1部上場。06年8月会長を退任し現職。著書は、ベストセラー『やっぱり変だよ日本の営業』ほか多数。&lt;/div&gt;
&lt;/blockquote&gt;
</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/9177490934024390927/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2018/07/blog-post_6.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/9177490934024390927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/9177490934024390927'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2018/07/blog-post_6.html' title='仕事ができる人は「負け方」がうまい / 宋文洲'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-9064165926081174570</id><published>2017-04-23T00:10:00.000+09:00</published><updated>2017-05-01T14:00:00.940+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="R/RStan"/><title type='text'>RStan(1)： Windows で RStan の環境を構築する</title><content type='html'>お仕事でもお世話になっているRStan。とあるきっかけがあって自分のPCでも環境を整備しようと思いたちました。ブログを書くのも６~７年ぶり。&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
基本的に↓の要約です。&lt;/div&gt;
&lt;div&gt;
&lt;a href=&quot;https://github.com/stan-dev/rstan/wiki/RStan-Getting-Started-(Japanese)&quot;&gt;https://github.com/stan-dev/rstan/wiki/RStan-Getting-Started-(Japanese)&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;Rのインストール (R 3.3.3 for widows)&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;私の場合は昔入れた古いRがあったので、これをまずアンインストールしました。&lt;/li&gt;
&lt;li&gt;その後、&lt;a href=&quot;https://cran.ism.ac.jp/&quot;&gt;https://cran.ism.ac.jp/&lt;/a&gt; から&amp;nbsp;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Download R for Windows → base&lt;/li&gt;
&lt;li&gt;ここで普通は一番上のインストーラへのリンクをクリックしますが、後述するRtoolsのバージョンの関係で、&lt;span style=&quot;color: red;&quot;&gt;一つ前のバージョンをインストールしました。&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;下の方の Previous releases から R3.3.3 を選択しダウンロード。&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;li&gt;インストーラは、すべてデフォルト設定で。&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;Rをインストールした実感を得る&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;言うまでもなく本項は省略可能です。&lt;/li&gt;
&lt;li&gt;R x64 3.3.3　を起動する。コンソール画面が出てくる。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://d.hatena.ne.jp/isseing333/20100515/1273928356&quot;&gt;http://d.hatena.ne.jp/isseing333/20100515/1273928356&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;↑こちらのサイトにある「&lt;a class=&quot;keyword&quot; href=&quot;http://a/&quot; style=&quot;border-bottom: 1px solid rgb(222, 222, 222); color: #333333; font-family: &amp;quot;Courier New&amp;quot;; font-size: 13.248px; text-decoration-line: none;&quot;&gt;set.seed&lt;/a&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #555555; font-family: &amp;quot;courier new&amp;quot;; font-size: 13.248px;&quot;&gt;(1)&lt;/span&gt;」から始まる部分をコピーして、コンソール画面に貼り付ける。&lt;/li&gt;
&lt;li&gt;グラフが出てきて、おおおっとなる。&lt;/li&gt;
&lt;li&gt;Rを終了する。workspaceの保存はどちらでも。&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;Rtoolsのインストール (Rtools 3.3)&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Windows用のRのツールチェイン。MinGWなどが含まれます。導入する意味が分からないまま、言われるままにインストール。（おそらく、StanにC++コンパイラが必要だからではないかと予想）&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cran.ism.ac.jp/&quot;&gt;https://cran.ism.ac.jp/&lt;/a&gt;&amp;nbsp;へ戻り、Rtoolsへ。&lt;/li&gt;
&lt;li&gt;インストールしたRとコンパチでFrozenされているバージョンをダウンロード。&lt;/li&gt;
&lt;li&gt;インストーラは、ほとんどデフォルト設定ですが、環境変数PATHの更新のところだけチェックを入れます。（デフォルトでチェックが入っていないのが謎）&lt;/li&gt;
&lt;li&gt;1GB近くデータをインストールされます。気長に待ちます。&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;（余談ですが、RtoolsはC:\直下にフォルダを作ってインストールします。気持ち悪いと思いつつもターゲットパスは変えませんでしたが、気持ち悪いですね）&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Rtoolsが適切にインストールされたか確認します。以下はR上での確認ですがコマンドプロンプト等でやっても同じはずです。&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;Rを再起動&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;gt; Sys.getenv(&quot;PATH&quot;)　→RtoolsがPATHに含まれていればOK&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;gt; system(&#39;g++ -v&#39;)　→インストールしたgccが呼び出されていればOK（gcc 4.6.3でした）&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;gt; system(&#39;where make&#39;)　→同上&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;コンパイラ周りの設定 (任意)&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;元サイトでは「やらなくて良い」とありますが、原文だと「強く推奨する」とあったのでやっておきました。&lt;span style=&quot;font-size: x-small;&quot;&gt;やっていることは、コンパイラオプションを最適化したり、推奨されるワーニングオプションを設定したり、といったもの。設定ファイルを作成（編集）しているだけです。&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/stan-dev/rstan/wiki/Installing-RStan-on-Windows#configuration&quot;&gt;https://github.com/stan-dev/rstan/wiki/Installing-RStan-on-Windows#configuration&lt;/a&gt;　にある、dotRから始まる８行と、cat(&#39;Sys.から始まる３行と、cat(&lt;span class=&quot;pl-s&quot; style=&quot;box-sizing: border-box; color: #183691; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;&lt;span class=&quot;pl-pds&quot; style=&quot;box-sizing: border-box;&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;pl-cce&quot; style=&quot;box-sizing: border-box;&quot;&gt;\n&lt;/span&gt;CXXFLAGS&lt;/span&gt;から始まる２行とを、それぞれRコンソールにコピペするだけ。&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;RStudioのインストール (RStudio 1.0.143)&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;RのIDE環境。必要なのか分かりませんが、勧められるままに入れました。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.rstudio.com/products/rstudio/&quot;&gt;https://www.rstudio.com/products/rstudio/&lt;/a&gt; からダウンロード＆インストール。&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;RStanパッケージのインストール (RStan 2.15.1)&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Rを起動し、コンソールに以下をコピペ。&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;&amp;gt; install.packages(&lt;span class=&quot;pl-s&quot; style=&quot;box-sizing: border-box; color: #183691; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;&lt;span class=&quot;pl-pds&quot; style=&quot;box-sizing: border-box;&quot;&gt;&#39;&lt;/span&gt;rstan&lt;span class=&quot;pl-pds&quot; style=&quot;box-sizing: border-box;&quot;&gt;&#39;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #f6f8fa; color: #24292e; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;pl-v&quot; style=&quot;box-sizing: border-box; color: #ed6a43; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;repos&lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;box-sizing: border-box; color: #a71d5d; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pl-s&quot; style=&quot;box-sizing: border-box; color: #183691; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;&lt;span class=&quot;pl-pds&quot; style=&quot;box-sizing: border-box;&quot;&gt;&#39;&lt;/span&gt;https://cloud.r-project.org/&lt;span class=&quot;pl-pds&quot; style=&quot;box-sizing: border-box;&quot;&gt;&#39;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #f6f8fa; color: #24292e; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;pl-v&quot; style=&quot;box-sizing: border-box; color: #ed6a43; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;box-sizing: border-box; color: #a71d5d; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pl-c1&quot; style=&quot;box-sizing: border-box; color: #0086b3; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;TRUE&lt;/span&gt;&lt;span style=&quot;background-color: #f6f8fa; color: #24292e; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;BH, Rcpp, RUnit, ggplot2などもインストールされます。&lt;/li&gt;
&lt;li&gt;RStanが動作することを確認します。4行目以下は一例。&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;&amp;gt; library(&lt;span class=&quot;pl-smi&quot; style=&quot;box-sizing: border-box; color: #333333; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;rstan&lt;/span&gt;&lt;span style=&quot;background-color: #f6f8fa; color: #24292e; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&amp;gt; rstan_options(&lt;span class=&quot;pl-v&quot; style=&quot;box-sizing: border-box; color: #ed6a43; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;auto_write&lt;/span&gt;&lt;span style=&quot;background-color: #f6f8fa; color: #24292e; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;box-sizing: border-box; color: #a71d5d; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;background-color: #f6f8fa; color: #24292e; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pl-c1&quot; style=&quot;box-sizing: border-box; color: #0086b3; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;TRUE&lt;/span&gt;&lt;span style=&quot;background-color: #f6f8fa; color: #24292e; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&amp;gt; options(&lt;span class=&quot;pl-v&quot; style=&quot;box-sizing: border-box; color: #ed6a43; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;mc.cores&lt;/span&gt;&lt;span style=&quot;background-color: #f6f8fa; color: #24292e; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;box-sizing: border-box; color: #a71d5d; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;background-color: #f6f8fa; color: #24292e; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pl-e&quot; style=&quot;box-sizing: border-box; color: #795da3; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;parallel&lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;box-sizing: border-box; color: #a71d5d; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;background-color: #f6f8fa; color: #24292e; font-family: , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: 13.6px;&quot;&gt;detectCores())&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&amp;gt; sf &amp;lt;- stan_demo(&quot;pump&quot;)　→ダウンロードに関する選択は１を。&lt;/li&gt;
&lt;li&gt;&amp;gt; pairs(sf, pars=c(&quot;alpha&quot;,&quot;beta&quot;))&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;それっぽいグラフが出てきます。&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIUa8Eqh4VfvKeKzlwqGSa_v8nbGOq5FFwnherKpKFW8B88OZ_GuYQFZfHyz-t7lg2jdRPwxyaHBBJ7L2bX-cgE6GQQTSlnddBzGRY23WvhjCyjRnuwYZbLtFLuBPXJsMVA2hMqpXJpcAO/s1600/Rplot+pump+alpha-beta.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;308&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIUa8Eqh4VfvKeKzlwqGSa_v8nbGOq5FFwnherKpKFW8B88OZ_GuYQFZfHyz-t7lg2jdRPwxyaHBBJ7L2bX-cgE6GQQTSlnddBzGRY23WvhjCyjRnuwYZbLtFLuBPXJsMVA2hMqpXJpcAO/s320/Rplot+pump+alpha-beta.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/9064165926081174570/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2017/04/rstan1-windows-10-rstan.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/9064165926081174570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/9064165926081174570'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2017/04/rstan1-windows-10-rstan.html' title='RStan(1)： Windows で RStan の環境を構築する'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIUa8Eqh4VfvKeKzlwqGSa_v8nbGOq5FFwnherKpKFW8B88OZ_GuYQFZfHyz-t7lg2jdRPwxyaHBBJ7L2bX-cgE6GQQTSlnddBzGRY23WvhjCyjRnuwYZbLtFLuBPXJsMVA2hMqpXJpcAO/s72-c/Rplot+pump+alpha-beta.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-1994696313509313124</id><published>2011-02-25T21:18:00.002+09:00</published><updated>2011-02-25T21:39:13.976+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="haskell"/><title type='text'>斜蹴、襲来</title><content type='html'>Haskellを勉強していこうと思います。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:hs&quot;&gt;--euler #001 / recursion
let fizzbuzz a = (a `mod` 3 == 0) || (a `mod` 5 == 0)
putStrLn(show(sum(filter (fizzbuzz) [1..999])))
&lt;/pre&gt;&lt;br /&gt;
referring&amp;nbsp;&lt;a href=&quot;http://projecteuler.net/index.php?section=problems&amp;amp;id=1&quot;&gt;Problem 1 - Project Euler&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/1994696313509313124/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2011/02/haskell.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/1994696313509313124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/1994696313509313124'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2011/02/haskell.html' title='斜蹴、襲来'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-8541907286568459307</id><published>2011-02-25T17:48:00.006+09:00</published><updated>2011-03-04T12:26:49.822+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="コード進行"/><title type='text'>自問自答 - スネオヘアー - コード進行</title><content type='html'>&lt;pre style=&quot;line-height:2em;&quot;&gt;Original Key Db / Capo. 1 / Play in C / Tempo 97

[intro]
C &quot; &quot; &quot; | G &quot; &quot; &quot; | Am7 &quot; &quot; &quot; | F &quot; &quot; &quot; |
C &quot; C/B &quot; | G/A# &quot; Am &quot; |
F &quot; &quot; &quot; | G# &quot; &quot; &quot; | C &quot; &quot; &quot; | F &quot; G &quot; |

[verse]
C &quot; &quot; &quot; | C &quot; &quot; &quot; | Am7 &quot; &quot; &quot; | Am7 &quot; &quot; &quot; |
F &quot; &quot; &quot; | Fm &quot; &quot; &quot; | C &quot; &quot; &quot; | E7 &quot; &quot; &quot; |
F &quot; &quot; &quot; | F &quot; &quot; &quot; | C &quot; &quot; &quot; | Am7 &quot; &quot; &quot; |
F &quot; &quot; &quot; | F &quot; &quot; &quot; | G &quot; &quot; &quot; | G &quot; &quot; &quot; |

[chorus]
C &quot; &quot; &quot; | C &quot; &quot; &quot; | Am7 &quot; &quot; &quot; | E7 &quot; &quot; &quot; |
F &quot; &quot; &quot; | G &quot; &quot; &quot; | C &quot; &quot; &quot; | C &quot; &quot; &quot; |

[bridge]
F &quot; &quot; &quot; | G &quot; &quot; &quot; | C &quot; &quot; &quot; | C &quot; &quot; &quot; |
F &quot; &quot; &quot; | G &quot; &quot; &quot; | C &quot; &quot; &quot; | F &quot; G &quot; |
(1st: go back to [verse])

[chorus2]
C &quot; &quot; &quot; | C &quot; &quot; &quot; | Am7 &quot; &quot; &quot; | E7 &quot; &quot; &quot; |
F &quot; &quot; &quot; | G &quot; &quot; &quot; |
C &quot; &quot; &quot; | C &quot; &quot; &quot; | Am7 &quot; &quot; &quot; | E7 &quot; &quot; &quot; |
F &quot; &quot; &quot; | G &quot; &quot; &quot; | C &quot; &quot; &quot; | C &quot; &quot; &quot; |

[pre-outro]
F &quot; &quot; &quot; | G &quot; &quot; &quot; | C &quot; &quot; &quot; | Am7 &quot; &quot; &quot; |
F &quot; &quot; &quot; | E7 &quot; &quot; &quot; |
Am7 &quot; &quot; &quot; | G &quot; &quot; &quot; | F &quot; &quot; &quot; | E7 &quot; &quot; &quot; |
( Am7 &quot; &quot; &quot; | G &quot; &quot; &quot; | F &quot; &quot; &quot; | G &quot; &quot; &quot; | )
C &quot; C/B &quot; | G/A# &quot; Am &quot; | F &quot; G &quot; |
C &quot; C/B &quot; | G/A# &quot; Am &quot; | F &quot; G &quot; |
C &quot; C/B &quot; | G/A# &quot; Am &quot; | F &quot; G &quot; |
C &quot; C/B &quot; | G/A# &quot; Am &quot; | F &quot; G &quot; |

[outro]
C &quot; &quot; &quot; | G &quot; &quot; &quot; | Am7 &quot; &quot; &quot; | F &quot; &quot; &quot; |
C &quot; &quot; &quot; | G &quot; &quot; &quot; | Am7 &quot; &quot; &quot; | F &quot; &quot; &quot; |
C &quot; &quot; &quot; | G &quot; &quot; &quot; | Am7 &quot; &quot; &quot; | F &quot; &quot; &quot; |
...

&lt;/pre&gt;&lt;br /&gt;
referring: &lt;a href=&quot;http://gakufu.gakki.me/m/data/DT10234.html&quot;&gt;「自問自答」 | スネオヘアー　歌詞/コード検索サービス | 楽器.me&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;iframe title=&quot;BestMetronome.com - simple metronome&quot; width=&quot;440&quot; height=&quot;406&quot; src=&quot;http://bestmetronome.com/simpleembedobject&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
Metronome by &lt;a href=&quot;http://bestmetronome.com&quot;&gt;BestMetronome.com&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/8541907286568459307/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2011/02/blog-post_25.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/8541907286568459307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/8541907286568459307'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2011/02/blog-post_25.html' title='自問自答 - スネオヘアー - コード進行'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-4474625831568361721</id><published>2011-02-23T08:27:00.000+09:00</published><updated>2011-02-23T08:27:14.060+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="その他"/><title type='text'>なぜ Null は要らない子なのか</title><content type='html'>という記事があって面白かったので。&lt;br /&gt;
&lt;br /&gt;
一番はやはり&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;Nullチェックを一々コードに埋め込むのは冗長だ&lt;/span&gt;ということに尽きる。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;u&gt;例1&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Null云々とは少し違うが、例えば Door クラスを作ったとして、以下の2つのプロパティを書いたとする。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;class Door
    private bool isShut
    private bool isLocked
&lt;/pre&gt;&lt;br /&gt;
ここで、&lt;br /&gt;
&lt;pre&gt;!isShut &amp;amp;&amp;amp; isLocked&lt;/pre&gt;という状態は有り得ないので、Doorクラスを扱う際は『常に』気を使う必要がある。&lt;br /&gt;
例えば、isShutのsetter内に、falseにセットするときに次のように書いたり。。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;if(newval==true){
    this.isShut = true
}
else{
    this.isShut = false
    if(this.isLocked){
        this.isLocked = false
    }
}
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;&lt;u&gt;例2&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
あるいは、次のようなPersonクラスに、名前の総文字数を計算するメソッドを用意することを考える:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;class Person
    private string FirstName
    private string MiddleName
    private string LastName
&lt;/pre&gt;&lt;br /&gt;
当然ながら、string型は Null にもなるし、空文字にもなる。&lt;br /&gt;
ので、次のメソッドは不十分で:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;let TotalNumCharsInPersonsName(p:Person) =
    p.FirstName.Length + p.MiddleName.Length + p.LastName.Length&lt;/pre&gt;&lt;br /&gt;
こんな風に書かなきゃいけない:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;let TotalNumCharsInPersonsName(p:Person) =
    (if p.FirstName=null then 0 else p.FirstName.Length)
    + (if p.MiddleName=null then 0 else p.MiddleName.Length)
    + (if p.LastName=null then 0 else p.LastName.Length)&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;&lt;u&gt;解&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
これだけ見ても、どんだけアホなんだと言いたくなる。&lt;br /&gt;
(でもプログラムを長く書いていると、もう慣れてしまってそのアホさに鈍感になってくる。)&lt;br /&gt;
じゃあどうやって解決するのか。それは、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;新しい型をつくる&lt;/span&gt;ことだ。&lt;br /&gt;
&lt;br /&gt;
例1なら、こうする。&lt;br /&gt;
&lt;pre&gt;type DoorState =
    | Open | ShutAndUnlocked | ShutAndLocked

# then I could define
class Door
    private DoorState state
&lt;/pre&gt;&lt;br /&gt;
例2なら、こうする。&lt;br /&gt;
(ここにstringはnon-nullであり、Option&amp;lt;T&amp;gt;&lt;t&gt;は(T型の値 or null)である)&lt;br /&gt;
&lt;/t&gt;&lt;br /&gt;
&lt;pre&gt;class Person
    private string FirstName
    private Option&amp;lt;string&amp;gt;&lt;string&gt; MiddleName
    private string LastName

let TotalNumCharsInPersonsName(p:Person) =
    let middleLen = match p.MiddleName with
                    | None -&amp;gt; 0
                    | Some(s) -&amp;gt; s.Length
    p.FirstName.Length + middleLen + p.LastName.Length&lt;/string&gt;&lt;/pre&gt;&lt;br /&gt;
もうここにアホさは残っていない。本質的に必要な処理だけをコーディングしている。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;u&gt;結論&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;Nullはコードを不要に複雑にする&lt;/span&gt;。複雑さは全てのソフトウェアにおいて『敵』であり、我々は常にこれを排除するよう努めなきゃいかん。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;元記事&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;http://stackoverflow.com/questions/3989264/best-explanation-for-languages-without-null&quot;&gt;http://stackoverflow.com/questions/3989264/best-explanation-for-languages-without-null&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/4474625831568361721/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2011/02/null.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/4474625831568361721'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/4474625831568361721'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2011/02/null.html' title='なぜ Null は要らない子なのか'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-8462872380569866679</id><published>2011-02-15T10:21:00.000+09:00</published><updated>2011-02-15T10:21:35.077+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="その他"/><title type='text'>ターミナルに切り替えずにコマンドを実行&amp;結果確認</title><content type='html'>&lt;b&gt;&lt;u&gt;以前の俺&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;u&gt;&lt;br /&gt;
&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
エディタでコード書いて、alt-tabでターミナルひらいて、↑押して実行して結果を確認して、またエディタに戻って、あぁ、またブラウザ開いてしまった、…エディタに戻って、コード書いて、ターミナルに…ああまたブラウザに以下略&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;u&gt;Vim使うようになってから&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;エディタからコマンドを実行可能に&lt;/li&gt;
&lt;li&gt;でも以前の実行結果が見たい時があって困る&lt;/li&gt;
&lt;li&gt;実行結果を大量に吐くコード、一度に全部吐かないコードだとさらに困る&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;b&gt;&lt;u&gt;新たな解&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;u&gt;&lt;br /&gt;
&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.codeography.com/2011/02/14/focus-on-a-test-in-vim.html&quot;&gt;Focus on a test in Vim — Codeography&lt;/a&gt;&lt;br /&gt;
tail コマンドを利用した妙技を発見。すなわち&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;エディタからコマンド実行するときにファイルにリダイレクト&lt;/li&gt;
&lt;li&gt;そのファイルを tail -f で開いとく&lt;/li&gt;
&lt;li&gt;エディタの隣にターミナル置いておけば…Wow!!&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;u&gt;注意&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
モニタが小さいとあまり恩恵がない</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/8462872380569866679/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2011/02/blog-post.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/8462872380569866679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/8462872380569866679'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2011/02/blog-post.html' title='ターミナルに切り替えずにコマンドを実行&amp;結果確認'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-1425388276805047263</id><published>2011-02-06T19:23:00.000+09:00</published><updated>2011-02-06T19:23:48.246+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="その他"/><title type='text'>Chromeのマルチ検索機能</title><content type='html'>&lt;a href=&quot;http://techblog.ecstudio.jp/tips/useful_search_by_google-chrome.html&quot;&gt;Google Chrome から好きな検索エンジンで検索する方法&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: large;&quot;&gt;ちょ&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
こんな便利すぎる機能があったのか…！&lt;br /&gt;
速攻で英辞郎とstackoverflow登録した</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/1425388276805047263/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2011/02/chrome.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/1425388276805047263'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/1425388276805047263'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2011/02/chrome.html' title='Chromeのマルチ検索機能'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-3438665427714397286</id><published>2011-02-06T16:47:00.000+09:00</published><updated>2011-02-06T16:47:03.940+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ゴミ"/><title type='text'>Biham-Middleton-Levine traffic model</title><content type='html'>ネットサーフィンしていて見つけた記事。&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://en.wikipedia.org/wiki/User:Purpy_Pupple/BML&quot;&gt;User:Purpy Pupple/BML - Wikipedia, the free encyclopedia&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
交通モデルに自己組織化。&lt;br /&gt;
シンプルなモデルながらスケールフリーな結果。&lt;br /&gt;
うーん、何に応用できるんだろう。</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/3438665427714397286/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2011/02/biham-middleton-levine-traffic-model.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/3438665427714397286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/3438665427714397286'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2011/02/biham-middleton-levine-traffic-model.html' title='Biham-Middleton-Levine traffic model'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-8804705268073647743</id><published>2011-01-28T14:22:00.001+09:00</published><updated>2011-01-28T14:23:11.493+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="MacOSX"/><title type='text'>(Mac OS X) コマンドラインからゴミ箱へ</title><content type='html'>$&amp;nbsp;&lt;a href=&quot;http://hasseg.org/trash/&quot;&gt;trash&lt;/a&gt;&amp;nbsp;file-not-in-use.dat</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/8804705268073647743/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2011/01/mac-os-x-rm.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/8804705268073647743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/8804705268073647743'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2011/01/mac-os-x-rm.html' title='(Mac OS X) コマンドラインからゴミ箱へ'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-624762422889429706</id><published>2011-01-27T14:54:00.001+09:00</published><updated>2011-01-27T21:28:35.729+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ゴミ"/><title type='text'>SuperMailer というサービスが面白い</title><content type='html'>&lt;a href=&quot;http://supermailer.jp/&quot;&gt;フリーメールを2秒で取得 - Super Mailer（スーパーメイラー）&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
どのフリーメーラーも、初期登録のストレスを極力減らして登録数を増やそうとしていると思う。&lt;br /&gt;
この SuperMailer は、username（@より前の部分）だけ入力すればメールアドレスが取得できる。&lt;br /&gt;
&lt;br /&gt;
まさにアイデアの勝利。ただし名前はダサい</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/624762422889429706/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2011/01/supermailer.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/624762422889429706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/624762422889429706'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2011/01/supermailer.html' title='SuperMailer というサービスが面白い'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-5673067577811169915</id><published>2010-12-22T09:58:00.000+09:00</published><updated>2010-12-22T09:58:02.432+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="iPhone"/><title type='text'>そういえばブログに書いてなかったけど</title><content type='html'>iPhoneアプリ作りました。&lt;br /&gt;
&lt;a href=&quot;http://itunes.apple.com/jp/app/id407479350&quot;&gt;http://itunes.apple.com/jp/app/id407479350&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/5673067577811169915/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/12/blog-post.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/5673067577811169915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/5673067577811169915'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/12/blog-post.html' title='そういえばブログに書いてなかったけど'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-8517829537269028605</id><published>2010-12-15T23:18:00.007+09:00</published><updated>2011-02-24T01:37:05.588+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="iPhone"/><category scheme="http://www.blogger.com/atom/ns#" term="subversion"/><category scheme="http://www.blogger.com/atom/ns#" term="Xcode"/><title type='text'>subversion-controlledなXcode Projectの新規作成手順</title><content type='html'>何回やっても忘れるのでもう備忘録を付けます。&lt;br /&gt;
(Xcodeと銘打ってますが手順そのものは汎用的だと思います。どちらかと言うとsubversionの備忘録です)&lt;br /&gt;
抜けとかがあったら指摘お願いします。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;u&gt;前提&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;line-height: 2em;&quot;&gt;&lt;li&gt;既存 svn リポジトリ:&amp;nbsp;http://your.svnhost/&lt;/li&gt;
&lt;li&gt;プロジェクトのURL: http://your.svnhost/path/to/project/NewProject/&lt;/li&gt;
&lt;li&gt;プロジェクトの場所: ~/work/NewProject/&lt;/li&gt;
&lt;li&gt;trunk/tag/brunches などはよく分からないので使わない&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;b&gt;&lt;u&gt;手順&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;途中でエラーが出たら最初からやり直すのが無難。&lt;/span&gt;&lt;br /&gt;
&lt;ol style=&quot;line-height: 2em;&quot;&gt;&lt;li&gt;http://your.svnhost/ をXcodeのSCMリポジトリに登録していない場合は登録する&lt;br /&gt;
&lt;a href=&quot;http://www.covertapps.com/development/6-setting-up-your-xcode-scm-repositories&quot;&gt;Setting up your XCode SCM Repositories&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Xcode起動→プロジェクト新規作成→テンプレート選択&lt;/li&gt;
&lt;li&gt;場所: ~/work/ プロジェクト名: NewProject → OK&lt;/li&gt;
&lt;li&gt;Xcodeを終了&lt;/li&gt;
&lt;li&gt;Finderで~/work/に行き、NewProjectフォルダをデスクトップに移動&lt;/li&gt;
&lt;li&gt;ターミナルを起動&lt;/li&gt;
&lt;li&gt;$ svn mkdir -m &quot;Making a new directory for NewProject.&quot; http://your.svnhost/path/to/project/NewProject/&lt;/li&gt;
&lt;li&gt;$ cd ~/work/&lt;/li&gt;
&lt;li&gt;$ mkdir NewProject&lt;/li&gt;
&lt;li&gt;$ svn co&amp;nbsp;http://your.svnhost/path/to/project/NewProject/ NewProject&lt;/li&gt;
&lt;li&gt;$ cd NewProject&lt;/li&gt;
&lt;li&gt;$ cp -r ~/Desktop/NewProject/* . &lt;/li&gt;
&lt;li&gt;$ vi .svnignore&lt;/li&gt;
&lt;li&gt;i → 以下をコピペ → :wq&lt;br /&gt;
&lt;pre&gt;.DS_Store
build
*.pbxuser
*.perspectiv*&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;$&amp;nbsp;svn propset svn:ignore -R -F .svnignore .&lt;/li&gt;
&lt;li&gt;$ svn add --force .&lt;/li&gt;
&lt;li&gt;$ svn st&lt;br /&gt;
buildフォルダやNewProject.xcodeproj以下にproject.pbxproj以外が無いことを確認&lt;/li&gt;
&lt;li&gt;XcodeでメニューのSCM→このプロジェクトのSCMを設定&lt;/li&gt;
&lt;li&gt;右上あたりのSCMルート設定をクリック&lt;/li&gt;
&lt;li&gt;Noneをクリック→リポジトリ選択(Recommendedになっているはず、なってなかったら手順1が抜けてるか、そうでなければやり直す)&lt;/li&gt;
&lt;li&gt;メニューのSCM→プロジェクト全体をリフレッシュ (一応)&lt;/li&gt;
&lt;li&gt;メニューのSCM→プロジェクト全体をコミット&lt;/li&gt;
&lt;li&gt;メニューのSCM→SCM Results→何も表示されていないことを確認&lt;/li&gt;
&lt;li&gt;デスクトップのNewProjectフォルダを捨てる&lt;/li&gt;
&lt;/ol&gt;以上です。以降はコマンドラインでsubversion管理擦る必要はないでしょう。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;u&gt;参考&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://svnbook.red-bean.com/en/1.1/ch09.html&quot;&gt;Chapter&amp;nbsp;9.&amp;nbsp;Subversion Complete Reference&lt;/a&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;他色々&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;b&gt;&lt;u&gt;この後は&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://ksk77.blogspot.com/2010/10/iphonexcode.html&quot;&gt;BLOG.: [iPhone]Xcodeプロジェクトを作ったらまずやること&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/8517829537269028605/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/12/subversion-controlledxcode-project.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/8517829537269028605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/8517829537269028605'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/12/subversion-controlledxcode-project.html' title='subversion-controlledなXcode Projectの新規作成手順'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-7266061846169229650</id><published>2010-12-08T12:54:00.000+09:00</published><updated>2010-12-08T12:54:16.557+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="デザインパターン"/><title type='text'>第21章 Proxyパターン : 必要になってから作る</title><content type='html'>&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;asins=4797327030&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
Proxyパターンもそんなに難しくないですね。RealSubject役がProxy役を意識しないところが味噌ですね。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Virtual Proxy ... 今回の例&lt;/li&gt;
&lt;li&gt;Remote Proxy ... ネットワーク越しのメソッド呼び出しに&lt;/li&gt;
&lt;li&gt;Access Proxy ... メソッド呼び出しにアクセス制限を設けたい時に&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;&lt;br /&gt;
timeモジュールのsleep(sec)はスレッドをブロックするので、マルチスレッド化しなければsynchronizeを意識する必要はなさそうです。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;実行結果&lt;/b&gt;&lt;br /&gt;
&lt;pre&gt;名前は現在Aliceです。
名前は現在Bobです。
Printerのインスタンス(Bob)を生成中
生成完了
=== Bob ===
Hello, world
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;ソースコード&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;#!/usr/bin/env python
# -*- coding: utf8 -*-

# Subject interface
class __Printable:
    def __init__(self): raise NotImplementedError
    def setPrinterName(self, n): raise NotImplementedError
    def getPrinterName(self): raise NotImplementedError
    def printIt(self): raise NotImplementedError

from time import sleep
# RealSubject class
class Printer(__Printable):
    def __init__(self, name):
        self.__name = name
        print &quot;Printerのインスタンス(%s)を生成中&quot; % name
        self.__heavyjob()

    def getPrinterName(self):
        return self.__name
    def setPrinterName(self, n):
        self.__name = n

    def printIt(self, msg):
        print &quot;=== %s ===&quot; % self.__name
        print msg

    def __heavyjob(self):
        sleep(3)
        print &#39;生成完了&#39;

# Proxy class
class PrinterProxy(__Printable):
    def __init__(self, name):
        self.__name = name
        self.__real = None

    def getPrinterName(self):
        return self.__name
    def setPrinterName(self, n):
        self.__name = n
        if not self.__real == None:
            self.__real.setPrinterName(n)

    def printIt(self, msg):
        if self.__real == None:
            self.__realize()
        self.__real.printIt(msg)


    def __realize(self):
        self.__real = Printer(self.__name)

# Client
def main():
    m_printer = PrinterProxy(&quot;Alice&quot;)
    print &quot;名前は現在%sです。&quot; % m_printer.getPrinterName()
    m_printer.setPrinterName(&quot;Bob&quot;)
    print &quot;名前は現在%sです。&quot; % m_printer.getPrinterName()
    m_printer.printIt(&quot;Hello, world&quot;)

if __name__==&#39;__main__&#39;: main()
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/7266061846169229650/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/12/21-proxy.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/7266061846169229650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/7266061846169229650'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/12/21-proxy.html' title='第21章 Proxyパターン : 必要になってから作る'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-1810401458914157868</id><published>2010-12-06T23:22:00.001+09:00</published><updated>2010-12-06T23:22:15.958+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="デザインパターン"/><title type='text'>第20章 Flyweightパターン : 同じものを共有して無駄をなくす</title><content type='html'>&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;asins=4797327030&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
今回のFlyweightパターンは分かりやすいですね。&lt;br /&gt;
factoryにpool作っておいて、同じものを表すオブジェクトはpoolに入っているものを共有するだけです。&lt;br /&gt;
&lt;br /&gt;
注意点は2つ。詳細は省きます。&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;共有しているものを変更すると、&lt;b&gt;複数箇所に影響が及ぶ&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;管理されているインスタンスは、&lt;b&gt;ガベージコレクションされない&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;hr /&gt;&lt;br /&gt;
今回もオリジナルで。とは言っても『元の文字に空白を一文字追加して新しい文字列とする』だけなので全く大したことないですが。&lt;br /&gt;
あとpythonにsynchronizedが無くてちょっとがっかり。threading.Queueとか使うとよさそうです。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;実行結果&lt;/b&gt;&lt;br /&gt;
&lt;pre&gt;L o r e m   i p s u m   d o l o r   s i t   a m e t ,   c o n s e c t e t u r   a d i p i s c i n g   e l i t .   P r a e s e n t   d i g n i s s i m   d i g n i s s i m   e r o s ,   a c   c o n d i m e n t u m   o r c i   i n t e r d u m   s e d .   U t   e t   d o l o r   a t   e s t   e l e m e n t u m   p o s u e r e .   M a u r i s   i a c u l i s   e u i s m o d   l a c u s ,   e g e t   d a p i b u s   a u g u e   i n t e r d u m   v i t a e .   D o n e c   i d   c o n g u e   e l i t .   D o n e c   e r o s   d i a m ,   c o n s e c t e t u r   s i t   a m e t   v a r i u s   i d ,   f e r m e n t u m   e g e t   n i s i .   V i v a m u s   l a o r e e t   a u c t o r   m a s s a   e g e t   p o r t t i t o r .   C r a s   a   e s t   a   n i s i   e g e s t a s   s a g i t t i s   e t   s i t   a m e t   p u r u s .   F u s c e   n e c   u l l a m c o r p e r   p u r u s .   N u l l a   f a c i l i s i .   V e s t i b u l u m   i n   o r c i   s e d   n i b h   r u t r u m   v e n e n a t i s . 
 
 P r a e s e n t   f a c i l i s i s ,   n i s l   t i n c i d u n t   m a l e s u a d a   s u s c i p i t ,   d o l o r   u r n a   f a c i l i s i s   d o l o r ,   v i t a e   i a c u l i s   l o r e m   l i b e r o   s e d   r i s u s .   Q u i s q u e   e t   p l a c e r a t   m a u r i s .   I n   e g e t   a d i p i s c i n g   n i b h .   P e l l e n t e s q u e   i m p e r d i e t   u l t r i c i e s   f e l i s ,   q u i s   p o r t t i t o r   a u g u e   v i v e r r a   a t .   C u r a b i t u r   s e d   n i b h   i p s u m .   E t i a m   c o n d i m e n t u m   l e c t u s   i d   m a u r i s   l a o r e e t   e g e t   r u t r u m   n u n c   r h o n c u s .   F u s c e   e g e s t a s   s a g i t t i s   l a c u s ,   s e d   u l l a m c o r p e r   s a p i e n   m o l e s t i e   a .   M a u r i s   o r n a r e   t u r p i s   u t   l i g u l a   f a u c i b u s   e t   p o r t a   e s t   l a o r e e t .   U t   e u   p u r u s   a c   d i a m   v a r i u s   f a u c i b u s   e l e m e n t u m   v i t a e   a u g u e .   N u n c   i d   o d i o   v e l i t ,   v e l   r h o n c u s   n u n c .   S e d   e g e s t a s   t r i s t i q u e   s o l l i c i t u d i n .   I n   v i v e r r a   m a u r i s   a t   i p s u m   v u l p u t a t e   m o l l i s .   D o n e c   l e c t u s   f e l i s ,   r h o n c u s   v e l   e l e i f e n d   s e d ,   f a c i l i s i s   a c c u m s a n   l e c t u s .   P r a e s e n t   n e c   m a g n a   v e l   e s t   g r a v i d a   p r e t i u m   s a g i t t i s   v i t a e   d u i .   S u s p e n d i s s e   p o t e n t i .   C u r a b i t u r   l o b o r t i s   t o r t o r   n e c   e s t   a d i p i s c i n g   l a c i n i a . 
 
 L o r e m   i p s u m   d o l o r   s i t   a m e t ,   c o n s e c t e t u r   a d i p i s c i n g   e l i t .   P e l l e n t e s q u e   f e u g i a t   a u g u e   v e l   m a s s a   v o l u t p a t   f r i n g i l l a .   N u l l a m   m a t t i s   a c c u m s a n   s a p i e n   e t   d i c t u m .   S u s p e n d i s s e   n e c   u r n a   e g e t   n i s i   p e l l e n t e s q u e   s e m p e r   s i t   a m e t   q u i s   v e l i t .   A e n e a n   a c c u m s a n   d i a m   i n   s e m   c o n s e c t e t u r   i d   u l t r i c i e s   d o l o r   l o b o r t i s .   I n   e g e s t a s   s e m   u t   n u n c   c o n v a l l i s   s o d a l e s   i n   u t   t o r t o r .   P r a e s e n t   n e c   m a g n a   n e q u e .   P r a e s e n t   s e m p e r   s a g i t t i s   d o l o r   a   d a p i b u s .   N a m   h e n d r e r i t ,   l o r e m   n e c   f a u c i b u s   v e h i c u l a ,   n u n c   e n i m   i n t e r d u m   s e m ,   n o n   e g e s t a s   s a p i e n   a n t e   e u   l e c t u s .   P e l l e n t e s q u e   h a b i t a n t   m o r b i   t r i s t i q u e   s e n e c t u s   e t   n e t u s   e t   m a l e s u a d a   f a m e s   a c   t u r p i s   e g e s t a s .   D u i s   v e l   m a u r i s   t e l l u s ,   e g e t   p l a c e r a t   m i .   P e l l e n t e s q u e   m e t u s   m i ,   e l e i f e n d   u t   t e m p u s   i n ,   f e r m e n t u m   q u i s   l i g u l a .   A l i q u a m   e r a t   l e o ,   m o l l i s   a c   c u r s u s   a c ,   f e u g i a t   i n   n i s i .   E t i a m   g r a v i d a   e u i s m o d   l e c t u s   e t   c o n s e c t e t u r .   E t i a m   i a c u l i s   e l e m e n t u m   r i s u s ,   i n   e l e i f e n d   v e l i t   a u c t o r   a c .   V i v a m u s   u l l a m c o r p e r ,   l o r e m   n o n   m o l e s t i e   c o n v a l l i s ,   t e l l u s   a n t e   p u l v i n a r   s a p i e n ,   v e l   p o r t t i t o r   m a s s a   o d i o   e u   l e c t u s .   D o n e c   a c   r i s u s   t r i s t i q u e   n i s l   e u i s m o d   c o n s e c t e t u r .   D o n e c   m o l l i s   s e m p e r   a n t e ,   q u i s   f e u g i a t   l a c u s   i m p e r d i e t   a t .   N a m   e u   l o r e m   s i t   a m e t   v e l i t   s a g i t t i s   c o n s e c t e t u r   a   v o l u t p a t   m i .   S u s p e n d i s s e   s e d   a d i p i s c i n g   l e c t u s . 
 
 C l a s s   a p t e n t   t a c i t i   s o c i o s q u   a d   l i t o r a   t o r q u e n t   p e r   c o n u b i a   n o s t r a ,   p e r   i n c e p t o s   h i m e n a e o s .   N a m   c o n v a l l i s   f e r m e n t u m   e n i m ,   v e l   b l a n d i t   n i s l   b l a n d i t   v e l .   I n t e g e r   a c   j u s t o   n u l l a .   N u l l a   e r o s   e l i t ,   u l l a m c o r p e r   s e d   c o n d i m e n t u m   v e l ,   p o r t a   s e d   e n i m .   S e d   a t   l i b e r o   v e l   l a c u s   p r e t i u m   d i c t u m .   M a u r i s   h e n d r e r i t   u r n a   s i t   a m e t   m i   r h o n c u s   n o n   a l i q u a m   e n i m   i m p e r d i e t .   C u r a b i t u r   a   e r o s   a   d i a m   u l l a m c o r p e r   r h o n c u s .   P r o i n   e t   m a g n a   i n   n i s i   e l e m e n t u m   d i c t u m   v e l   s i t   a m e t   l e c t u s .   U t   t r i s t i q u e   d u i   q u i s   v e l i t   a u c t o r   m o l e s t i e   d a p i b u s   n u l l a   v a r i u s .   F u s c e   v i t a e   v e l i t   p e l l e n t e s q u e   m a g n a   c o n s e q u a t   p l a c e r a t .   M a e c e n a s   d i g n i s s i m   r i s u s   n o n   e s t   s o l l i c i t u d i n   v u l p u t a t e .   M a u r i s   v i t a e   o r c i   f r i n g i l l a   n u l l a   p r e t i u m   p h a r e t r a .   C u r a b i t u r   a c   f a c i l i s i s   t o r t o r .   C u r a b i t u r   e g e t   m o l l i s   v e l i t .   I n   a c   l e c t u s   e l i t ,   a c   p o s u e r e   r i s u s .   Q u i s q u e   q u i s   l i g u l a   m e t u s ,   u t   b l a n d i t   l i b e r o .   C u r a b i t u r   s e d   n i b h   v i t a e   m i   e l e m e n t u m   m o l e s t i e .   D o n e c   e u i s m o d   a r c u   u t   t u r p i s   u l t r i c e s   v i v e r r a .   N u l l a   f a c i l i s i . 
 
 N u l l a   i d   p u l v i n a r   m a u r i s .   N u n c   m a t t i s   f a c i l i s i s   a u g u e ,   s e d   t r i s t i q u e   e s t   i n t e r d u m   s e d .   P r a e s e n t   u l t r i c i e s   n i b h   i d   a u g u e   s u s c i p i t   i d   u l t r i c i e s   m e t u s   a d i p i s c i n g .   A l i q u a m   e r a t   v o l u t p a t .   V e s t i b u l u m   u t   i p s u m   i n   u r n a   l o b o r t i s   f e u g i a t   v i t a e   s i t   a m e t   a r c u .   A l i q u a m   d i a m   p u r u s ,   p r e t i u m   n e c   c o n s e q u a t   v e l ,   p l a c e r a t   a   n i b h .   A e n e a n   l e o   n i s l ,   u l l a m c o r p e r   i n   p l a c e r a t   c o n g u e ,   m o l e s t i e   u l t r i c e s   t o r t o r .   P r a e s e n t   d i a m   l i g u l a ,   e g e s t a s   a   f e r m e n t u m   s e d ,   u l t r i c i e s   i d   o d i o .   D o n e c   a t   p u r u s   i p s u m .   P h a s e l l u s   p o r t a   p l a c e r a t   s c e l e r i s q u e .   S u s p e n d i s s e   h e n d r e r i t   r u t r u m   q u a m   u t   p o r t t i t o r . &lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;ソースコード&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;#!/usr/bin/env python
# -*- coding: utf8 -*-

import sys

# Flyweight class
class SparseChar:
    def __init__(self, char):
        self.__char = char[0]

    def draw(self):
        sys.stdout.write(self.__char+&quot; &quot;)

# FlyweightFactory class
class SparseCharFactory:
    def __init__(self):
        self.__pool = {}

    def getSparseChar(self, char):
        if not self.__pool.has_key(char):
            self.__pool[char] = SparseChar(char)
        return self.__pool[char]

# Client class
class SparseString:
    def __init__(self, string):
        self.__string = string
        self.factory = SparseCharFactory()

    def draw(self):
        for s in self.__string:
            self.factory.getSparseChar(s).draw()
        print &quot;&quot;


def main():
    m_sparseString = SparseString(&quot;&quot;&quot;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent dignissim dignissim eros, ac condimentum orci interdum sed. Ut et dolor at est elementum posuere. Mauris iaculis euismod lacus, eget dapibus augue interdum vitae. Donec id congue elit. Donec eros diam, consectetur sit amet varius id, fermentum eget nisi. Vivamus laoreet auctor massa eget porttitor. Cras a est a nisi egestas sagittis et sit amet purus. Fusce nec ullamcorper purus. Nulla facilisi. Vestibulum in orci sed nibh rutrum venenatis.

Praesent facilisis, nisl tincidunt malesuada suscipit, dolor urna facilisis dolor, vitae iaculis lorem libero sed risus. Quisque et placerat mauris. In eget adipiscing nibh. Pellentesque imperdiet ultricies felis, quis porttitor augue viverra at. Curabitur sed nibh ipsum. Etiam condimentum lectus id mauris laoreet eget rutrum nunc rhoncus. Fusce egestas sagittis lacus, sed ullamcorper sapien molestie a. Mauris ornare turpis ut ligula faucibus et porta est laoreet. Ut eu purus ac diam varius faucibus elementum vitae augue. Nunc id odio velit, vel rhoncus nunc. Sed egestas tristique sollicitudin. In viverra mauris at ipsum vulputate mollis. Donec lectus felis, rhoncus vel eleifend sed, facilisis accumsan lectus. Praesent nec magna vel est gravida pretium sagittis vitae dui. Suspendisse potenti. Curabitur lobortis tortor nec est adipiscing lacinia.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque feugiat augue vel massa volutpat fringilla. Nullam mattis accumsan sapien et dictum. Suspendisse nec urna eget nisi pellentesque semper sit amet quis velit. Aenean accumsan diam in sem consectetur id ultricies dolor lobortis. In egestas sem ut nunc convallis sodales in ut tortor. Praesent nec magna neque. Praesent semper sagittis dolor a dapibus. Nam hendrerit, lorem nec faucibus vehicula, nunc enim interdum sem, non egestas sapien ante eu lectus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis vel mauris tellus, eget placerat mi. Pellentesque metus mi, eleifend ut tempus in, fermentum quis ligula. Aliquam erat leo, mollis ac cursus ac, feugiat in nisi. Etiam gravida euismod lectus et consectetur. Etiam iaculis elementum risus, in eleifend velit auctor ac. Vivamus ullamcorper, lorem non molestie convallis, tellus ante pulvinar sapien, vel porttitor massa odio eu lectus. Donec ac risus tristique nisl euismod consectetur. Donec mollis semper ante, quis feugiat lacus imperdiet at. Nam eu lorem sit amet velit sagittis consectetur a volutpat mi. Suspendisse sed adipiscing lectus.

Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam convallis fermentum enim, vel blandit nisl blandit vel. Integer ac justo nulla. Nulla eros elit, ullamcorper sed condimentum vel, porta sed enim. Sed at libero vel lacus pretium dictum. Mauris hendrerit urna sit amet mi rhoncus non aliquam enim imperdiet. Curabitur a eros a diam ullamcorper rhoncus. Proin et magna in nisi elementum dictum vel sit amet lectus. Ut tristique dui quis velit auctor molestie dapibus nulla varius. Fusce vitae velit pellentesque magna consequat placerat. Maecenas dignissim risus non est sollicitudin vulputate. Mauris vitae orci fringilla nulla pretium pharetra. Curabitur ac facilisis tortor. Curabitur eget mollis velit. In ac lectus elit, ac posuere risus. Quisque quis ligula metus, ut blandit libero. Curabitur sed nibh vitae mi elementum molestie. Donec euismod arcu ut turpis ultrices viverra. Nulla facilisi.

Nulla id pulvinar mauris. Nunc mattis facilisis augue, sed tristique est interdum sed. Praesent ultricies nibh id augue suscipit id ultricies metus adipiscing. Aliquam erat volutpat. Vestibulum ut ipsum in urna lobortis feugiat vitae sit amet arcu. Aliquam diam purus, pretium nec consequat vel, placerat a nibh. Aenean leo nisl, ullamcorper in placerat congue, molestie ultrices tortor. Praesent diam ligula, egestas a fermentum sed, ultricies id odio. Donec at purus ipsum. Phasellus porta placerat scelerisque. Suspendisse hendrerit rutrum quam ut porttitor.&quot;&quot;&quot;)
    m_sparseString.draw()


if __name__==&#39;__main__&#39;: main()
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/1810401458914157868/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/12/20-flyweight.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/1810401458914157868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/1810401458914157868'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/12/20-flyweight.html' title='第20章 Flyweightパターン : 同じものを共有して無駄をなくす'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-3534529634844463293</id><published>2010-12-06T23:22:00.000+09:00</published><updated>2010-12-06T23:22:05.836+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="デザインパターン"/><title type='text'>第19章 Stateパターン : 状態をクラスとして表現する</title><content type='html'>&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;asins=4797327030&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
今回はStateパターン。なかなかエキセントリックなデザインパターンです。&lt;br /&gt;
&lt;br /&gt;
要は&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;メソッドの実装を&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;ある状態&lt;/span&gt;に応じて切り替える(条件分岐させる)&lt;/li&gt;
&lt;/ul&gt;ような実装を&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;ある状態&lt;/span&gt;というクラスがメソッドの実装を記述する&lt;/li&gt;
&lt;/ul&gt;という、説明しても『???』なデザインパターンです。&lt;br /&gt;
&lt;br /&gt;
もう少し概念的な説明すると、&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;普通の条件分岐…『この状態&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;なら&lt;/span&gt;こういう処理にする』&lt;/li&gt;
&lt;li&gt;Stateパターン…『この状態&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;が&lt;/span&gt;こういう処理をする』&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
というように、状態が主語になるイメージです。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;u&gt;いつ使うのか。メリットは何か。&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
使う場面を間違えると却って混乱しそうなStateパターン。自分で例を考えて実装してみて、有効だと感じた点を列挙します。&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;&lt;i&gt;どのメソッドにも同じような条件分岐が散らばるほどに重要な『状態』がある時&lt;/i&gt;&lt;br /&gt;
まあこれは当たり前っちゃあ当たり前。&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #990000;&quot;&gt;『この状態の時に呼ばれたらこう動く』&lt;/span&gt;という説明のメソッドがあったら要チェック。&lt;br /&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;i&gt;将来状態が増減しそうな時&lt;/i&gt;&lt;br /&gt;
これも当たり前かな&lt;br /&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;i&gt;状態を矛盾なく取り扱える&lt;/i&gt;&lt;br /&gt;
本書でも触れてますが、このパターンを適用する時は各Stateは排反である必要があるので、必竟&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;自己矛盾が起きません&lt;/span&gt;。&lt;br /&gt;
これはプログラミングする上でとても大事です。『このifはelse ifにしないと動かない』みたいな分かりづらさから解放されます。&lt;/li&gt;
&lt;/ol&gt;逆に&lt;u&gt;デメリット&lt;/u&gt;は以下のような点。&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;&lt;i&gt;状態が増えすぎるとしんどい&lt;/i&gt;&lt;br /&gt;
特にベクトルの違う複数の状態の組み合わせだと、状態数が指数的に増えるおそれがある&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;&lt;br /&gt;
今回は完全オリジナル。どこかのブログのパクリで、『マリオでStateパターン』です。&lt;br /&gt;
1ターンにランダムで&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #a64d79;&quot;&gt;きのこを食べる&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #a64d79;&quot;&gt;フラワーを食べる&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #a64d79;&quot;&gt;スターを食べる&lt;/span&gt;(スターは3ターンで切れる)&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #a64d79;&quot;&gt;敵に当たる&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #a64d79;&quot;&gt;穴に落ちる&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
のなかから一つの行動をします。State(状態)は&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;チビマリオ&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;デカマリオ&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;フラワーマリオ&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;上記3種のスター状態&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
の計6種類です。&lt;br /&gt;
これだと、例えば『しっぽマリオを追加する』なんて時にSippoMarioStateクラスとStarSippoMarioStateクラスを追加するだけで実現できてしまいます(他所はいじる必要なし!)。Stateパターンの有効なケースですね。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;実行結果&lt;/b&gt;&lt;br /&gt;
&lt;pre&gt;[残5:チビマリオ] スターを食べた!  チビマリオ★ になった!
[残5:チビマリオ★] ...
[残5:チビマリオ★] キノコを食べた!  デカマリオ★ になった!
[残5:デカマリオ★] スターが切れた!  デカマリオ になった!
[残5:デカマリオ] スターを食べた!  デカマリオ★ になった!
[残5:デカマリオ★] 敵に接触!  敵を倒した!
[残5:デカマリオ★] スターを食べた!  デカマリオ★ になった!
[残5:デカマリオ★] 穴に落ちた!  死んだ! 残り残機:4
[残4:チビマリオ] キノコを食べた!  デカマリオ になった!
[残4:デカマリオ] ...
[残4:デカマリオ] 穴に落ちた!  死んだ! 残り残機:3
[残3:チビマリオ] ...
[残3:チビマリオ] フラワーを食べた!  デカマリオ になった!
[残3:デカマリオ] スターを食べた!  デカマリオ★ になった!
[残3:デカマリオ★] フラワーを食べた!  ファイアーマリオ★ になった!
[残3:ファイアーマリオ★] フラワーを食べた!  意味はない!
[残3:ファイアーマリオ★] スターが切れた!  ファイアーマリオ になった!
[残3:ファイアーマリオ] ...
[残3:ファイアーマリオ] 穴に落ちた!  死んだ! 残り残機:2
[残2:チビマリオ] フラワーを食べた!  デカマリオ になった!
[残2:デカマリオ] 敵に接触!  チビマリオ になった!
[残2:チビマリオ] 穴に落ちた!  死んだ! 残り残機:1
[残1:チビマリオ] キノコを食べた!  デカマリオ になった!
[残1:デカマリオ] スターを食べた!  デカマリオ★ になった!
[残1:デカマリオ★] フラワーを食べた!  ファイアーマリオ★ になった!
[残1:ファイアーマリオ★] キノコを食べた!  意味はない!
[残1:ファイアーマリオ★] スターが切れた!  ファイアーマリオ になった!
[残1:ファイアーマリオ] フラワーを食べた!  意味はない!
[残1:ファイアーマリオ] 敵に接触!  チビマリオ になった!
[残1:チビマリオ] フラワーを食べた!  デカマリオ になった!
[残1:デカマリオ] 敵に接触!  チビマリオ になった!
[残1:チビマリオ] 敵に接触!  死んだ! 残り残機:0
[残0:チビマリオ] 穴に落ちた!  GAME OVER
30ターンプレイしました&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;ソースコード&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;#!/usr/bin/env python
# -*- coding: utf8 -*-

class __MarioState:
    def __init__(self): raise NotImplementedError
    def doGetKinoko(self, context): raise NotImplementedError # キノコ取得
    def doGetFlower(self, context): raise NotImplementedError # フラワー取得
    def doGetStar(self, context): raise NotImplementedError # スター取得
    def doLostStar(self, context): raise NotImplementedError # スター消滅
    def doEncounter(self, context): raise NotImplementedError # 敵に接触
    def doFall(self, context): raise NotImplementedError # 穴に落ちる
    def __str__(self): raise NotImplementedError


class NormalMario(__MarioState):
    def __init__(self): pass
    def doGetKinoko(self, context): context.changeState(BigMario())
    def doGetFlower(self, context): context.changeState(BigMario())
    def doEncounter(self, context): context.dead()
    def doGetStar(self, context): context.changeState(StarNormalMario())
    def doLostStar(self, context): print &quot;bug&quot;
    def doFall(self, context): context.dead()
    def __str__(self): return &quot;チビマリオ&quot;

class BigMario(__MarioState):
    def __init__(self): pass
    def doGetKinoko(self, context): context.nope()
    def doGetFlower(self, context): context.changeState(FlowerMario())
    def doEncounter(self, context): context.changeState(NormalMario())
    def doGetStar(self, context): context.changeState(StarBigMario())
    def doLostStar(self, context): print &quot;bug&quot;
    def doFall(self, context): context.dead()
    def __str__(self): return &quot;デカマリオ&quot;

class FlowerMario(__MarioState):
    def __init__(self): pass
    def doGetKinoko(self, context): context.nope()
    def doGetFlower(self, context): context.nope()
    def doEncounter(self, context): context.changeState(NormalMario())
    def doGetStar(self, context): context.changeState(StarFlowerMario())
    def doLostStar(self, context): print &quot;bug&quot;
    def doFall(self, context): context.dead()
    def __str__(self): return &quot;ファイアーマリオ&quot;

class StarNormalMario(__MarioState):
    def __init__(self): pass
    def doGetKinoko(self, context): context.changeState(StarBigMario())
    def doGetFlower(self, context): context.changeState(StarBigMario())
    def doGetStar(self, context): context.changeState(StarNormalMario())
    def doLostStar(self, context): context.changeState(NormalMario())
    def doEncounter(self, context): context.defeat()
    def doFall(self, context): context.dead()
    def __str__(self): return &quot;チビマリオ★&quot;

class StarBigMario(__MarioState):
    def __init__(self): pass
    def doGetKinoko(self, context): context.nope()
    def doGetFlower(self, context): context.changeState(StarFlowerMario())
    def doGetStar(self, context): context.changeState(StarBigMario())
    def doLostStar(self, context): context.changeState(BigMario())
    def doEncounter(self, context): context.defeat()
    def doFall(self, context): context.dead()
    def __str__(self): return &quot;デカマリオ★&quot;

class StarFlowerMario(__MarioState):
    def __init__(self): pass
    def doGetKinoko(self, context): context.nope()
    def doGetFlower(self, context): context.nope()
    def doGetStar(self, context): context.changeState(StarFlowerMario())
    def doLostStar(self, context): context.changeState(FlowerMario())
    def doEncounter(self, context): context.defeat()
    def doFall(self, context): context.dead()
    def __str__(self): return &quot;ファイアーマリオ★&quot;



class __Context:
    def __init__(self): raise NotImplementedError
    def changeState(self, mariostate): raise NotImplementedError # 状態が変化した
    def defeat(self): raise NotImplementedError # 敵を倒した
    def dead(self): raise NotImplementedError # 死んだ
    def nope(self): raise NotImplementedError # 何も起きない

import sys
from threading import Timer
class Game(__Context):
    def __init__(self):
        self.state = NormalMario()
        self.zanki = 5 # 残機
        self.turncount = 0 # 何ターン目か
        self.starcount = 99999 # スター用カウンタ

    def changeState(self, mariostate):
        self.state = mariostate
        print str(mariostate)+&quot; になった!&quot;

    def defeat(self):
        print &quot;敵を倒した!&quot;

    def dead(self):
        self.zanki -= 1
        if self.zanki &amp;lt; 0:
            print &quot;GAME OVER&quot;
            print &quot;%dターンプレイしました&quot; % self.turncount
            sys.exit(0)
        print &quot;死んだ! 残り残機:%d&quot; % self.zanki
        self.state = NormalMario()
        self.starcount = 99999

    def nope(self):
        print &quot;意味はない!&quot;

    #--

    def youGetKinoko(self):
        print &quot;[残%d:%s] キノコを食べた! &quot; % (self.zanki, self.state),
        self.state.doGetKinoko(self)
    def youGetFlower(self):
        print &quot;[残%d:%s] フラワーを食べた! &quot; % (self.zanki, self.state),
        self.state.doGetFlower(self)
    def youEncounter(self):
        print &quot;[残%d:%s] 敵に接触! &quot; % (self.zanki, self.state),
        self.state.doEncounter(self)
    def youFall(self):
        print &quot;[残%d:%s] 穴に落ちた! &quot; % (self.zanki, self.state),
        self.state.doFall(self)
    def nothingHappened(self):
        print &quot;[残%d:%s] ...&quot; % (self.zanki, self.state)

    def youGetStar(self):
        print &quot;[残%d:%s] スターを食べた! &quot; % (self.zanki, self.state),
        self.state.doGetStar(self)
        self.starcount = 0
    def __youLostStar(self):
        print &quot;[残%d:%s] スターが切れた! &quot; % (self.zanki, self.state),
        self.state.doLostStar(self)

    def youCountTurn(self):
        self.turncount += 1
        self.starcount += 1
        if self.starcount == 3:
            self.__youLostStar()



from time import sleep
from random import randint
def main():
    m_game = Game()
    while True:
        # random action
        m_game.youCountTurn()
        act = randint(1,6)
        if   act==1: m_game.youGetKinoko()
        elif act==2: m_game.youGetFlower()
        elif act==3: m_game.youGetStar()
        elif act==4: m_game.youEncounter()
        elif act==5: m_game.youFall()
        elif act==6: m_game.nothingHappened()
        sleep(0.1)

if __name__==&#39;__main__&#39;: main()
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/3534529634844463293/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/12/19-state.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/3534529634844463293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/3534529634844463293'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/12/19-state.html' title='第19章 Stateパターン : 状態をクラスとして表現する'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-9059151752252371277</id><published>2010-12-06T23:21:00.000+09:00</published><updated>2010-12-06T23:21:50.973+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="デザインパターン"/><title type='text'>第18章 Memento : 状態を保存する</title><content type='html'>&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;asins=4797327030&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
今回はMementoパターン。undo/redo/snapshotといった機能をカプセル化を破壊することなく提供する方法です。&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Originator役はMemento役のオブジェクトを生成し、&lt;/li&gt;
&lt;li&gt;Caretaker役はMemento役のオブジェクトを保持します。&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
『&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;オブジェクトの状態を保存する&lt;/span&gt;』という機能は、undo以外にも用途がありそうです。&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
簡単のため、所持金のみ増減するゲームにしてあります。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;実行結果&lt;/b&gt;&lt;br /&gt;
&lt;pre&gt;4の目が出た!... 
2の目が出た!... 所持金が半分になった!
1の目が出た!... 所持金が100増えた!
所持金が増えたので状態を保存。現在150円
5の目が出た!... 
3の目が出た!... 
5の目が出た!... 
2の目が出た!... 所持金が半分になった!
2の目が出た!... 所持金が半分になった!
所持金がかなり減ったので状態を復元。現在150円
(中略)
6の目が出た!... 
2の目が出た!... 所持金が半分になった!
所持金がかなり減ったので状態を復元。現在1412円
5の目が出た!... 
2の目が出た!... 所持金が半分になった!
2の目が出た!... 所持金が半分になった!
所持金がかなり減ったので状態を復元。現在1412円
1の目が出た!... 所持金が100増えた!
所持金が増えたので状態を保存。現在1512円
6の目が出た!... 
終了。最終金額1512円&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;ソースコード&lt;/b&gt;&lt;br /&gt;
game.py&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;# -*- coding: utf8 -*-

from random import randint
class Gamer:
    def __init__(self, money):
        self.__money = money

    def getMoney(self): return self.__money
    def bet(self):
        dice = randint(1,6)
        print &quot;%dの目が出た!...&quot; % (dice),
        if dice==1:
            self.__money += 100
            print &quot;所持金が100増えた!&quot;
        elif dice==2:
            self.__money /= 2
            print &quot;所持金が半分になった!&quot;
        else:
            print &quot;&quot;

    def createMemento(self):
        return Memento(self.__money)

    def restoreMemento(self, memento):
        self.__money = memento.getMoney()



class Memento:
    # protected constructor
    def __init__(self, money):
        self.__money = money

    def getMoney(self): return self.__money
&lt;/pre&gt;&lt;br /&gt;
main.py&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;#!/usr/bin/env python
# -*- coding: utf8 -*-

from game import Gamer, Memento
from time import sleep
def main():
    gamer = Gamer(100)
    memento = gamer.createMemento()
    for i in xrange(100):
        gamer.bet()
        if gamer.getMoney() &amp;gt; memento.getMoney():
            memento = gamer.createMemento()
            print &quot;所持金が増えたので状態を保存。現在%d円&quot; % (gamer.getMoney())
        elif gamer.getMoney() &amp;lt; memento.getMoney() / 2:
            gamer.restoreMemento(memento)
            print &quot;所持金がかなり減ったので状態を復元。現在%d円&quot; % (gamer.getMoney())
        sleep(0.5)

    print &quot;終了。最終金額%d円&quot; % (gamer.getMoney())

if __name__==&#39;__main__&#39;: main()
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/9059151752252371277/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/12/18-memento.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/9059151752252371277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/9059151752252371277'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/12/18-memento.html' title='第18章 Memento : 状態を保存する'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-5091420087517253942</id><published>2010-11-28T13:46:00.001+09:00</published><updated>2010-12-04T03:57:58.711+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="デザインパターン"/><title type='text'>第17章 Observerパターン : 状態の変化を通知する</title><content type='html'>&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;asins=4797327030&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
今回はObserverパターン。とは言っても(本文中にもありますが)『観察』というよりは『通知』、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #a64d79;&quot;&gt;Publish―Subscribe&lt;/span&gt;の関係になってます。そして相変わらず委譲を使ってます。&lt;br /&gt;
&lt;br /&gt;
これも前回同様、Subject役をモデル、Observer役をコントローラまたはビューに当てはめると&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;MVCの典型的実装パターン&lt;/span&gt;ですね。と思ってたら本でもちょこっとこのトピックに触れていました。&lt;br /&gt;
&lt;br /&gt;
『更新のためのヒント情報の扱い』の節は私にとっていいヒントになりました。変化する情報に応じて一個ずつupdateメソッドを作るのでなく、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #a64d79;&quot;&gt;メソッドはupdate一つ&lt;/span&gt;にし、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #a64d79;&quot;&gt;変化する情報を引数&lt;/span&gt;に入れるという方法は新鮮でした。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;実行結果&lt;/b&gt;&lt;br /&gt;
&lt;pre&gt;1
*
4
****
0

5
*****
4
****
10
**********
3
***
・
・
・
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;ソースコード&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;#!/usr/bin/env python
# -*- coding: utf8 -*-

class ConstructInterfaceError(Exception):
    def __init__(self):
        pass

# Subject
class NumberGenerator:
    _observers = []
    def __init__(self): raise Exception(&quot;Abstract class&quot;)
    def addObserver(self, o):
        self._observers.append(o)

    def deleteObserver(self, o):
        self._observers.remove(o)

    def notifyObservers(self):
        for o in self._observers:
            o.update(self)

    def getNumber(self): raise NotImplementedError
    def execute(self): raise NotImplementedError

# ConcreteSubject
from random import randint
class RandomNumberGenerator(NumberGenerator):
    def __init__(self, maxnumber):
        self.__maxnumber = maxnumber
        self.__number = 0

    def getNumber(self):
        return self.__number

    def execute(self):
        self.__number = randint(0,self.__maxnumber)
        self.notifyObservers()



# Observer interface
class __Observer:
    def __init__(self): raise ConstructInterfaceError
    def update(self, subject): raise NotImplementedError

# ConcreteObserver
from time import sleep
class DigitObserver(__Observer):
    def __init__(self): pass
    def update(self, subject):
        print subject.getNumber()
        sleep(0.5)

# ConcreteObserver
class GraphObserver(__Observer):
    def __init__(self): pass
    def update(self, subject):
        print &#39;&#39;.join([&#39;*&#39; for i in xrange(subject.getNumber())])
        sleep(0.5)



def main():
    # NumberGenerator&#39;s instance
    g = RandomNumberGenerator(10)

    # Observer&#39;s instance
    do = DigitObserver()
    go = GraphObserver()

    g.addObserver(do)
    g.addObserver(go)
    for i in xrange(50):
        g.execute()

if __name__==&#39;__main__&#39;: main()
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/5091420087517253942/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/11/17-observer.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/5091420087517253942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/5091420087517253942'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/11/17-observer.html' title='第17章 Observerパターン : 状態の変化を通知する'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-4796412432014593975</id><published>2010-11-27T19:36:00.005+09:00</published><updated>2010-12-04T03:58:15.679+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="デザインパターン"/><title type='text'>第16章 Mediatorパターン : 相手は相談役1人だけ</title><content type='html'>&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;asins=4797327030&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
今回はMediatorパターン。Mediatorは仲介者で、オブジェクト間の連携を一手に担ってくれます。&lt;br /&gt;
下例のようなGUIプログラミングによく使われるそうです。MVCモデルに通じますね。&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;&lt;br /&gt;
今回はGUIが絡んでいるので、JavaScriptで書いてみました。&lt;br /&gt;
JavaScriptはほぼ初挑戦なので、変な実装とかあったら指摘もらえると助かります。&lt;br /&gt;
(JavaScriptのOOPってこんなにしんどいんですか？)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;実行結果&lt;/b&gt;&lt;br /&gt;
&lt;script&gt;
// id=&quot;my_content&quot; のelementがあると仮定している

function onLoad(){
    var container = document.getElementById(&quot;my_content&quot;);
    var loginform = new LoginForm();
    loginform.appendInto(container);
}


// class declaration
function ColleagueInputButton(){ // implements Colleague Interface
    this.initialize.apply(this, arguments);
}
ColleagueInputButton.prototype = {
     initialize:
        function(caption){
            this.content = document.createElement(&#39;input&#39;);
            this.content.setAttribute(&#39;type&#39;, &#39;button&#39;);
            this.content.setAttribute(&#39;value&#39;, caption);
        }
    ,appendInto:
        function(parentContainer){
            parentContainer.appendChild(this.content);
        }
    ,setMediator: // Colleague Interface method
        function(mediator){
            this.content.onclick = mediator.onClick;
        }
    ,setColleagueEnabled: // Colleague Interface method
        function(enabled){
            this.content.disabled = !enabled;
        }
};


// class declaration
function ColleagueInputTextField(){ // implements Colleague Interface
    this.initialize.apply(this, arguments);
}
ColleagueInputTextField.prototype = {
     initialize:
        function(text, columns, passwordtype){
            this.content = document.createElement(&#39;input&#39;);
            if(passwordtype){
                this.content.setAttribute(&#39;type&#39;, &#39;password&#39;);
            }else{
                this.content.setAttribute(&#39;type&#39;, &#39;text&#39;);
            }
            this.content.setAttribute(&#39;value&#39;, text);
            this.content.setAttribute(&#39;size&#39;, columns);
        }
    ,appendInto:
        function(parentContainer){
            parentContainer.appendChild(this.content);
        }
    ,getText:
        function(){
            return this.content.value;
        }
    ,setText:
        function(text){
            this.content.value = text;
            this.content.onchange();
        }
    ,setMediator: // Colleague Interface method
        function(mediator){
            this.content.onchange = mediator.colleagueChanged;
        }
    ,setColleagueEnabled: // Colleague Interface method
        function(enabled){
            this.content.disabled = !enabled;
            if(enabled){
                this.content.setAttribute(&#39;style&#39;, &#39;background-color: #FFF;&#39;);
            }else{
                this.content.setAttribute(&#39;style&#39;, &#39;background-color: #EEE;&#39;);
            }
        }
};


// class declaration
function ColleagueInputRadioButton(){ // implements Colleague Interface
    this.initialize.apply(this, arguments);
}
ColleagueInputRadioButton.prototype = {
     initialize:
        function(caption, groupname, state){
            this.content = document.createElement(&#39;input&#39;);
            this.content.setAttribute(&#39;type&#39;, &#39;radio&#39;);
            this.content.setAttribute(&#39;name&#39;, groupname);
            this.content.defaultChecked = state;
        }
    ,appendInto:
        function(parentContainer){
            parentContainer.appendChild(this.content);
        }
    ,isChecked:
        function(){
            return this.content.checked;
        }
    ,setMediator: // Colleague Interface method
        function(mediator){
            this.content.onchange = mediator.colleagueChanged;
        }
    ,setColleagueEnabled: // Colleague Interface method
        function(enabled){
            this.content.disabled = !enabled;
        }
};


// class declaration
function LoginForm(){ // implements Mediator Interface
    this.radioGuest = null;
    this.radioLogin = null;
    this.textUser = null;
    this.textPass = null;
    this.buttonOK = null;
    this.buttonCancel = null;
    this.initialize.apply(this, arguments);
}
LoginForm.prototype = {
     initialize:
        function(){
            self = this;
            this.content = document.createElement(&#39;form&#39;);
            this.createColleagues();

            this.radioGuest.appendInto(this.content);
            span = document.createElement(&#39;span&#39;);
            span.innerHTML = &quot;Guest&quot;;
            this.content.appendChild(span);
            this.radioLogin.appendInto(this.content);
            span = document.createElement(&#39;span&#39;);
            span.innerHTML = &quot;Login&quot;;
            this.content.appendChild(span);
            this.content.appendChild(document.createElement(&#39;br&#39;));

            span = document.createElement(&#39;span&#39;);
            span.innerHTML = &quot;Username:&amp;nbsp;&quot;;
            this.content.appendChild(span);
            this.textUser.appendInto(this.content);
            this.content.appendChild(document.createElement(&#39;br&#39;));
            span = document.createElement(&#39;span&#39;);
            span.innerHTML = &quot;Password:&amp;nbsp;&quot;;
            this.content.appendChild(span);
            this.textPass.appendInto(this.content);
            this.content.appendChild(document.createElement(&#39;br&#39;));

            this.buttonOK.appendInto(this.content);
            this.buttonCancel.appendInto(this.content);

            this.colleagueChanged();
        }
    ,appendInto:
        function(parentContainer){
            parentContainer.appendChild(this.content);
        }
    ,createColleagues: // Mediator Interface method
        function(){
            this.radioGuest = new ColleagueInputRadioButton(&quot;Guest&quot;, &quot;usertype&quot;, true);
            this.radioLogin = new ColleagueInputRadioButton(&quot;Login&quot;, &quot;usertype&quot;, false);
            this.textUser = new ColleagueInputTextField(&quot;&quot;, 10);
            this.textPass = new ColleagueInputTextField(&quot;&quot;, 10, true);
            this.buttonOK = new ColleagueInputButton(&quot;OK&quot;);
            this.buttonCancel = new ColleagueInputButton(&quot;Cancel&quot;);
            this.radioGuest.setMediator(this);
            this.radioLogin.setMediator(this);
            this.textUser.setMediator(this);
            this.textPass.setMediator(this);
            this.buttonOK.setMediator(this);
            this.buttonCancel.setMediator(this);
        }
    ,colleagueChanged: // Mediator Interface method
        function(){
            if(self.radioGuest.isChecked() === true){
                self.textUser.setColleagueEnabled(false);
                self.textPass.setColleagueEnabled(false);
                self.buttonOK.setColleagueEnabled(true);
            }else{
                self.textUser.setColleagueEnabled(true);
                // and also needs to check textUser&amp;textPass
                if(self.textUser.getText().length === 0){
                    self.textPass.setColleagueEnabled(false);
                    self.buttonOK.setColleagueEnabled(false);
                }else{
                    self.textPass.setColleagueEnabled(true);
                    if(self.textPass.getText().length === 0){
                        self.buttonOK.setColleagueEnabled(false);
                    }else{
                        self.buttonOK.setColleagueEnabled(true);
                    }
                }
            }
        }
    ,onClick:
        function(){
            if(this.value === &quot;Cancel&quot;){
                self.textUser.setText(&quot;&quot;);
                self.textPass.setText(&quot;&quot;);
            }
            else{
                if(self.radioGuest.isChecked() === true){
                    alert(&quot;Hello, Guest!&quot;);
                }else{
                    alert(&quot;Hello, &quot;+self.textUser.getText()+&quot;!\nYour pass is &quot;+self.textPass.getText()+&quot;, right??&quot;);
                }
            }
        }
};

            window.onload = onLoad;
&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div id=&quot;my_content&quot; style=&quot;border: 1px solid #CCC; padding: 1em;&quot;&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;ソースコード&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:js&quot;&gt;// id=&quot;my_content&quot; のelementがあると仮定している

function onLoad(){
    var container = document.getElementById(&quot;my_content&quot;);
    var loginform = new LoginForm();
    loginform.appendInto(container);
}


// class declaration
function ColleagueInputButton(){ // implements Colleague Interface
    this.initialize.apply(this, arguments);
}
ColleagueInputButton.prototype = {
     initialize:
        function(caption){
            this.content = document.createElement(&#39;input&#39;);
            this.content.setAttribute(&#39;type&#39;, &#39;button&#39;);
            this.content.setAttribute(&#39;value&#39;, caption);
        }
    ,appendInto:
        function(parentContainer){
            parentContainer.appendChild(this.content);
        }
    ,setMediator: // Colleague Interface method
        function(mediator){
            this.content.onclick = mediator.onClick;
        }
    ,setColleagueEnabled: // Colleague Interface method
        function(enabled){
            this.content.disabled = !enabled;
        }
};


// class declaration
function ColleagueInputTextField(){ // implements Colleague Interface
    this.initialize.apply(this, arguments);
}
ColleagueInputTextField.prototype = {
     initialize:
        function(text, columns, passwordtype){
            this.content = document.createElement(&#39;input&#39;);
            if(passwordtype){
                this.content.setAttribute(&#39;type&#39;, &#39;password&#39;);
            }else{
                this.content.setAttribute(&#39;type&#39;, &#39;text&#39;);
            }
            this.content.setAttribute(&#39;value&#39;, text);
            this.content.setAttribute(&#39;size&#39;, columns);
        }
    ,appendInto:
        function(parentContainer){
            parentContainer.appendChild(this.content);
        }
    ,getText:
        function(){
            return this.content.value;
        }
    ,setText:
        function(text){
            this.content.value = text;
            this.content.onchange();
        }
    ,setMediator: // Colleague Interface method
        function(mediator){
            this.content.onchange = mediator.colleagueChanged;
        }
    ,setColleagueEnabled: // Colleague Interface method
        function(enabled){
            this.content.disabled = !enabled;
            if(enabled){
                this.content.setAttribute(&#39;style&#39;, &#39;background-color: #FFF;&#39;);
            }else{
                this.content.setAttribute(&#39;style&#39;, &#39;background-color: #EEE;&#39;);
            }
        }
};


// class declaration
function ColleagueInputRadioButton(){ // implements Colleague Interface
    this.initialize.apply(this, arguments);
}
ColleagueInputRadioButton.prototype = {
     initialize:
        function(caption, groupname, state){
            this.content = document.createElement(&#39;input&#39;);
            this.content.setAttribute(&#39;type&#39;, &#39;radio&#39;);
            this.content.setAttribute(&#39;name&#39;, groupname);
            this.content.defaultChecked = state;
        }
    ,appendInto:
        function(parentContainer){
            parentContainer.appendChild(this.content);
        }
    ,isChecked:
        function(){
            return this.content.checked;
        }
    ,setMediator: // Colleague Interface method
        function(mediator){
            this.content.onchange = mediator.colleagueChanged;
        }
    ,setColleagueEnabled: // Colleague Interface method
        function(enabled){
            this.content.disabled = !enabled;
        }
};


// class declaration
function LoginForm(){ // implements Mediator Interface
    this.radioGuest = null;
    this.radioLogin = null;
    this.textUser = null;
    this.textPass = null;
    this.buttonOK = null;
    this.buttonCancel = null;
    this.initialize.apply(this, arguments);
}
LoginForm.prototype = {
     initialize:
        function(){
            self = this;
            this.content = document.createElement(&#39;form&#39;);
            this.createColleagues();

            this.radioGuest.appendInto(this.content);
            span = document.createElement(&#39;span&#39;);
            span.innerHTML = &quot;Guest&quot;;
            this.content.appendChild(span);
            this.radioLogin.appendInto(this.content);
            span = document.createElement(&#39;span&#39;);
            span.innerHTML = &quot;Login&quot;;
            this.content.appendChild(span);
            this.content.appendChild(document.createElement(&#39;br&#39;));

            span = document.createElement(&#39;span&#39;);
            span.innerHTML = &quot;Username:&amp;nbsp;&quot;;
            this.content.appendChild(span);
            this.textUser.appendInto(this.content);
            this.content.appendChild(document.createElement(&#39;br&#39;));
            span = document.createElement(&#39;span&#39;);
            span.innerHTML = &quot;Password:&amp;nbsp;&quot;;
            this.content.appendChild(span);
            this.textPass.appendInto(this.content);
            this.content.appendChild(document.createElement(&#39;br&#39;));

            this.buttonOK.appendInto(this.content);
            this.buttonCancel.appendInto(this.content);

            this.colleagueChanged();
        }
    ,appendInto:
        function(parentContainer){
            parentContainer.appendChild(this.content);
        }
    ,createColleagues: // Mediator Interface method
        function(){
            this.radioGuest = new ColleagueInputRadioButton(&quot;Guest&quot;, &quot;usertype&quot;, true);
            this.radioLogin = new ColleagueInputRadioButton(&quot;Login&quot;, &quot;usertype&quot;, false);
            this.textUser = new ColleagueInputTextField(&quot;&quot;, 10);
            this.textPass = new ColleagueInputTextField(&quot;&quot;, 10, true);
            this.buttonOK = new ColleagueInputButton(&quot;OK&quot;);
            this.buttonCancel = new ColleagueInputButton(&quot;Cancel&quot;);
            this.radioGuest.setMediator(this);
            this.radioLogin.setMediator(this);
            this.textUser.setMediator(this);
            this.textPass.setMediator(this);
            this.buttonOK.setMediator(this);
            this.buttonCancel.setMediator(this);
        }
    ,colleagueChanged: // Mediator Interface method
        function(){
            if(self.radioGuest.isChecked() === true){
                self.textUser.setColleagueEnabled(false);
                self.textPass.setColleagueEnabled(false);
                self.buttonOK.setColleagueEnabled(true);
            }else{
                self.textUser.setColleagueEnabled(true);
                // and also needs to check textUser&amp;amp;textPass
                if(self.textUser.getText().length === 0){
                    self.textPass.setColleagueEnabled(false);
                    self.buttonOK.setColleagueEnabled(false);
                }else{
                    self.textPass.setColleagueEnabled(true);
                    if(self.textPass.getText().length === 0){
                        self.buttonOK.setColleagueEnabled(false);
                    }else{
                        self.buttonOK.setColleagueEnabled(true);
                    }
                }
            }
        }
    ,onClick:
        function(){
            if(this.value === &quot;Cancel&quot;){
                self.textUser.setText(&quot;&quot;);
                self.textPass.setText(&quot;&quot;);
            }
            else{
                if(self.radioGuest.isChecked() === true){
                    alert(&quot;Hello, Guest!&quot;);
                }else{
                    alert(&quot;Hello, &quot;+self.textUser.getText()+&quot;!\nYour pass is &quot;+self.textPass.getText()+&quot;, right??&quot;);
                }
            }
        }
};

window.onload = onLoad;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/4796412432014593975/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/11/16-mediator-1.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/4796412432014593975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/4796412432014593975'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/11/16-mediator-1.html' title='第16章 Mediatorパターン : 相手は相談役1人だけ'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-2431640432675397858</id><published>2010-11-26T18:22:00.001+09:00</published><updated>2010-11-27T18:50:18.232+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="vim"/><title type='text'>ネットで見かけた素敵なvimrc</title><content type='html'>&lt;pre&gt;imap {} {}&amp;lt;Left&amp;gt;
imap [] []&amp;lt;Left&amp;gt;
imap () ()&amp;lt;Left&amp;gt;
imap &amp;lt;&amp;gt; &amp;lt;&amp;gt;&amp;lt;Left&amp;gt;
imap &#39;&#39; &#39;&#39;&amp;lt;Left&amp;gt;
imap &quot;&quot; &quot;&quot;&amp;lt;Left&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
発想の勝利ですね。&lt;br /&gt;
&lt;br /&gt;
追記(2010/11/27 18:49)&lt;br /&gt;
空のカッコを書くときに異常にウザ買ったので消しました。</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/2431640432675397858/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/11/vimrc.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/2431640432675397858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/2431640432675397858'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/11/vimrc.html' title='ネットで見かけた素敵なvimrc'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-6283711289996035373</id><published>2010-11-26T14:53:00.002+09:00</published><updated>2010-12-04T03:58:28.723+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="デザインパターン"/><title type='text'>第15章 Facadeパターン : シンプルな窓口</title><content type='html'>&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;asins=4797327030&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
Facadeはファサードって読むらしいです。フランス語。&lt;br /&gt;
概要とポイントは本文から引用します。&lt;br /&gt;
&lt;blockquote&gt;Facadeパターンは、複雑にからみ合ってごちゃごちゃした詳細をまとめ、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;高レベルのインターフェイス&lt;/span&gt;(API)を提供します。(中略)Facade役はシステムの内側にある各クラスの役割や依存関係を考えて、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;正しい順番でクラスを利用&lt;/span&gt;します。&lt;/blockquote&gt;&lt;blockquote&gt;非常に大きなシステムが、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;多数のクラス・多数のパッケージ&lt;/span&gt;を抱えるとき、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;要所要所にFacadeパターン&lt;/span&gt;を適用すると、システムはより便利になるでしょう。&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;はっきりと言葉で表現できるノウハウ&lt;/span&gt;は、プログラマの頭の中に隠しておくべきものではなく、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;コードとして表現&lt;/span&gt;しておくべきものなのです。&lt;/blockquote&gt;いつも決まった手順でクラスを利用するときは、その手順そのものをクラス(メソッド)にしてしまおうということです。&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
今回は練習問題の、リンク集をつくる方を書きました。&lt;br /&gt;
また、色々簡略化しています。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;実行結果&lt;/b&gt;&lt;br /&gt;
linkpage.html&lt;br /&gt;
&lt;pre&gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Link page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;
&amp;lt;h1&amp;gt;Link page&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&quot;mailto:hyuki@hyuki.com&quot;&amp;gt;Hiroshi Yuki&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&quot;mailto:hanako@hyuki.com&quot;&amp;gt;Hanako Sato&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&quot;mailto:tomura@hyuki.com&quot;&amp;gt;Tomura&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&quot;mailto:mamoru@hyuki.com&quot;&amp;gt;Mamoru Takahashi&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;ソースコード&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;#!/usr/bin/env python
# -*- coding: utf8 -*-

class Database:
    def __init__(self): raise Exception(&quot;Do not construct instances&quot;)
    @classmethod
    def getProperties(cls):
        return [
                 (&quot;hyuki@hyuki.com&quot;,&quot;Hiroshi Yuki&quot;)
                ,(&quot;hanako@hyuki.com&quot;,&quot;Hanako Sato&quot;)
                ,(&quot;tomura@hyuki.com&quot;,&quot;Tomura&quot;)
                ,(&quot;mamoru@hyuki.com&quot;,&quot;Mamoru Takahashi&quot;)
                ]

class HtmlWriter:

    def __init__(self, fsock):
        self.__fsock = fsock

    def __print(self, string):
        try:
            print &amp;gt;&amp;gt;self.__fsock, string
        except IOError, (errno, strerror):
            print &quot;I/O error(%s): %s&quot; % (errno, strerror)

    def makeTitle(self, title):
        self.__print(&quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&quot;+title.encode(&quot;utf_8&quot;)+&quot;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&quot;)
        self.__print(&quot;&amp;lt;h1&amp;gt;&quot;+title.encode(&quot;utf_8&quot;)+&quot;&amp;lt;/h1&amp;gt;&quot;)

    def makeParagraph(self, string):
        self.__print(&quot;&amp;lt;p&amp;gt;&quot;+string.encode(&quot;utf_8&quot;)+&quot;&amp;lt;/p&amp;gt;&quot;)

    def makeLink(self, href, caption):
        self.makeParagraph(&#39;&amp;lt;a href=&quot;%s&quot;&amp;gt;%s&amp;lt;/a&amp;gt;&#39; % (href, caption))

    def makeMailTo(self, mailaddr, username):
        self.makeLink(&#39;mailto:&#39;+mailaddr, username)

    def close(self):
        self.__print(&quot;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&quot;)
        self.__fsock.close()


class PageMaker:
    def __init__(self): raise Exception(&quot;Do not construct instances&quot;)

    @classmethod
    def makeLinkPage(cls, filename):
        try:
            fsock = open(filename, &#39;w&#39;)
        except IOError, (errno, strerror):
            print &quot;I/O error(%s): %s&quot; % (errno, strerror)

        htmlwriter = HtmlWriter(fsock)
        dbList = Database.getProperties()

        htmlwriter.makeTitle(&quot;Link page&quot;)
        for t in dbList:
            htmlwriter.makeMailTo(t[0], t[1])
        htmlwriter.close()


def main():
    PageMaker.makeLinkPage(&quot;linkpage.html&quot;)

if __name__==&#39;__main__&#39;: main()
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/6283711289996035373/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/11/15-facade.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/6283711289996035373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/6283711289996035373'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/11/15-facade.html' title='第15章 Facadeパターン : シンプルな窓口'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-7817344567884298529</id><published>2010-11-25T11:26:00.001+09:00</published><updated>2010-12-04T03:58:41.595+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="デザインパターン"/><title type='text'>第14章 Chain of Responsibilityパターン : 責任のたらい回し</title><content type='html'>&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;asins=4797327030&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
今回はChain of Responsibility。UIなどでよく使われるパターンだそうです。&lt;br /&gt;
&lt;br /&gt;
というのも、UIはビューコンポーネントのようなものを入れ子にして構成されることが多く、&lt;br /&gt;
(&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #741b47;&quot;&gt;Window&lt;/span&gt; → &lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #351c75;&quot;&gt;Canvas&lt;/span&gt; → &lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #0b5394;&quot;&gt;TextField&lt;/span&gt; 的な)&lt;br /&gt;
そのUIをユーザがクリック(タップ)したりキーボード操作したりする『要求』に対し、その要求をどのコンポーネントが処理するかは、普通『たらい回し』にされることが多いからです。&lt;br /&gt;
(上の例だと&amp;nbsp;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #0b5394;&quot;&gt;TextField&lt;/span&gt;&amp;nbsp;→&amp;nbsp;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #351c75;&quot;&gt;Canvas&lt;/span&gt;&amp;nbsp;→&amp;nbsp;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #741b47;&quot;&gt;Window&lt;/span&gt;)&lt;br /&gt;
&lt;br /&gt;
すなわち、Chain of Responsibilityパターンは&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;(主にユーザなどによる)&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;要求&lt;/span&gt;があり &lt;/li&gt;
&lt;li&gt;その要求の&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;処理先を動的&lt;/span&gt;に設定したい&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
時に最適なパターンと言えそうです。&lt;br /&gt;
&lt;br /&gt;
また、Compositeパターンなどの再帰的構造でよく使うそうです。&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;&lt;br /&gt;
&lt;b&gt;実行結果&lt;/b&gt;&lt;br /&gt;
&lt;pre&gt;[0] is resolved by [Bob].
[33] is resolved by [Bob].
[66] is resolved by [Bob].
[99] is resolved by [Bob].
[132] is resolved by [Danie].
[165] is resolved by [Danie].
[198] is resolved by [Danie].
[231] is resolved by [Elmo].
[264] is resolved by [Fred].
[297] is resolved by [Elmo].
[330] cannot be resolved.
[363] is resolved by [Elmo].
[396] cannot be resolved.
[429] is resolved by [Charlie].
[462] cannot be resolved.
[495] is resolved by [Elmo].&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;ソースコード&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;#!/usr/bin/env python
# -*- coding: utf8 -*-

class Trouble:
    def __init__(self, number): self.number = number
    def __str__(self): return &quot;[%d]&quot; % (self.number)


class Support:
    def __init__(self): raise Exception(&quot;Abstract class&quot;)
    def __str__(self): return &quot;[%s]&quot; % self.name

    # final method - template method
    def support(self, trouble):
        if self._resolve(trouble):
            self._done(trouble)
        elif self.next is not None:
            self.next.support(trouble)
        else:
            self._fail(trouble)

    def _resolve(self, trouble): raise NotImplementedError
    def _done(self, trouble): print &quot;%s is resolved by %s.&quot; % (trouble, self)
    def _fail(self, trouble): print &quot;%s cannot be resolved.&quot; % (trouble)

    def setNext(self, next):
        self.next = next
        return self.next


class NoSupport(Support):
    def __init__(self, name):
        self.name = name
        self.next = None

    def _resolve(self, trouble): return False


class LimitSupport(Support):
    def __init__(self, name, limit):
        self.name = name
        self.limit = limit
        self.next = None

    def _resolve(self, trouble):
        return True if trouble.number &amp;lt; self.limit else False


class OddSupport(Support):
    def __init__(self, name):
        self.name = name
        self.next = None

    def _resolve(self, trouble):
        return True if trouble.number % 2 == 1 else False


class SpecialSupport(Support):
    def __init__(self, name, number):
        self.name = name
        self.number = number
        self.next = None

    def _resolve(self, trouble):
        return True if trouble.number == self.number else False


def main():
    m_alice = NoSupport(&quot;Alice&quot;)
    m_bob = LimitSupport(&quot;Bob&quot;, 100)
    m_charlie = SpecialSupport(&quot;Charlie&quot;, 429)
    m_danie = LimitSupport(&quot;Danie&quot;, 200)
    m_elmo = OddSupport(&quot;Elmo&quot;)
    m_fred = LimitSupport(&quot;Fred&quot;, 300)

    m_alice.setNext(m_bob).setNext(m_charlie).setNext(m_danie).setNext(m_elmo).setNext(m_fred)

    for i in xrange(0, 500, 33):
        m_alice.support(Trouble(i))

if __name__==&#39;__main__&#39;: main()
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/7817344567884298529/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/11/14-chain-of-responsibility.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/7817344567884298529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/7817344567884298529'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/11/14-chain-of-responsibility.html' title='第14章 Chain of Responsibilityパターン : 責任のたらい回し'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-5537189267865536585</id><published>2010-11-24T13:07:00.001+09:00</published><updated>2010-12-04T03:58:54.553+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="デザインパターン"/><title type='text'>第13章 Visitorパターン : 構造を渡り歩きながら仕事をする ~design patterns with python~</title><content type='html'>&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;asins=4797327030&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
気がつけば、もう本の半分以上の量を消化していました。&lt;br /&gt;
今回はVisitorパターン。キーワードは『&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;データ構造と処理を分離する&lt;/span&gt;』です。&lt;br /&gt;
&lt;br /&gt;
例えば、データモデルクラスを作って、その中にデータ処理のメソッドなんかを追加すると、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;モデルクラスが肥大&lt;/span&gt;してしまうことがままありました。&lt;br /&gt;
(アクセサぐらいならまだいいのですが、シリアライザやパーサなんかもついつい入れがちでした)&lt;br /&gt;
そんな時は大抵別のクラスを用意してメソッド類を引越ししてやるのですが、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;色んなモデルクラスの色んな処理クラスが混在&lt;/span&gt;して見通しが悪くなりがちでした。&lt;br /&gt;
Visitorパターンは、こうしたケースに一貫した解決を与えるいい方法ではないかと思いました。&lt;br /&gt;
&lt;br /&gt;
また書籍内の例を見ても分かりますが、CompositeパターンやDecoratorパターンなどの再帰的なパターンと相性が良さそうです。&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
visit()のオーバーロードは特に意味が無いようなので、メソッドを分けてあります。&lt;br /&gt;
iterator()は単にリストを返すようにしてあります。&lt;br /&gt;
練習問題13-1には、対象のファイルが存在するディレクトリのパスも併せて出力するように勝手に変更 してあります。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;実行結果&lt;/b&gt;&lt;br /&gt;
&lt;pre&gt;Making root entries...
/root (30000)
/root/bin (30000)
/root/bin/vi (10000)
/root/bin/latex (20000)
/root/tmp (0)
/root/usr (0)

Making user entries...
/root (31850)
/root/bin (30000)
/root/bin/vi (10000)
/root/bin/latex (20000)
/root/tmp (0)
/root/usr (1850)
/root/usr/yuki (300)
/root/usr/yuki/diary.html (100)
/root/usr/yuki/Composite.java (200)
/root/usr/hanako (650)
/root/usr/hanako/memo.tex (300)
/root/usr/hanako/index.html (350)
/root/usr/tomura (900)
/root/usr/tomura/game.doc (400)
/root/usr/tomura/junk.mail (500)

HTML files are:
diary.html (100) in /root/usr/yuki
index.html (350) in /root/usr/hanako&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;ソースコード&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;#!/usr/bin/env python
# -*- coding: utf8 -*-

class FileTreatmentException(Exception):
    def __init__(self):
        pass

class __Element:
    def __init__(self): raise NotImplementedError
    def accept(self, visitor): raise NotImplementedError

class _Entry(__Element):
    def __init__(self): raise Exception(&quot;Abstract class&quot;)
    def getName(self): raise NotImplementedError
    def getSize(self): raise NotImplementedError
    def add(self, entry): raise FileTreatmentException
    def iterator(self): raise FileTreatmentException
    def __str__(self): return &quot;%s (%d)&quot; % (self.getName(), self.getSize())


class File(_Entry):
    def __init__(self, name, size):
        self.__name = name
        self.__size = size

    def getName(self): return self.__name
    def getSize(self): return self.__size

    def accept(self, visitor):
        visitor.visitFile(self)


class Directory(_Entry):
    def __init__(self, name):
        self.__name = name
        self.directory = []

    def getName(self): return self.__name
    def getSize(self): return sum([e.getSize() for e in self.directory])

    def add(self, entry):
        self.directory.append(entry)

    def iterator(self):
        return self.directory

    def accept(self, visitor):
        visitor.visitDirectory(self)


class _Visitor:
    def __init__(self): raise Exception(&quot;Abstract class&quot;)
    def visitFile(self, thefile): raise NotImplementedError
    def visitDirectory(self, directory): raise NotImplementedError

class ListVisitor(_Visitor):
    def __init__(self):
        self.__currentdir = &quot;&quot;

    def visitFile(self, thefile):
        print self.__currentdir+&quot;/&quot;+str(thefile)

    def visitDirectory(self, directory):
        print self.__currentdir+&quot;/&quot;+str(directory)

        # ディレクトリ内を走査するために一旦入る
        savedir = self.__currentdir
        self.__currentdir = self.__currentdir+&quot;/&quot;+directory.getName()

        for e in directory.iterator():
            e.accept(self)

        # 走査が終わったらディレクトリを出る
        self.__currentdir = savedir

#13-1
class FileFindVisitor(_Visitor):
    def __init__(self, pattern):
        self.__pattern = pattern
        self.__currentdir = &quot;&quot;
        self.__founds = [] #(file, dirname which contains the file)

    def visitFile(self, thefile):
        if thefile.getName().find(self.__pattern) is not -1:
            self.__founds.append((thefile, self.__currentdir))

    def visitDirectory(self, directory):
        savedir = self.__currentdir
        self.__currentdir = self.__currentdir+&quot;/&quot;+directory.getName()

        for e in directory.iterator():
            e.accept(self)

        self.__currentdir = savedir

    def getFoundFiles(self):
        return self.__founds


def main():
    try:
        print &quot;Making root entries...&quot;
        m_rootdir = Directory(&quot;root&quot;)
        m_bindir = Directory(&quot;bin&quot;)
        m_tmpdir = Directory(&quot;tmp&quot;)
        m_usrdir = Directory(&quot;usr&quot;)
        m_rootdir.add(m_bindir)
        m_rootdir.add(m_tmpdir)
        m_rootdir.add(m_usrdir)
        m_bindir.add(File(&quot;vi&quot;, 10000))
        m_bindir.add(File(&quot;latex&quot;, 20000))
        m_rootdir.accept(ListVisitor())

        print &quot;&quot;
        print &quot;Making user entries...&quot;
        m_yuki = Directory(&quot;yuki&quot;)
        m_hanako = Directory(&quot;hanako&quot;)
        m_tomura = Directory(&quot;tomura&quot;)
        m_usrdir.add(m_yuki)
        m_usrdir.add(m_hanako)
        m_usrdir.add(m_tomura)
        m_yuki.add(File(&quot;diary.html&quot;, 100))
        m_yuki.add(File(&quot;Composite.java&quot;, 200))
        m_hanako.add(File(&quot;memo.tex&quot;, 300))
        m_hanako.add(File(&quot;index.html&quot;, 350))
        m_tomura.add(File(&quot;game.doc&quot;, 400))
        m_tomura.add(File(&quot;junk.mail&quot;, 500))
        m_rootdir.accept(ListVisitor())

        #13-1
        print &quot;&quot;
        print &quot;HTML files are:&quot;
        ffv = FileFindVisitor(&quot;.html&quot;)
        m_rootdir.accept(ffv)
        for (f,d) in ffv.getFoundFiles():
            print &quot;%s in %s&quot; % (str(f), d)

    except FileTreatmentException:
        print &quot;FileTreatmentException raised&quot;

if __name__==&#39;__main__&#39;: main()
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/5537189267865536585/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/11/13-visitor-design-patterns-with-python.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/5537189267865536585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/5537189267865536585'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/11/13-visitor-design-patterns-with-python.html' title='第13章 Visitorパターン : 構造を渡り歩きながら仕事をする ~design patterns with python~'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-280802042219423531</id><published>2010-11-23T22:20:00.002+09:00</published><updated>2010-12-04T03:59:08.461+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="デザインパターン"/><title type='text'>第12章 Decoratorパターン : 飾り枠と中身の同一視 ~ design patterns with python ~</title><content type='html'>&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;asins=4797327030&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
Decoratorパターンは前回のCompositeパターン&lt;br /&gt;
&lt;a href=&quot;http://ksk77.blogspot.com/2010/11/11-composite.html&quot;&gt;http://ksk77.blogspot.com/2010/11/11-composite.html&lt;/a&gt;&lt;br /&gt;
と同様、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;同一視&lt;/span&gt;がキーワードですね。&lt;br /&gt;
&lt;br /&gt;
DecoratorパターンのUML(Fig 12-5 p.179)を見てみると、CompositeパターンのUML(Fig 11-3 p.164)とよく似ているのが分かります。&lt;br /&gt;
それもそのはずで、前回のファイルシステムの例で考えて見れば、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #a64d79;&quot;&gt;ディレクトリを『飾り枠』として&lt;/span&gt;も同様の構造を記述できることが想像できます。またCompositeでは末端(Leaf)が分離され、Decoratorでは根っこ(ConcreteComponent)が分離されています。&lt;br /&gt;
&lt;br /&gt;
Decoratorパターンは、言うなれば、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #a64d79;&quot;&gt;中身が常に一つで、追加や取り出しが出来ないCompositeパターン&lt;/span&gt;でしょうか。…普通そんな風には考えないと思いますが。&lt;br /&gt;
&lt;br /&gt;
Decoratorパターンの特徴は、&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;どこを切ってもそこにはただ一つのComponentがある&lt;/span&gt;という点でしょう。マトリョーシカのように。&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
SideBorderクラスのコンストラクタは引数の順番が逆な方が分かりやすいと思います。&lt;br /&gt;
あと今回は書籍内のコードを読まずに書いたので、実装が書籍に沿わないかもです。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;実行結果&lt;/b&gt;&lt;br /&gt;
&lt;pre&gt;Hello, world.
#Hello, world.#
+---------------+
|#Hello, world.#|
+---------------+
/+----------------+/
/|+--------------+|/
/||*+----------+*||/
/||*|konnichiwa|*||/
/||*+----------+*||/
/|+--------------+|/
/+----------------+/
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;ソースコード&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;#!/usr/bin/env python
# -*- coding: utf8 -*-

class Display:
    def __init__(self): raise Exception(&quot;Abstract class&quot;)
    def columns(self): raise NotImplementedError
    def rows(self): raise NotImplementedError
    def rowText(self, index): raise NotImplementedError
    def show(self):
        for i in xrange(self.rows()):
            print self.rowText(i)

class StringDisplay(Display):
    def __init__(self, string):
        self.__string = string

    def columns(self):
        return len(self.__string)

    def rows(self):
        return 1

    def rowText(self, index):
        return self.__string


class Border(Display):
    _display = None


class SideBorder(Border):
    def __init__(self, borderChar, display):
        self.__borderChar = borderChar
        self._display = display

    def columns(self):
        return self._display.columns() + 2

    def rows(self):
        return self._display.rows()

    def rowText(self, index):
        return self.__borderChar + self._display.rowText(index) + self.__borderChar


class FullBorder(Border):
    def __init__(self, display):
        self._display = display

    def columns(self):
        return self._display.columns() + 2

    def rows(self):
        return self._display.rows() + 2

    def rowText(self, index):
        if index == 0 or index == self.rows()-1:
            return &quot;+&quot; + &quot;&quot;.join([&quot;-&quot; for i in xrange(self._display.columns())]) + &quot;+&quot;
        else:
            return &quot;|&quot; + self._display.rowText(index-1) + &quot;|&quot;



def main():
    # these data type are Display
    m_b1 = StringDisplay(&quot;Hello, world.&quot;)
    m_b2 = SideBorder(&quot;#&quot;, m_b1)
    m_b3 = FullBorder(m_b2)
    m_b4 = SideBorder(&quot;/&quot;, FullBorder(FullBorder(SideBorder(&quot;*&quot;, FullBorder(StringDisplay(&quot;konnichiwa&quot;))))))
    m_b1.show()
    m_b2.show()
    m_b3.show()
    m_b4.show()

if __name__==&#39;__main__&#39;: main()
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/280802042219423531/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/11/12-decorator-design-patterns-with.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/280802042219423531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/280802042219423531'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/11/12-decorator-design-patterns-with.html' title='第12章 Decoratorパターン : 飾り枠と中身の同一視 ~ design patterns with python ~'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7513445162961451638.post-5145007095967517644</id><published>2010-11-23T19:00:00.002+09:00</published><updated>2010-12-04T03:59:18.172+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="デザインパターン"/><title type='text'>第11章 Compositeパターン : 容器と中身の同一視</title><content type='html'>&lt;iframe frameborder=&quot;0&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=000000&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=000000&amp;amp;lc1=0000FF&amp;amp;t=ksk77-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;asins=4797327030&quot; style=&quot;height: 240px; width: 120px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
第11章はCompositeパターン。これは分かりやすい上に利用頻度も高そうなデザインパターンです。&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #cc0000;&quot;&gt;再帰的なクラス構造が出てきたら、このパターンが適用できないかを常に意識&lt;/span&gt;したほうがいいでしょう。&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Leaf役とComposite役とで&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #a64d79;&quot;&gt;共通な実装&lt;/span&gt;にしたければ&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;Componentに実装&lt;/span&gt;し、&lt;/li&gt;
&lt;li&gt;それぞれで&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #a64d79;&quot;&gt;違う実装&lt;/span&gt;にしたければ&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #674ea7;&quot;&gt;Componentで定義&lt;/span&gt;(宣言)だけして、LeafとCompositeそれぞれで実装すればいい&lt;/li&gt;
&lt;/ul&gt;という点も、コードの見通しが良くなっていいですね。&lt;br /&gt;
&lt;br /&gt;
add/remove/getChild は、例と同じようにComponent(親)にエラーとして実装し、Compositeでオーバーライドするのが好きです。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;実行結果&lt;/b&gt;&lt;br /&gt;
&lt;pre&gt;Making root entries...
/root (30000)
/root/bin (30000)
/root/bin/vi (10000)
/root/bin/latex (20000)
/root/tmp (0)
/root/usr (0)

Making user entries...
/root (31500)
/root/bin (30000)
/root/bin/vi (10000)
/root/bin/latex (20000)
/root/tmp (0)
/root/usr (1500)
/root/usr/yuki (300)
/root/usr/yuki/diary.html (100)
/root/usr/yuki/Composite.java (200)
/root/usr/hanako (300)
/root/usr/hanako/memo.tex (300)
/root/usr/tomura (900)
/root/usr/tomura/game.doc (400)
/root/usr/tomura/junk.mail (500)

#11-2
/root (100)
/root/usr (100)
/root/usr/yuki (100)
/root/usr/yuki/Composite.java (100)
file = /root/usr/yuki/Composite.java
yuki = /root/usr/yuki
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;ソースコード&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;#!/usr/bin/env python
# -*- coding: utf8 -*-

class FileTreatmentException(Exception):
    def __init__(self):
        print &quot;FileTreatmentException raised&quot;


class Entry:
    def __init__(self): raise Exception(&quot;Abstract class&quot;)
    def getName(self): raise NotImplementedError
    def getSize(self): raise NotImplementedError
    def printList(self): self._printList(&quot;&quot;)
    def _printList(self, prefix): raise NotImplementedError
    def add(self, entry): raise FileTreatmentException
    def __str__(self): return &quot;%s (%d)&quot; % (self.getName(), self.getSize())

    #11-2
    def getFullName(self):
        entry = self
        fullname = &quot;&quot;
        while entry is not None:
            fullname = &quot;/&quot; + entry.getName() + fullname
            entry = entry.parent
        return fullname


class File(Entry):
    def __init__(self, name, size):
        self.__name = name
        self.__size = size
        self.parent = None

    def getName(self): return self.__name
    def getSize(self): return self.__size
    def _printList(self, prefix): print prefix+&quot;/&quot;+str(self)


class Directory(Entry):
    def __init__(self, name):
        self.__name = name
        self.directory = []
        self.parent = None

    def getName(self): return self.__name
    def getSize(self): return sum([e.getSize() for e in self.directory])

    def _printList(self, prefix):
        print prefix+&quot;/&quot;+str(self)
        for e in self.directory: e._printList(prefix+&quot;/&quot;+self.__name)

    def add(self, entry):
        self.directory.append(entry)
        entry.parent = self #11-2


def main():
    print &quot;Making root entries...&quot;
    m_rootdir = Directory(&quot;root&quot;)
    m_bindir = Directory(&quot;bin&quot;)
    m_tmpdir = Directory(&quot;tmp&quot;)
    m_usrdir = Directory(&quot;usr&quot;)
    m_rootdir.add(m_bindir)
    m_rootdir.add(m_tmpdir)
    m_rootdir.add(m_usrdir)
    m_bindir.add(File(&quot;vi&quot;, 10000))
    m_bindir.add(File(&quot;latex&quot;, 20000))
    m_rootdir.printList()

    print &quot;&quot;
    print &quot;Making user entries...&quot;
    m_yuki = Directory(&quot;yuki&quot;)
    m_hanako = Directory(&quot;hanako&quot;)
    m_tomura = Directory(&quot;tomura&quot;)
    m_usrdir.add(m_yuki)
    m_usrdir.add(m_hanako)
    m_usrdir.add(m_tomura)
    m_yuki.add(File(&quot;diary.html&quot;, 100))
    m_yuki.add(File(&quot;Composite.java&quot;, 200))
    m_hanako.add(File(&quot;memo.tex&quot;, 300))
    m_tomura.add(File(&quot;game.doc&quot;, 400))
    m_tomura.add(File(&quot;junk.mail&quot;, 500))
    m_rootdir.printList()

    #11-2
    print &quot;&quot;
    print &quot;#11-2&quot;
    m_rootdir = Directory(&quot;root&quot;);
    m_usrdir = Directory(&quot;usr&quot;);
    m_rootdir.add(m_usrdir);
    m_yuki = Directory(&quot;yuki&quot;);
    m_usrdir.add(m_yuki);
    m_file = File(&quot;Composite.java&quot;, 100);
    m_yuki.add(m_file);
    m_rootdir.printList();
    print &quot;file = &quot; + m_file.getFullName()
    print &quot;yuki = &quot; + m_yuki.getFullName()

if __name__==&#39;__main__&#39;: main()
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ksk77.blogspot.com/feeds/5145007095967517644/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://ksk77.blogspot.com/2010/11/11-composite.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/5145007095967517644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7513445162961451638/posts/default/5145007095967517644'/><link rel='alternate' type='text/html' href='http://ksk77.blogspot.com/2010/11/11-composite.html' title='第11章 Compositeパターン : 容器と中身の同一視'/><author><name>ksk77</name><uri>http://www.blogger.com/profile/05600360228844540339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>