前提
- 引数によって異なるサブクラスのインスタンスを返したい
- もしくはその他の方法で下記要件を満たしたい
- より良いクラス設計を学びたい
該当のソースコード
- 下記のようなXMLを入力とします。
- XMLのスキーマはname, detailまでは共通ですが、detailより下の階層はnameの中身によって変わります。
- 実際に実現したいプログラムで使用するXMLのスキーマはもっと複雑ですが例として簡単にしています。
- XML例1
xml
1<sports> 2 <name> 3 baseball 4 </name> 5 <detail> 6 <items> 7 <item> 8 ball 9 </item> 10 <item> 11 bat 12 </item> 13 <item> 14 glove 15 </item> 16 </items> 17 <swing> 18 double play.... 19 </swing> 20 </detail> 21</sports>
- XML例2
xml
1<sports> 2 <name> 3 soccer 4 </name> 5 <detail> 6 <positions> 7 <position> 8 offence 9 </position> 10 <position> 11 diffence 12 </position> 13 <position> 14 midfielder 15 </position> 16 </positions> 17 <shoot> 18 goal!!! 19 </shoot> 20 </detail> 21</sports>
- 各XMLの共通部分をスーパークラスとして定義しています。
- 各XML独自の部分をサブクラスとして定義しています。
- XML文字列を解析するXMLUtilクラスは省略しています。
- Sportクラス
java
1public class Sport { 2 protected String name; 3 public Sport(String xml) { 4 // baseball / soccer 5 name = XmlUtil.get(xml, "name"); 6 } 7 public String getName() { 8 return name; 9 } 10} 11
- Baseballクラス
java
1public class Baseball extends Sport { 2 private List<String> itemList; 3 private String swingResult; 4 public Baseball(String xml) { 5 super(xml); 6 7 // [ball, bat, glove] 8 itemList = XmlUtil.getList(xml, "items"); 9 // "double play..." 10 swingResult = XMlUtil.get(xml, "swing"); 11 } 12 public List<String >getItemList() { 13 return itemList; 14 } 15 public void swing() { 16 System.out.println(swingResult); 17 } 18}
- Soccerクラス
java
1public class Soccer extends Sport { 2 private List<String> positionList; 3 private String shootResult; 4 public Soccer(String xml) { 5 super(xml); 6 7 // [offence, diffence, midfielder] 8 positionList = XmlUtil.getList(xml, "positions"); 9 // "goal!!!" 10 shootResult = XMlUtil.get(xml, "shoot"); 11 } 12 public List<String >getPositionList() { 13 return positionList; 14 } 15 public void shoot() { 16 System.out.println(shootResult); 17 } 18}
- 呼び出し元クラスではXMLの中身に応じたサブクラスのインスタンスを生成し、それぞれ独自のメソッドを呼び出したいです。
- このクラスではXmlUtilクラスのメソッドは呼び出したくないです。
- 下記方法だと、
new Sport(xml);
とnew Baseball(xml);
で二回スーパークラスのコンストラクタが呼び出されていると思います。そのため、とても冗長に感じています。
- 呼び出し元クラス
java
1public void playSport(String xml) { 2 3 Sport sport = new Sport(xml); 4 5 if("baseball".equals(sport.getName())) { 6 Baseball baseball = new Baseball (xml); 7 baseball.swing(); 8 } else if ("soccer".equals(sport.getName())) { 9 Soccer soccer = new Soccer(xml); 10 soccer.shoot(); 11 } 12 13}
実現したいこと
- 以下のようなイメージで一度でサブクラスを作成し処理を行うことはできないでしょうか?
- このクラスではXML文字列の中身を解析したくはないです。
java
1public void newPlaySport(String xml) { 2 3 Sport sport = new Sport(xml); 4 5 if(sport instanceof Baseball) { 6 Baseball baseball = (Baseball)sport; 7 baseball.swing(); 8 } else if (sport instanceof Soccer) { 9 Soccer soccer = (Soccer)sport; 10 soccer.shoot(); 11 } 12 13}
ジェネリクスや抽象クラス等を組み合わせてやるとよいのか、あるいはファクトリクラスのようなものを定義するのがよいのか、いろいろ考えてみたのですが難しいです。
なにか、もっとこうした方がよい、私ならこうする、というようなアドバイスいただけると幸いです。
XMLのスキーマの設計等は変更はできません。
よろしくお願いいたします。
補足情報(FW/ツールのバージョンなど)
Java 1.8
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/08/29 08:37
2019/08/29 08:41
2019/08/29 09:01 編集