kyosho5’s blog

貧乏で数学があまり得意ではない理系出身のエンジニアのブログ

デザインパターン勉強メモ③

※投稿し忘れていた分も続けて投稿します。とりあえず1日2章ペースは維持。

第5章 Singletonパターン

指定したクラスのインスタンスが絶対に1つしか存在しないことを保証する
また、そのことをプログラム上で表現する
staticなフィールドを用意し、Singletonクラスのロード時に1度だけ初期化している。
コンストラクタをprivateにすることで、クラス外からのnew Singleton()を禁止している
→以上より、Singletonクラスのインスタンスは1つしか存在しないことになる。

・Singleton役
→唯一のインスタンスを得るためのstaticメソッドを持っている。いつも同じインスタンスを返す。

プログラムの実行開始後、最初にgetInstance(インスタンスを取得する)メソッドが実行された際に
Singletonクラスが初期化される。→staticフィールドの初期化が行われ、唯一のインスタンスが生成される。

第6章 Prototypeパターン

new Something()というクラス名を指定したインスタンス作成ではなく、インスタンスを複製して新しいインスタンスを作る。
以下のような場合に用いる。

・扱うオブジェクトの種類が多すぎて1つ1つをクラスに分けて書くとソースが増えすぎてしまう場合
インスタンス生成に必要な過程が多い場合など、クラスからのインスタンス生成が難しい場合
(1度作ったインスタンスをいったん保管しておき、必要な時にそれをコピーする)
インスタンスを生成するときのフレームワークを特定のクラスに依存させたくないとき
(クラス名を指定してインスタンスを生成するのではなく、ひな型となるインスタンスを保管しておき、必要な時にコピーする)

・Prototypeの役
インスタンスをコピーして新しいインスタンスを作るメソッドを定める。

・ConcretePrototypeの役
インスタンスをコピーして新しいインスタンスを作るメソッドを実際に実装する。

・Clientの役
インスタンスをコピーするメソッドを利用して、新しいインスタンスを作る。

インスタンスをコピーするメソッドとして、Java言語にはcloneメソッドがある。
使用する場合にはjava.lang.Cloneableインタフェースを実装する必要がある。
cloneメソッドはjava.lang.Objectクラスで定義されている

デザインパターン勉強メモ②

第3章 Template Methodパターン

スーパークラスにテンプレートとなるメソッドを定義し、その中で抽象メソッドを使った処理を実装する。
スーパークラスでは抽象メソッドの呼び出しによって処理の流れだけを記述し、具体的な処理内容はサブクラスにて実装する。

・Abstractクラス
→テンプレートメソッドを実装する。その中では使用する抽象メソッドを宣言する。
抽象メソッドの実装はConcreteクラス(サブクラス)で行われる。

・Concreteクラス
→抽象メソッドを具体的に実装する。Abstractクラスのテンプレートメソッドより呼び出される。

ロジックの共通化ができる。
サブクラスの実装を行うときは、スーパークラス内でどのような処理の流れになっているかを理解する必要がある。
スーパークラス型の変数にサブクラス型のインスタンスを代入する方式にする時に
instancofなどでサブクラスの種類を特定せずにプログラムが動くようにする方針が良い。
スーパークラス型の変数にサブクラスのインスタンスのどれを代入しても正しく動作するようにするという原則を
リスコフの置換原則(LSP:The Liskov Substitution Principle)という。←継承の一般原則

スーパークラスとサブクラスの実装密度のトレードオフを意識する。
スーパークラスは骨組み、サブクラスは肉付けという意識。
正解はないので設計時によく考えること。

スーパークラスは、サブクラスに対して抽象メソッドの実装を期待している
→サブクラスの責任(Subclass Responsibilities)

第4章 Factoryパターン

Template Methodパターンをインスタンス生成の場面に適用したもの。
インスタンスの作り方をスーパークラスで定めるが、具体的な肉付けは
すべてサブクラス側で行う。

・Product役
フレームワーク側。このパターンで生成されるインスタンスが持つべきインタフェース(API)を定める抽象クラス。
具体的な内容はサブクラスのConcreteProduct役が定める。

Creator
フレームワーク側。Product役を生成する抽象クラス。
具体的な内容はサブクラスのConcreteCreator役が定める。
Creator役が知っているのはProduct役とインスタンス生成のメソッドを呼び出せばProductが生成されるということのみ。
newによる実際のインスタンス生成をインスタンス生成のためのメソッド呼び出しに変えることで
具体的なクラス名による束縛からスーパークラスを解放している。

・ConcrteProduct役
→具体的な肉付けを行うクラス。製品を定める。

・ConcreteCreator役
→具体的な肉付けを行うクラス。製品を作るクラスを定める。

スーパークラス(抽象的な骨組み・フレームワーク)側にあるCreator役とProduct役の関係が、
サブクラス(具体的な肉付けの側にあるConcreteCreator役とConcreteProduct役の関係と並行している。

サンプルソースでは、frameworkパッケージの中ではidcardパッケージをインポートしていない
→ProductクラスやFactoryクラスの中では具体的なクラス名が書かれていない
→新しいクラスを同じフレームワークで生成する場合もframeworkパッケージを変更する必要がない
「frameworkパッケージはidcardパッケージに依存していない」


デザインパターンを使ってクラス群を設計する場合、そのクラス群を保守する人に
設計者の意図が何であるのかがうまく伝わるようにする必要がある(意図せぬ修正をされないように)
コメントやドキュメントの中で実際に使われているデザインパターンの名称や意図を記述しておくのがよい。

クラスやインタフェースの相互関係に目を向けること。

ここまでの感想

4章あたりからは具体的なコードだけを頼りにするのではなく、より抽象的に各クラスやインタフェースの関係をイメージできるようにする必要があると感じた。
若干、腑に落ちる前に頭の中を通過していってしまっている感があるので、明日もう一度5~10分程度時間をとって読み返してみることにする。

デザインパターン勉強メモ①

各パターン整理の前に・・・

・一般に言う「インタフェース」
→そのクラスが持っているメソッドの集まりを指す。そのクラスに対して何らかの処理を行う場合は中にあるメソッドを通じて行う。
Javaで言う「インタフェース」
→interfaceを使って宣言されるもの

UML(Unifiied Modeling Language)
→システムを視覚化したり、仕様や設計を文書化したりするための表現技法
アトリビュート(属性)や、オペレーション(操作)といった概念を持つ(Javaで言うところのフィールドとメソッド)


抽象クラス。抽象メソッド
staticクラス、staticメソッド

シーケンス図(Sequence Diagram)
→プログラムが動くときにどのメソッドがどの順番に実行されるか、どのような事象がどういう順番で起こるかを表現したもの
(時間に従って変化するもの→動的な振る舞い)

※クラス図は時間によって変化しないもの→静的な関係

第1章 Iteratorパターン

for (int i = 0; i < arr.lelngth(); i++) {
    System.out.println(arr[i]);
}

の時の変数iの働きを抽象化し、一般化したもの。

・Aggregateインタフェース
→数え上げを行うものの集合体を表す。
このインタフェースを実装するクラスは、配列やVectorなどの集合体を表す。
このインタフェースではiterator()のみを書く(集合体に対応するIteratorを1つ作成するためのもの)

Iteratorインタフェース
→要素の数え上げを行うもの、ループ変数の役割を示すもの。
もっとも単純なタイプでは
public abstract boolean hasNext(); // 次の要素があるかを示す
public abstract Object next(); //次の要素を返す

・Bookクラス
→コンストラクタでは引数で本の名前を指定する
本の名前を返すgetName()を実装する

・BookShelfクラス implements Aggregate
→本棚を表現するクラス。集合体を表現するためAggregateクラスを実装する
Bookの配列を持っている。iteratorメソッドではBookShelfクラスに対応するIteratorとして
BookShelfIteratorクラスのインスタンスを作成して返す。
本棚の本を数え上げたいときにiteratorメソッドを呼び出す。

・BookShelfIteratorクラス implements Iterator
Iteratorインタフェースを実装する。
hasNext()は次の本があるか否かでbooleanを返す。
next()は今注目している本の次の要素を指す。

iteratorの戻り値をObject型にしておけば、配列でなくVectorなどに変更されても対応できるようになる
→再利用可能な部品となる

第2章 Adapterパターン

既存のクラスなどを用いて新しいクラスなどを実装するときに
返還の役割を果たす。

・Target
→今必要となっているメソッドを定めている役。
インタフェース(継承の場合)やクラス(委譲の場合)などがこれに当てはまる。

・Client
→Targetのメソッドを実際に使う役。サンプルではMainクラスが相当。

・Adaptee
→適合される側。すでに用意されているメソッドを持っている役。

・Adapter
→変換アダプタの役を務める。
クラスによるAdapterパターンの場合はAdapter役は継承を使ってAdaptee役を利用する。
インスタンスによるAdaptenパターンの場合は委譲を使ってAdaptee役を利用する。

ここまでの感想

2週目ということと、やはり実務で曲がりなりにも経験を積んできている分すんなり理解できる部分もかなり多いと思う。
あと、このパターンにピッタリは当てはまらないけども、似たような実装をしている部分もあるのではないかと思う。
より具体的な知識として落とし込み、自由に使いこなせるようになりたい。

最近の反省

かなりのご無沙汰です。



しばらく記事を書かない間に現場常駐をしたりC#に触れてみたりAndroid開発に入ったりいろんなことがありました



で、最近は勉強用読書として「アジャイルソフトウェア開発の奥義」という本を読んでおりました



読んでみた感想として




割とマジで何言ってるのか理解できない




あと1か月ほどすると、エンジニアになってから1年になりますが




うーん デザインパターンとかの理解がゴミ過ぎる




↑の本は今週末までに読む計画でおりましたが、あまりにも根っこの理解がお粗末なので今日で打ち切って、




明日からは再度デザインパターンの本で基礎から学びなおすことにします。




数えてみたら23章あるから、2週間くらいを目安に1日2章ずつくらい読み進める感じで




で、読んで理解した内容をここでアウトプットとして記録していこうかと思っています



ソースの写経とかも考えたけど、デザパタのソース自体はそれほど複雑でもない(半年前はこれを読むのもしんどかった)ので、



概要理解→ソース読んで確認→記事に自分の言葉で認める、みたいな感じで進めていこうかな



以上、決意表明でした。

ジムを最大限に使う

今日という休日、日中はなんとなくダラダラと過ごしてしまった



夕方になり、いかんいかんとジムに行き、汗を流し、シャワーを浴びて帰宅。




なんていうか、自分の中にあるダメなものがいろいろ出ていった気がする。物質的にも気分的にも。



筋トレは最強のソリューションである。



この一言を最近の専らのポリシーとして生きているが、今までの人生で言われたどんな説教よりも心に響いた気がする。

(上記を提言している方のtwitterや書籍もあります)



自分の体形に変化が見えてくると、ものすごい達成感で満たされる。



運動そのものの健康への良さ、ダイエットなどの引き締め効果、そしてメンタルの浄化。しかもカネはかからない。



体を動かす、鍛えるというのには、人々が思う以上の効果があるんですね



1日20回のスクワットからでも。  人生、一緒に変えようぜ。



あ、あけましておめでとうございます。



今年はもっと技術的な記事が書けるように、精進します。

「他人の人生を生きるな」

スティーブ・ジョブズはそのように言っていました。




2005年、スタンフォード大学の卒業式で語っていたことです。




初めて原文で読んだ当時は、どうしても最後の "Stay Hungry, Stay Foolish."というフレーズが強烈に印象に残ったのですが、




「無駄に他人の人生を生きないでください」という説教が今になってジワジワきている。もちろん面白おかしいという意味ではなく、「あぁ、大事なことだよな」と。











で、話は変わるんだけど、さっきこんな記事を読んでいた。

www.dokodeneru.com




巨乳女性ならではの悩みということで およそ男には想像・理解するのが難しいことなんだろうけど




それでも最後の締めくくりは、まさジョブズが語っていたことと変わりはしていないワケで。




誰にでも言えることなんだなと。




「自分の人生を生きろ」ということは。

三項演算子を使うという選択

javaのおはなし。



ついこの前、javaのプログラミング問題を解いてる時に調べ物をしていたら、




三項演算子というのが便利だ、という記事を見かけた。




簡単な例として、

「もしint型のnumが0だったらtrueを返し、それ以外だったらfalseを返す」という処理を書くとする。




javaを学び始めた初期の私なら、真っ先に

	public boolean sampleMethod(int num) {
		if(num % 2 == 0) {
			return true;
		} else {
			return false;
		}
	}


今でも一番最初に思いつくのはこれだったりする。



しかし、少し勉強を進めていくとswitch文の書き方も選択肢として出てくる。
(最後のbreakは冗長ではあるが、現在参画しているとあるプロジェクトではコーデイング規約の中にbreakの記述が必須となっていた。
なんで無駄に行を増やすのか…)



	public boolean sampleMethod(int num) {
		switch(num) {
		case 0:
			return true;
			break;
		default:
			return false;
			break;
		}
	}


で、三項演算子だとこんな感じ。

	public boolean sampleMethod(int num) {
		return num == 0 ? true : false;
	}

なんと実際の処理は1行で書けてしまう。




意味としては、

return 条件 ? 条件が真のときの戻り値 : 条件が偽のときの戻り値;

である。



あまり複雑なコードの中にこれをガリガリ書いていくと可読性が落ちるという指摘もあるようだが、基本的には



全体のコード行数を減らしてスッキリさせるのに一役買ってくれそう。



ただし、あくまで戻り値は2パターンまでしか表現できないのでパターン数次第ではifかswitchを用いた方がいい場合もある。



ifもswitchも三項演算子も、それぞれのいい部分と悪い部分があるので場合に応じて使い分けられるようにしておきたい。