Java - Simple Factory Pattern & Abstract Factory Pattern

讀了大話設計模式這本書,發現簡單工廠模式對於撰寫一主功能下各獨立子功能的應用上是

易於擴充的寫法,但是仍避免不了的是在工廠部分還是會有過多的判斷式,因此在這邊練習

撰寫例子同時也吸收了他提到的抽象工廠模式進一步修正這過多判斷式的問題,但同時也有

使用到進階的Enum部分!

PS.設計模式相關說明定義的部分可以直接去參考這本書囉!

簡單工廠模式

抽象運動員
package simplefactory;
public abstract class Athlete {
 public abstract String getSkill();
}

運動員(一)
package simplefactory;
public class BandmintonAthlete extends Athlete{
 @Override
 public String getSkill() {
  // TODO Auto-generated method stub
  return "扣殺!!";
 }
}

運動員(二)
package simplefactory;
public class BaseballAthlete extends Athlete{
 @Override
 public String getSkill() {
  // TODO Auto-generated method stub
  return "轟出全壘打!!";
 }
}

運動員(三)
package simplefactory;
public class SoccerAthlete extends Athlete{
 @Override
 public String getSkill() {
  // TODO Auto-generated method stub
  return "後空翻!!";
 }
}

運動員(四)
package simplefactory;
public class VolleyballAthlete extends Athlete{
 @Override
 public String getSkill() {
  // TODO Auto-generated method stub
  return "跳殺!!";
 }
}

指導教練 => 工廠
package simplefactory;
public class SchoolCoach {
 public static Athlete teachSkill(int select){
  Athlete athlete = null;
  switch(select)
  {
   case 1:{
    System.out.println("羽球員");
    athlete = new BandmintonAthlete();
    break;
   }
   case 2:{
    System.out.println("棒球員");
    athlete = new BaseballAthlete();
    break;
   }
   case 3:{
    System.out.println("足球員");
    athlete = new SoccerAthlete();
    break;
   }
   case 4:{
    System.out.println("排球員");
    athlete = new VolleyballAthlete();
    break;
   }
  }
  return athlete;
 }
}

工廠會產生相關運動員的實體,根據您所要學習的運動員的項目來決定之

學生 => 主體
public class Students {
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  System.out.println("Hi~ 同學, 您有想過成為哪種運動員? "+
                        "(1)Bandminton(2)Baseball(3)Soccer(4)Volleyball");
  Scanner input = new Scanner(System.in);
  int select = input.nextInt();
  Athlete athlete = SchoolCoach.teachSkill(select);
  System.out.println("因為可以學會...."+athlete.getSkill());
  input.close();
 }
}

執行過程


導入抽象工廠模式 & Enum

改寫如下

增加 => AthleteType

目的:從選擇的項目之中,可以取得相關AthleteType的實體,藉此取得相關該實體下的屬性

,如sport => 帶出名稱;className => 帶出類別名稱
public enum AthleteType {
 Bandminton("羽球員", "BandmintonAthlete"),
 Baseball("棒球員", "BaseballAthlete"),
 Soccer("足球員", "SoccerAthlete"),
 Volleyball("排球員", "VolleyballAthlete");
 
 private String className;
 private String sport;
 
 private AthleteType(String sport, String className){
  this.sport = sport;
  this.className = className;
 }
 
 public String getSport() {
  return sport;
 }

 public String getClassName() {
  return className;
 }
}

新教練 => 工廠

public class SchoolNewCoach {
 private static String PKG = "simplefactory";
 
 public static Athlete teachSkill(AthleteType select){
  Athlete athlete = null;
  try {
   System.out.println(select.getSport());
   Class clazz = Class.forName(PKG+"."+select.getClassName());
   Object obj = clazz.newInstance();
   athlete = (Athlete)obj;
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return athlete;
 }
}

新的教練部分在新增運動員時,也不用再做任何修改與判斷式,由反射與Enum的屬性來得到

相關Athlete的實體做回傳

Students Class部分只需改寫
//Athlete athlete = SchoolCoach.teachSkill(select);
Athlete athlete = SchoolNewCoach.teachSkill(AthleteType.values()[select-1]);

首先,如何取到Enum的實體呢?

在AthleteType內定義的項目順序,會依序在AthleteType.values()回傳的陣列內取得之

從0開始依序編下去,Enum的詳細說明請參考良葛格。因此AthleteType.values()[0]表式的

就是AthleteType.Bandminton,以此類推。

留言