アイマスでデザインパターン Adapter
実装クラス一覧
IdolMaster
MillionLive - すでに実装がされているミリオンライブクラス
CinderellaGirls - すでに実装がされているシンデレラガールズクラス
今回はミリオンとシンデレラ両者がすでに実装されているが、アイドルマスターとしてともに扱いたい。
しかし、既存のクラスを変更はできないといった状態。
そのため、間にクラスを挟んで実装を行う
以下がそのクラス
IdolMasterMillionLive - ミリオンライブをアイドルマスターとして扱うためのAdapter
IdolMasterCinderellaGirls - シンデレラガールズをアイドルマスターとして扱うためのAdapter
各クラス
IdolMaster
public interface IdolMaster { // あいさつするだけ public abstract void aisatu(); }
MillionLive
public class MillionLive { // キャラ名 private String name; // 中の人 private String cv; // ミリオンライブ public MillionLive(String name, String cv) { this.name = name; this.cv = cv; } // 挨拶 みりっほー public void mirihho() { System.out.println("ミリオンライブ" + this.name + "役の" + this.cv + "です。"); } }
CinderellaGirls
public class CinderellaGirls { // キャラ名 private String name; // 中の人 private String cv; // ミリオンライブ public CinderellaGirls(String name, String cv) { this.name = name; this.cv = cv; } // 挨拶 でれっす public void mirihho() { System.out.println("シンデレラガールズ" + this.name + "役の" + this.cv + "です。"); } }
IdolMasterMillionLive
public class IdolMasterMillionLive extends MillionLive implements IdolMaster{ // super()を使用して名前とCVをセット public IdolMasterMillionLive(String name, String cv) { super(name, cv); } // あいさつ @Override public void aisatu() { // 親クラスのメソッドをそのまま使用する mirihho(); } }
IdolMasterMillionLive
public class IdolMasterCinderellaGirls extends CinderellaGirls implements IdolMaster{ // super()を使用して名前とCVをセット public IdolMasterCinderellaGirls(String name, String cv) { super(name, cv); } // あいさつ @Override public void aisatu() { // 親クラスのメソッドをそのまま使用する deressu(); } }
動作確認
public static void main() { IdolMaster million = new IdolMasterMillionLive("箱崎星梨花", "麻倉もも"); million.aisatu(); IdolMaster cinderella = new IdolMasterCinderellaGirls("島村卯月", "大橋彩香"); cinderella.aisatu(); }
実行結果
ミリオンライブ箱崎星梨花役の麻倉ももです。 シンデレラガールズ島村卯月役の大橋彩香です。
IdolMaserインタフェースを実装したので、これでアイドルマスターとしてミリオンとデレマスがアイドルマスターとしてともに扱うことが可能になる。
親クラスを継承したことによって、元のメソッドの挙動も変えずに済んでいる。
2017/11 30日間チャレンジ -デザインパターン-
アイマスでデザインパターン Iterator
実装クラス一覧
Aggregate
Iterator
Office - 事務所
OfficeIterator - 事務所のアイドルをスキャン
Idol - オフィスに所属するアイドル
各クラス
Iterator
public intrface Iterator { // 次のアイドルが存在すればTrue public boolean hasNext(); // 次のアイドルを指し示す public Object next(); }
Aggregate
public interface Aggregate { public Iterator iterator(); }
Idol
public class Idol { // 名前 private String name; // 年齢 private int age; // コンストラクタ public Idol(String name, int age){ this.name = name; this.age = age; } // 自己紹介 public String selfIntroduction(){ return name + "," + age + "歳です。"; } }
Office
publc class Office implements Aggregate { // 事務所に所属しているアイドル private Idol[] idols; // 配列用インデックス private int index = 0; // コンストラクタ public Office(int number){ this.idols = new Idol[number]; } // Indexからアイドルを取得 public Idol getIdol(int index){ return idols[index]; } // アイドルを事務所に迎える public void enteringCompany(Idol idol){ this.idols[index] = idol; index++; } public int getLength(){ return index; } // Iteratorの生成 // thisでOfficeインスタンスを渡す @Override public Iterator iterator() { return new OfficeIterator(this); } }
OfficeIterator
public class OfficeIterator implements Iterator { // 事務所 private Office office; // インデックス private int index; // コンストラクタ public OfficeIterator(Office office) { this.office = office; this.index = 0; } // 事務所の所属アイドルがまだ存在していればTrue @Override public boolean hasNext() { if (index < office.getLength()) return true; return false; } // アイドルの情報を取得している大元 @Override public Object next() { Idol idol = office.getIdol(index); index++; return idol; } }
動作確認
public static void startIterator() { // 事務所作るよー Office 765Office = new Office(5); // アイドルスカウト 765Office.enteringCompany(new Idol("七尾百合子", 15)); 765Office.enteringCompany(new Idol("高坂海美", 16)); 765Office.enteringCompany(new Idol("佐竹美奈子", 18)); 765Office.enteringCompany(new Idol("周防桃子", 11)); 765Office.enteringCompany(new Idol("田中琴葉", 18)); // Iteratorインスタンスを作成して、アイドルを順番に呼び出す iterator iterator = office.iterator(); while(iterator.haxNext()){ Idol idol = (Idol)iterator.next(); // 自己紹介をする System.out.println(idol.selfIntroduction()); } }
実行結果
七尾百合子,15歳です。 高坂海美,16歳です。 佐竹美奈子,18歳です。 周防桃子,11歳です。 田中琴葉,18歳です。
765で作るならASメンバーで作ればよかったなと作り終わってから後悔
動き的にはアイドルがいれば引っ張ってきて、いなければ処理終了なだけ
あまり意識してないけど拡張forの内部とかでIterator使われているらしい
Amazon Web Service 学習メモ①
DjangoでAWS環境で作るための学習
AmazonWebServices 基礎からのネットワーク&サーバー構築の本を読んだので、学んだことをまとめ
システム構築について
インフラ知識を身に着けるメリット
- 障害に対応できる
- 堅牢なシステムを作成するためのコードを意識できる
Webサーバーなら『Apache』や『nginx』
※ApacheはSpring等で組み込まれていたため知っていたがnginxは知らなかった
Djangoのデプロイ環境用に使用している人がいるみたいでqiita等で記事がいくつかあがってます
- データベースサーバーなら『MySQL』など
※メールサーバーの存在自体を初めて知った
DjangoでミリオンライブキャラクターDB一応終了
今回作成物
GitHub - lilly-seventail/milliondb: 簡易ミリオンDB
終わり?
終わりです。
後は徐々に修正とアイドル達を増やしていきます。
Herokuあたりにでもデプロイはしようかとは思っています。
Model周りと個別ページの表示の仕方は修正します。
その他は気が向いたらです。
作成してみた感想
ほぼほぼDjangGirlsでやった内容で作れたんじゃないかなと
filterでの検索やImageFieldの扱いは調べながらになりましたがうまくいきました。
モデル1つと画面2つとだいぶ小規模になりましたが
自分の手で作るのはアウトプットとしてはやはり最適ですね。
今後も作りたいものがあれば作っていきます。
次やること
Django周りでいえばログイン処理だったりカスタムユーザーの作成なんかを勉強しておきたいです。
後は今回できなかったREST Frameworkを使ったものを作りたいですね。
今回勉強したことはそれなりにフルで使えた感じはするので、
しばらくまたインプットをしつつ、思いついたら何かを作っていきます。
DjangoでミリオンライブキャラクターDBを作成 ~検索処理作成~
検索処理の説明
検索用のフォーム
from django import forms from .models import Idol class IdolForm(forms.Form): name = forms.CharField(label="名前") //1
今回の検索フォームは名前での検索だけなので名前用のフィールドを作ってあげています。
ChoiceFieldとか使うと選択とかもできたり色々検索処理も色々と弄るのも楽しそう
検索用のView
def index(request): if request.method == 'GET': form = IdolForm() idols = Idol.objects.all() elif request.method == 'POST': form = IdolForm(request.POST) //1 name = request.POST['name'] //2 idols = Idol.objects.all().filter(name__contains=name) //3 return render(request, 'mysite/index.html', {'idols' : idols, 'form' : form } )
1.検索用のフォームです。
ここでformにわざわざ指定しているのは、POST時の値を検索処理後に格納するためです。
IdolFormをGETとPOSTまとめて記述しておくと初期化されてしまいます。
2. request.POST['フィールド名']で該当のフィールドの値が取得できます。
名前に入れられた値をここに格納しておきます。
3.filter(name__contains=name)はフィルター機能を使っています
初めに検索処理を行うフィールド名のnameを指定して__(アンダーバー二個)をつけて
フィルターとして実行する処理を書いていきます。
今回は入力された名前に部分一致しているものを抽出したいのでcontainsを使用しています。
nameは漢字だけの検索になるので読み仮名でも検索したいとなった場合は
from django.db.models import Q
filter(Q(name__contains=name) | Q(yomigana__contains=name))
でいけます。
こちらのサイト様が参考になります。
thinkami.hatenablog.com
DjangoでミリオンライブキャラクターDBを作成 ~メインページ初期表示の作成~
メインページのViewの説明
def index(request): idols = Idol.objects.all() //1 return render(request, 'mysite/index.html', {'idols' : idols} )
1. 現状は初期表示に全件取得するだけを記述
この後検索処理用にPOSTメソッドと分ける必要があります。
メインページのテンプレートの説明
{% extends 'mysite/base.html' %} {% block style %} <style> .img-over{ <!-- 1 --> transition: 0.3s; } .img-over:hover{ transform: scale(2.2); } </style> {% endblock style %} {% block content %} <form> <!-- 2 --> <label>名前:</label> <input type="text" name="name" /> <button type="submit">検索</button> </form> <div class="col-md-12"> {% for idol in idols %} <div class="col-md-1"> <a href="{% url 'mysite:detail' pk=idol.pk %}"><img src="{{ idol.image.url }}" class="img-responsive img-circle img-over"/></a> <!-- 3 --> </div> {% endfor %} </div> {% endblock content %}
1.画像の背景が白なのでマウスオーバーしたときにわかりにくすぎたのでCSSでマウスオーバー用に書いています。
マウスオーバーしたときに画像が拡大されて表示されるようになっています。
2.今回は初期表示だけなので検索はべた書きしています。
実際は検索処理用にDjangoのforms.pyを利用していくことになると思います。
3.今回urlを渡すのに mysite:detailを利用しています。
最初のmysiteは
プロジェクトの方のurls.pyのnamespaceで指定したものです。
最初この指定してある値を間違えてて無駄に時間を取ってしまいました。
urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^', include('mysite.urls', namespace='mysite')), ]
こうして書いておくことでどのアプリケーションのどのViewを渡しているのかわかりやすくなっていいですね。
次やること
検索フォームの実装に入ります。