现在假设有一个晚会,规定了节目样式和节目顺序。下面写一段简单的代码:
代码语言:javascript复制@Testpublic void demo1(){ System.out.println("晚会现在开始"); //周杰伦唱歌 new Jielun().sing(); //刘谦表演魔术 new Liuqian().magic(); //迈克尔杰克逊跳舞 new Michael().dance(); System.out.println("晚会结束");}
这是用Java代码模拟的一场晚会,顺序就是唱歌、表演魔术、跳舞。
突然,周杰伦不能来了,这个时候就要改一个歌手。怎么改呢,就直接改就好了。
代码语言:javascript复制//new Jielun().sing();//周杰伦不能来了,由陈奕迅来给大家演唱new Eason().sing();
换来换去都还是歌手。这个时候我们就可以抽象出一个接口Singer
代码语言:javascript复制/*** 歌手的接口,每个歌手都应实现这个接口*/interface Singer(){ void sing();}
其它的也可以抽出接口
代码语言:javascript复制/*** 魔术师的接口*/interface Magician{ void magic();}
/*** 跳舞的人的接口(不知道叫啥)*/interface Dancer{ void dance();}
然后相应职业的人就实现相应的接口,然后代码就可以这样写:
代码语言:javascript复制@Testpublic void demo1(){ System.out.println("晚会开始"); //省略了代码 Singer singer = new Jielun(); singer.sing();
}
这个时候,如果有歌手档期冲突,来不了了。就需要直接在demo1()中修改,这个时候我们可以使用工场模式。主代码中我们不做修改,利用歌手工场
代码语言:javascript复制/*** 工场类*/public class Factory(){ /** * 获取歌手 */ public Singer getSinger(){ return new Jielun(); }
//后面两个也一样写}
这个时候,主代码中就可以改成:
代码语言:javascript复制@Testpublic void demo1(){ System.out.println("晚会开始了");
//这个时候,修改歌手时,不需要动主程序 Singer singer = Factory.getSinger(); singer.sing(); }
这个时候虽然不需要改主程序,但是工程类还是需要经常修改。这个时候我们可以利用配置文件part.properties(名字可以随便取,必须要.properties结尾):
代码语言:javascript复制Singer=com.zack.JielunDancer=com.zack.MichaelMagician=com.zack.Liuqian
这里的键和接口名一致,值的话就是具体实现类的包全名。
代码语言:javascript复制/*** 工程类中的获取歌手的方法*/public static Singer getSinger(){ //读取配置文件,party是配置文件名,不需要加后缀。Singer就是配置文件中的键 String className = ResourceBundle.getBundle("party").getString("Singer");
//利用包全名获取对象 try{ //调用className类的构造方法 Object obj = Class.forName(className).newInstance(); return (Singer)obj; }catch(Exception e){ e.printStackTrace(); }}
这样我们修改歌手的时候就不需要修改任何代码,只需修改配置文件就够了。