PHPでsingletonパターンを有効に使おう!
PHPをしていてオブジェクト指向を勉強してる人向けです。
PHPはバージョンが5になってから、オブジェクト指向型の言語に近づいてきました。
オブジェクト指向は保守性が高いことが最大の利点と言えると思います。
(個人的な意見ですが)
しかし、まだまだPHPは完璧なオブジェクト指向型言語とは言えません。
完璧でない点を挙げますと・・・
・クラスの外にコードが書ける(C++なんかもそうだが。)
・データ型のすべてがオブジェクトではない
・packageがない
・classにアクセス修飾子をつけられない
・nativeなオブジェクトが少ない
まぁ、上記の機能は言語の簡易性が失われてしまうので、
PHPの取り柄である「簡単さ」という点からいえば、必要ない機能なのかもしれません。
PHP5はカンタンなまま、適度にOOPできるというバランスの良さがいいですね。
さて、上記の「PHPにない機能」のうち、
「classにアクセス修飾子がつけられない」ということが多少響いてくるデザインパターンがあります。
それがsingletonパターンです。
singletonパターンは、インスタンスの数を制限できるパターンです。
インスタンスを複数持つこともできるので、いろいろと応用が効くのですが、
ここではインスタンスを1つしか保有しないsingletonパターンについて述べたいと思います。
では問題です。
staticなabstractクラスと、インスタンスを1つしか保有しないsingletonパターンは、
どう違うのでしょうか。(PHP5での話。)
abstract class Sample{
private $var;
public static function set($var){
self::$var=$var;
}
}
↑こんな感じにすればインスタンス化しなくたって、
充分一つのオブジェクトっぽく機能するんですよね。
オブジェクト化することで速度は落ちるっていうし、
いちいちメモリ使うんならクラス関数でやっちまったらいいのでは?
私は結構最近まで↑のようなことを思ってました。
インスタンス化しないのなら、「オブジェクト指向」ならぬ「クラス指向」じゃん。
正解は・・・
1.インスタンス化することで、オブジェクトの差し替えができる。
2.インスタンス化することで、アクセスの制限が可能となる。
1はまぁ誰もが考えるでしょう。
$d=$obj->getData();
と書けば$objが何のオブジェクトであってもよい。
しかし
$d=SampleClass::getData();
では、SampleClassに限定されちゃうから差し替えが不能。
(まぁ離れ業として、
call_user_func_array(array($classname,'getData'),$args);
としてclassnameを差し替えることができるというロジックも作れるが)
今回説明したいのは
2の「アクセス制限」についてです。
上記のとおり、PHPは「クラスのアクセス修飾子がない」ので、
クラスのpublic staticメソッドは、グローバル関数並の使われ方をされます。
singletonパターンも、グローバル変数と同じだろ!とかよく言われてしまう存在ですよね。
確かに、
class Sample{
private $instance;
public static function getInstance(){
if (!self::$instance) {
self::$instance=new Sample();
}
return self::$instance;
}
}
と書けば、このgetInstance()メソッドはグローバル関数と同じポジションとなり、
したがってこのインスタンスは誰でも取得できるグローバル変数になってしまいます。
これではインスタンス化しないでabstractにしても同じです。
しかし、インスタンス化することによって「アクセス制限」がかけられるのです。
以下を見てください。
class Sample{
private $instance;
public static function getInstance(){
$trace=debug_backtrace();
if ($trace[1]['class'] != 'SampleFactory') {
throw new Exception("can't access.");
}
if (!self::$instance) {
self::$instance=new Sample();
}
return self::$instance;
}
}
こうしてしまえば、SampleFactoryクラスからアクセスされたときのみ
インスタンスを返すことができるので、グローバルになりません。
abstractなクラスでもこれを実装できますが、
メソッドにアクセスごとに毎回debug_backtrace()が実行されてしまいます。
abstract class Sample{
private static function check(){
$trace=debug_backtrace();
if ($trace[2]['class'] != 'SampleFactory') {
throw new Exception("can't access.");
} else {
return true;
}
}
また上記のcheckメソッドを各メソッドの最初で呼び出さなければなりません。
これは大変面倒だしあほらしい。
だからインスタンスを生成する利点は、
1.差し替え
2.アクセス制限
ということがあるんだなーと思ってくれれば。。
PHPはバージョンが5になってから、オブジェクト指向型の言語に近づいてきました。
オブジェクト指向は保守性が高いことが最大の利点と言えると思います。
(個人的な意見ですが)
しかし、まだまだPHPは完璧なオブジェクト指向型言語とは言えません。
完璧でない点を挙げますと・・・
・クラスの外にコードが書ける(C++なんかもそうだが。)
・データ型のすべてがオブジェクトではない
・packageがない
・classにアクセス修飾子をつけられない
・nativeなオブジェクトが少ない
まぁ、上記の機能は言語の簡易性が失われてしまうので、
PHPの取り柄である「簡単さ」という点からいえば、必要ない機能なのかもしれません。
PHP5はカンタンなまま、適度にOOPできるというバランスの良さがいいですね。
さて、上記の「PHPにない機能」のうち、
「classにアクセス修飾子がつけられない」ということが多少響いてくるデザインパターンがあります。
それがsingletonパターンです。
singletonパターンは、インスタンスの数を制限できるパターンです。
インスタンスを複数持つこともできるので、いろいろと応用が効くのですが、
ここではインスタンスを1つしか保有しないsingletonパターンについて述べたいと思います。
では問題です。
staticなabstractクラスと、インスタンスを1つしか保有しないsingletonパターンは、
どう違うのでしょうか。(PHP5での話。)
abstract class Sample{
private $var;
public static function set($var){
self::$var=$var;
}
}
↑こんな感じにすればインスタンス化しなくたって、
充分一つのオブジェクトっぽく機能するんですよね。
オブジェクト化することで速度は落ちるっていうし、
いちいちメモリ使うんならクラス関数でやっちまったらいいのでは?
私は結構最近まで↑のようなことを思ってました。
インスタンス化しないのなら、「オブジェクト指向」ならぬ「クラス指向」じゃん。
正解は・・・
1.インスタンス化することで、オブジェクトの差し替えができる。
2.インスタンス化することで、アクセスの制限が可能となる。
1はまぁ誰もが考えるでしょう。
$d=$obj->getData();
と書けば$objが何のオブジェクトであってもよい。
しかし
$d=SampleClass::getData();
では、SampleClassに限定されちゃうから差し替えが不能。
(まぁ離れ業として、
call_user_func_array(array($classname,'getData'),$args);
としてclassnameを差し替えることができるというロジックも作れるが)
今回説明したいのは
2の「アクセス制限」についてです。
上記のとおり、PHPは「クラスのアクセス修飾子がない」ので、
クラスのpublic staticメソッドは、グローバル関数並の使われ方をされます。
singletonパターンも、グローバル変数と同じだろ!とかよく言われてしまう存在ですよね。
確かに、
class Sample{
private $instance;
public static function getInstance(){
if (!self::$instance) {
self::$instance=new Sample();
}
return self::$instance;
}
}
と書けば、このgetInstance()メソッドはグローバル関数と同じポジションとなり、
したがってこのインスタンスは誰でも取得できるグローバル変数になってしまいます。
これではインスタンス化しないでabstractにしても同じです。
しかし、インスタンス化することによって「アクセス制限」がかけられるのです。
以下を見てください。
class Sample{
private $instance;
public static function getInstance(){
$trace=debug_backtrace();
if ($trace[1]['class'] != 'SampleFactory') {
throw new Exception("can't access.");
}
if (!self::$instance) {
self::$instance=new Sample();
}
return self::$instance;
}
}
こうしてしまえば、SampleFactoryクラスからアクセスされたときのみ
インスタンスを返すことができるので、グローバルになりません。
abstractなクラスでもこれを実装できますが、
メソッドにアクセスごとに毎回debug_backtrace()が実行されてしまいます。
abstract class Sample{
private static function check(){
$trace=debug_backtrace();
if ($trace[2]['class'] != 'SampleFactory') {
throw new Exception("can't access.");
} else {
return true;
}
}
また上記のcheckメソッドを各メソッドの最初で呼び出さなければなりません。
これは大変面倒だしあほらしい。
だからインスタンスを生成する利点は、
1.差し替え
2.アクセス制限
ということがあるんだなーと思ってくれれば。。
勝ったー!
001000000
000000000
000000000
000001000
000010000
010000001
これは一昨日までの横浜ベイスターズの各回の得点。
二進数を彷彿させるという悲しさ。
そんな6連敗中のベイスターズが昨日ついに勝った。
010332000
ようやく二進数っぽくなくなったね!
000000000
000000000
000001000
000010000
010000001
これは一昨日までの横浜ベイスターズの各回の得点。
二進数を彷彿させるという悲しさ。
そんな6連敗中のベイスターズが昨日ついに勝った。
010332000
ようやく二進数っぽくなくなったね!
空いた時間が
臨床実習始まると微妙に早く終わったりして空いた時間ができるんだが、
その時間を有効活用できた試しがない。
「悪銭身につかず」に近いね。
今日も午後からなんだけど午前中テキトーに過ごしそうだなー。
その時間を有効活用できた試しがない。
「悪銭身につかず」に近いね。
今日も午後からなんだけど午前中テキトーに過ごしそうだなー。
パターン認識
顔の表情がどんなものか見たりとか、
MRIの三次元画像から筋肉を抜き出して色をつけたりとか。
このような技術はすべて「パターン認識」という手法を用いている。
せっかくプログラミングを学んだんだから、
今後はそれを活かしてパターン認識を学んでいきたいなと思ったりしてる。
これからの時代パターン認識だーー!!
100%のルールを強いるのではなく、自然なルールをコンピュータで90%解釈するという感じ。
MRIの三次元画像から筋肉を抜き出して色をつけたりとか。
このような技術はすべて「パターン認識」という手法を用いている。
せっかくプログラミングを学んだんだから、
今後はそれを活かしてパターン認識を学んでいきたいなと思ったりしてる。
これからの時代パターン認識だーー!!
100%のルールを強いるのではなく、自然なルールをコンピュータで90%解釈するという感じ。
OPV
おっぱいバレーと言いたくない人は、OPVと言えばいいらしいよ。
以下秀逸な書きこみをコピペしてきた。
58 :名無シネマさん :2009/03/09(月) 18:00:15 ID:i3wZNaU6
俺「パイオツレーバー1枚!」
販売員「パイレーツオブカリビアンは今上映しておりません」
俺「パイオツバーレー1枚!」
販売員「すみません。パイレーツオブカリビアンは上映しておりません」
俺「オッパイバーレー1枚!」
販売員「ああ、おっぱいバレーですね。どうぞ」
以下秀逸な書きこみをコピペしてきた。
58 :名無シネマさん :2009/03/09(月) 18:00:15 ID:i3wZNaU6
俺「パイオツレーバー1枚!」
販売員「パイレーツオブカリビアンは今上映しておりません」
俺「パイオツバーレー1枚!」
販売員「すみません。パイレーツオブカリビアンは上映しておりません」
俺「オッパイバーレー1枚!」
販売員「ああ、おっぱいバレーですね。どうぞ」
ビーフカツ
トンカツは食べるがビーフカツにはあまりなじみがない、という方は多いと思う。
ビーフカツはあまりお目にかかるメニューでもないし、
メニューにあってもなかなか注文しない。
用いる分厚い牛肉は、衣をつけなくたって十分商品として機能する。
逆に衣をつけることで本来の味が分かりにくくなり、
結果として「トンカツとあまり変わらない味で値段は割増」という事態を引き起こす。
買う側の心理としては「あんまり味が変わらないんなら値段的にトンカツだよね」となる。
売る側も、「ビーフはそのまま使ったほうが本来の味出るじゃん」と考える。
このように、ビーフカツは買う側にも売る側にも嫌われて、不遇な日々を過ごしているのだ。

だがビーフカツとは違い、肉が赤くても怖くないのがいい。
中身が見えないというカツの弱点を見事に克服している。
いまこそビーフカツよ、その取り柄を武器に立ち上がる時だ。
名前を「ビーフステーキカツ」にするといいかもしれない。
「揚げ加減はいかがいたしましょうか?」
「ミディアムレアで」
もちろんナイフとフォークでいただく。
どうだろうか、このセレブ感。
このブログを見ているビーフカツ屋さんは即刻このアイデアを取り入れるべきだ。
※人形町にある「そときち」というお店がテレビで紹介されていたので書いてみた。
※たぶんビーフカツ屋さんはこのブログを見ていない。
ビーフカツはあまりお目にかかるメニューでもないし、
メニューにあってもなかなか注文しない。
用いる分厚い牛肉は、衣をつけなくたって十分商品として機能する。
逆に衣をつけることで本来の味が分かりにくくなり、
結果として「トンカツとあまり変わらない味で値段は割増」という事態を引き起こす。
買う側の心理としては「あんまり味が変わらないんなら値段的にトンカツだよね」となる。
売る側も、「ビーフはそのまま使ったほうが本来の味出るじゃん」と考える。
このように、ビーフカツは買う側にも売る側にも嫌われて、不遇な日々を過ごしているのだ。
だがビーフカツとは違い、肉が赤くても怖くないのがいい。
中身が見えないというカツの弱点を見事に克服している。
いまこそビーフカツよ、その取り柄を武器に立ち上がる時だ。
名前を「ビーフステーキカツ」にするといいかもしれない。
「揚げ加減はいかがいたしましょうか?」
「ミディアムレアで」
もちろんナイフとフォークでいただく。
どうだろうか、このセレブ感。
このブログを見ているビーフカツ屋さんは即刻このアイデアを取り入れるべきだ。
※人形町にある「そときち」というお店がテレビで紹介されていたので書いてみた。
※たぶんビーフカツ屋さんはこのブログを見ていない。
キム兄逮捕!?
「キム兄逮捕」の新聞報道!その真相は?
映画「ニセ札」で長編監督に挑戦した木村祐一。4月11日の公開が近づくなか、衝撃的な情報が飛び込んでき..........≪続きを読む≫ だってさwww
エイプリルフールって過ぎたんじゃないのか?
(今回はいつにも増して手抜きブログだが、逆にこっちのほうが評判が良かったりするから困る。)
映画「ニセ札」で長編監督に挑戦した木村祐一。4月11日の公開が近づくなか、衝撃的な情報が飛び込んでき..........≪続きを読む≫ だってさwww
エイプリルフールって過ぎたんじゃないのか?
(今回はいつにも増して手抜きブログだが、逆にこっちのほうが評判が良かったりするから困る。)
太郎かぶり
自分のフレームワークの定数には前々からイライラしていた。
ROOTPATH とか PLUGIN_DIR とかいう名前になってる。
こういう名前だと、他のプログラムと組み合わせたときに
名前が衝突してしまう可能性があるわけだ。
要は、「太郎!来い!」と叫べば、
一つの家族では意図した太郎が来るが、
他の家族と暮らした場合、太郎が別にいたらどうすんだ?って話。
やっぱ苗字をつけなあかんだろー。
ってことでかたっぱしから接頭辞をつけまくった。
「EZP_太郎」という名前にしたよ。
全然実質的には変わらない作業なんだがね。まだ相当量残ってるよ…。
やってはいるけど実際「他のプログラムと組み合わせる」なんてことはめったになくね?
(しかも有名なプログラムならちゃんと接頭辞つけてるし)
原動力は、「他人が自分のフレームワークを使ってくれる」という妄想だし。
つーわけで今日の作業は完全な自己満レベルのCO2排出作業なのでした。
ROOTPATH とか PLUGIN_DIR とかいう名前になってる。
こういう名前だと、他のプログラムと組み合わせたときに
名前が衝突してしまう可能性があるわけだ。
要は、「太郎!来い!」と叫べば、
一つの家族では意図した太郎が来るが、
他の家族と暮らした場合、太郎が別にいたらどうすんだ?って話。
やっぱ苗字をつけなあかんだろー。
ってことでかたっぱしから接頭辞をつけまくった。
「EZP_太郎」という名前にしたよ。
全然実質的には変わらない作業なんだがね。まだ相当量残ってるよ…。
やってはいるけど実際「他のプログラムと組み合わせる」なんてことはめったになくね?
(しかも有名なプログラムならちゃんと接頭辞つけてるし)
原動力は、「他人が自分のフレームワークを使ってくれる」という妄想だし。
つーわけで今日の作業は完全な自己満レベルのCO2排出作業なのでした。
使えねー理論家
医療界においては理論家ほど使えない者はいない。
なぜなら医療は、そこに患者がいることで成り立つ世界だからだ。
今日は授業で薬物動態の話があったんだが…。はぁー。
理論家がウザいことやってくれたよ。
まぁ話を聞いてくれよ。
先生が
「一次反応で消え去る薬物において、その投与間隔を4/3倍にしたいので、
投与量は4/3倍にして対応した。」
と言ったので、それは違うだろと理論家がつっこみやがったんです。
ちなみに先生もそこはさらりと流して次に行きたいところだった感じなのに
無駄に食いついてたんです。
さらに言うと理論的にそれがちょっと違ったところで大勢には影響ないんです。
つまり現場的には、投与量を1250にするか1500にするかぐらいな話なのに、
いちいちそんな難しい理論とか考えても意味ないんです。
投与は脳内で起きてるんじゃない!現場で起きてるんだ!
さらにさらに言うと、その理論家とやらは自分なんです。あー凹んだ。
いや、自分というか、私の頭の中の理論家、だね。
さらにさらにさらに言うと、先生にも
「いや、理論的にもあってるんですが。」とか言われました。
まぁ最後に言わせてもらうとやっぱり理論的には合ってねぇ。
なぜなら医療は、そこに患者がいることで成り立つ世界だからだ。
今日は授業で薬物動態の話があったんだが…。はぁー。
理論家がウザいことやってくれたよ。
まぁ話を聞いてくれよ。
先生が
「一次反応で消え去る薬物において、その投与間隔を4/3倍にしたいので、
投与量は4/3倍にして対応した。」
と言ったので、それは違うだろと理論家がつっこみやがったんです。
ちなみに先生もそこはさらりと流して次に行きたいところだった感じなのに
無駄に食いついてたんです。
さらに言うと理論的にそれがちょっと違ったところで大勢には影響ないんです。
つまり現場的には、投与量を1250にするか1500にするかぐらいな話なのに、
いちいちそんな難しい理論とか考えても意味ないんです。
投与は脳内で起きてるんじゃない!現場で起きてるんだ!
さらにさらに言うと、その理論家とやらは自分なんです。あー凹んだ。
いや、自分というか、私の頭の中の理論家、だね。
さらにさらにさらに言うと、先生にも
「いや、理論的にもあってるんですが。」とか言われました。
まぁ最後に言わせてもらうとやっぱり理論的には合ってねぇ。