之前对简单工厂模式一笔带过。今天我们来探究,如何优化简单工厂模式。
先来回顾一下代码
public abstract class Caffee {
public abstract void GetCoffeMsg();//获取咖啡信息
}
public class CafeeLatte extends Caffee{
@Override
public void GetCoffeMsg() {
System.out.println("这是拿铁咖啡");
}
}
public class CaffeeAmeric extends Caffee {
@Override
public void GetCoffeMsg() {
System.out.println("这是美式咖啡");
}
}
public class CaffeFactory {
public static Caffee getCaffee(String name){
Caffee caffee=null;
if("美式".equals(name)){
caffee=new CaffeeAmeric();
}else if("拿铁".equals(name)){
caffee=new CafeeLatte();
}else{
System.out.println("抱歉,没有这种咖啡 Exception");
return null;
}
return caffee;
}
}
public class CaffeeStore {
/**
* 模拟咖啡店对咖啡的包装
* @param caffee
*/
public void addSugar(Caffee caffee){
System.out.println("咖啡店正在给咖啡加糖");
}
/**
* 点咖啡
* @param name 咖啡种类,这里用字符串代替
*/
public void OrderCaffee(String name){
Caffee caffee=CaffeFactory.getCaffee(name);
this.addSugar(caffee);
caffee.GetCoffeMsg();
}
//测试代码
public static void main(String[] args) {
CaffeeStore caffeeStore=new CaffeeStore();
caffeeStore.OrderCaffee("美式");
caffeeStore.OrderCaffee("拿铁");
}
}
如果我们要加入一种咖啡:卡布奇诺,那么就需要修改工厂类的if分支,很明显不符合开闭原则,所以我们要想办法解决这个问题。其实可以利用反射,我们把需要加的类写在配置文件里,比如美式咖啡我们可以配置成:美式=com.CaffeeAmeric,然后通过反射进行实例化,添加新品种,只需要修改配置文件,不需要动代码,话不多说,直接上代码来解释说明
首先我创建了一个配置文件NeedCaffee,对应咖啡名和加载类名,各位要注意中文编码哦
美式=com.CaffeeAmeric
拿铁=com.CafeeLatte
配置文件一般由静态代码块加载,我们需要一张表来映射关系,以下代码概况起来就一句话,读取配置文件,映射到hashMap
static {
Properties propertiesIni=new Properties();
InputStream ini=CaffeFactory.class.getClassLoader().getResourceAsStream("NeedCaffee");
BufferedReader bf=null;
try {
bf = new BufferedReader(new InputStreamReader(ini, "UTF-8"));
propertiesIni.load(bf);
Set keySet=propertiesIni.keySet();
Iterator iterator=keySet.iterator();
while(iterator.hasNext()){
String key=(String)iterator.next();
CaffeeMap.put(key,propertiesIni.getProperty(key));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
bf.close();
ini.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
映射完毕后,我们就能通过咖啡名获取到类路径,进而反射,创建对象
public static Caffee getCaffee(String name){
Caffee caffee=null;
try {
Class caffeeClass=Class.forName(CaffeeMap.get(name));
caffee=(Caffee)caffeeClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return caffee;
}
成功解决,学到了很多,不亲自动手试试,还没发现中文编码这个bug,果然,一些小细节不能丢,还有反射,语法忘了好多