1. 工厂模式的作用解决接口选择的问题2. 何时使用当我们明确地知道不同条件下创建不同实例时。3. 使用场景--java的可移植性java--JVM工厂--操作系统--hibernate和mybatis切换数据库4. 注意事项作为一种创建类模式在任何需要生成复杂对象的地方都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式而简单对象特别是只需要通过 new 就可以完成创建的对象无需使用工厂模式。分析一下程序package test; public class test { public static void main(String[] args) { Apple apple new Apple(); apple.eat(); //如果突然不想吃苹果想吃香蕉就要重新实例化一个香蕉对象 //如此一来每次切换都要更新客户端的代码 //能不能有一种方式用户想吃什么就传入什么不需要改动客户端的代码 } } class Apple{ public void eat() { System.out.println(吃苹果。。。); } } class Banana{ public void eat() { System.out.println(吃香蕉。。。); } }5. 改进引入工厂类package test; public class test { public static void main(String[] args) { Fruit fruit Factory.getInstance(args[0]); fruit.eat(); } } abstract class Fruit{ //模板类 public void eat(){} ; } class Apple extends Fruit{ public void eat() { System.out.println(吃苹果。。。); } } class Banana extends Fruit{ public void eat() { System.out.println(吃香蕉。。。); } } interface Factory{ //工厂类 public static Fruit getInstance(String fruit) { if(apple.equals(fruit)) { return new Apple(); }else if(banana.equals(fruit)) { return new Banana(); }else { return null; } } }如此一来只要是水果工厂里面有的水果用户只要输入水果名称就可以吃到该水果不需要自己再去生产该水果生产的工作交由水果工厂负责。但是这个代码还是有一个特别麻烦的地方那就是每当接口产生一个新的子类的时候接口本身也必须修改可扩展性极低。6. 利用反射改进工厂模式package test; public class TestFactory { public static void main(String[] args) throws Exception { Fruit instance Factory.getInstance(test.Apple); instance.eat(); } } interface Fruit{ public void eat(); } class Apple implements Fruit{ Override public void eat() { System.out.println(吃苹果...); } } class Banana implements Fruit{ Override public void eat() { System.out.println(吃香蕉....); } } class Factory{ public static Fruit getInstance(String fruitClass) throws Exception { return (Fruit)Class.forName(fruitClass).newInstance(); //一句代码搞定以后有新的子类也不需要再修改工厂类了 } }但是这样还是不够完美因为客户端需要明确知道子类的详细名称包.类名并且每次切换子类都要改动客户端改进的方法是利用配置文件将类名写进配置文件中切换的时候全部代码都不需要改动只要改动配置文件就可以了。7. 利用配置温文件管理工程类名import java.util.ResourceBundle; public class TestFactory { public static final ResourceBundle rb ResourceBundle.getBundle(fruit);//使用配置文件 public static void main(String[] args) throws Exception { Fruit instance Factory.getInstance(rb.getString(fruitClass)); instance.eat(); } } interface Fruit{ public void eat(); } class Apple implements Fruit{ Override public void eat() { System.out.println(吃苹果...); } } class Banana implements Fruit{ Override public void eat() { System.out.println(吃香蕉....); } } class Factory{ public static Fruit getInstance(String fruitClass) throws Exception { return (Fruit)Class.forName(fruitClass).newInstance(); //一句代码搞定以后有新的子类也不需要再修改工厂类了 } }上面的代码仍不完美不完美之处在于需要用户去手工修改配置文件。所以必须想一种办法把配置写回配置中又可以跟程序进行有效的分离。参考servlet开发的经验使用Annotation来实现配置。8. 利用annotation改进工厂模式package factory; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Factory(className factory.Apple) public class TestFactory3{ public static void main(String[] args) { Fruit fruit; try { fruit getFruit(); fruit.eat(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static Fruit getFruit() throws Exception { Class? cls TestFactory3.class; Factory an cls.getAnnotation(Factory.class);//取得工厂annotation return (Fruit)Class.forName(an.className()).newInstance(); //返回工厂实例 } } interface Fruit{ public void eat(); } class Apple implements Fruit{ Override public void eat() { System.out.println(吃苹果...); } } class Banana implements Fruit{ Override public void eat() { System.out.println(吃香蕉....); } } //写自己的annotation Retention(RetentionPolicy.RUNTIME) interface Factory{ public String className() ; }9. 继续优化简化客户端annotationpackage factory; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Factory(className Banana) public class TestFactory3{ public static void main(String[] args) { Fruit fruit; try { fruit getFruit(); fruit.eat(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static Fruit getFruit() throws Exception { Class? cls TestFactory3.class; Factory an cls.getAnnotation(Factory.class);//取得工厂annotation return (Fruit)Class.forName(Fruit.class.getPackage().getName().an.className()).newInstance(); //返回工厂实例 } } interface Fruit{ public void eat(); } class Apple implements Fruit{ Override public void eat() { System.out.println(吃苹果...); } } class Banana implements Fruit{ Override public void eat() { System.out.println(吃香蕉....); } } //写自己的annotation Retention(RetentionPolicy.RUNTIME) interface Factory{ public String className() ; }
Java设计模式--工厂模式
1. 工厂模式的作用解决接口选择的问题2. 何时使用当我们明确地知道不同条件下创建不同实例时。3. 使用场景--java的可移植性java--JVM工厂--操作系统--hibernate和mybatis切换数据库4. 注意事项作为一种创建类模式在任何需要生成复杂对象的地方都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式而简单对象特别是只需要通过 new 就可以完成创建的对象无需使用工厂模式。分析一下程序package test; public class test { public static void main(String[] args) { Apple apple new Apple(); apple.eat(); //如果突然不想吃苹果想吃香蕉就要重新实例化一个香蕉对象 //如此一来每次切换都要更新客户端的代码 //能不能有一种方式用户想吃什么就传入什么不需要改动客户端的代码 } } class Apple{ public void eat() { System.out.println(吃苹果。。。); } } class Banana{ public void eat() { System.out.println(吃香蕉。。。); } }5. 改进引入工厂类package test; public class test { public static void main(String[] args) { Fruit fruit Factory.getInstance(args[0]); fruit.eat(); } } abstract class Fruit{ //模板类 public void eat(){} ; } class Apple extends Fruit{ public void eat() { System.out.println(吃苹果。。。); } } class Banana extends Fruit{ public void eat() { System.out.println(吃香蕉。。。); } } interface Factory{ //工厂类 public static Fruit getInstance(String fruit) { if(apple.equals(fruit)) { return new Apple(); }else if(banana.equals(fruit)) { return new Banana(); }else { return null; } } }如此一来只要是水果工厂里面有的水果用户只要输入水果名称就可以吃到该水果不需要自己再去生产该水果生产的工作交由水果工厂负责。但是这个代码还是有一个特别麻烦的地方那就是每当接口产生一个新的子类的时候接口本身也必须修改可扩展性极低。6. 利用反射改进工厂模式package test; public class TestFactory { public static void main(String[] args) throws Exception { Fruit instance Factory.getInstance(test.Apple); instance.eat(); } } interface Fruit{ public void eat(); } class Apple implements Fruit{ Override public void eat() { System.out.println(吃苹果...); } } class Banana implements Fruit{ Override public void eat() { System.out.println(吃香蕉....); } } class Factory{ public static Fruit getInstance(String fruitClass) throws Exception { return (Fruit)Class.forName(fruitClass).newInstance(); //一句代码搞定以后有新的子类也不需要再修改工厂类了 } }但是这样还是不够完美因为客户端需要明确知道子类的详细名称包.类名并且每次切换子类都要改动客户端改进的方法是利用配置文件将类名写进配置文件中切换的时候全部代码都不需要改动只要改动配置文件就可以了。7. 利用配置温文件管理工程类名import java.util.ResourceBundle; public class TestFactory { public static final ResourceBundle rb ResourceBundle.getBundle(fruit);//使用配置文件 public static void main(String[] args) throws Exception { Fruit instance Factory.getInstance(rb.getString(fruitClass)); instance.eat(); } } interface Fruit{ public void eat(); } class Apple implements Fruit{ Override public void eat() { System.out.println(吃苹果...); } } class Banana implements Fruit{ Override public void eat() { System.out.println(吃香蕉....); } } class Factory{ public static Fruit getInstance(String fruitClass) throws Exception { return (Fruit)Class.forName(fruitClass).newInstance(); //一句代码搞定以后有新的子类也不需要再修改工厂类了 } }上面的代码仍不完美不完美之处在于需要用户去手工修改配置文件。所以必须想一种办法把配置写回配置中又可以跟程序进行有效的分离。参考servlet开发的经验使用Annotation来实现配置。8. 利用annotation改进工厂模式package factory; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Factory(className factory.Apple) public class TestFactory3{ public static void main(String[] args) { Fruit fruit; try { fruit getFruit(); fruit.eat(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static Fruit getFruit() throws Exception { Class? cls TestFactory3.class; Factory an cls.getAnnotation(Factory.class);//取得工厂annotation return (Fruit)Class.forName(an.className()).newInstance(); //返回工厂实例 } } interface Fruit{ public void eat(); } class Apple implements Fruit{ Override public void eat() { System.out.println(吃苹果...); } } class Banana implements Fruit{ Override public void eat() { System.out.println(吃香蕉....); } } //写自己的annotation Retention(RetentionPolicy.RUNTIME) interface Factory{ public String className() ; }9. 继续优化简化客户端annotationpackage factory; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Factory(className Banana) public class TestFactory3{ public static void main(String[] args) { Fruit fruit; try { fruit getFruit(); fruit.eat(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static Fruit getFruit() throws Exception { Class? cls TestFactory3.class; Factory an cls.getAnnotation(Factory.class);//取得工厂annotation return (Fruit)Class.forName(Fruit.class.getPackage().getName().an.className()).newInstance(); //返回工厂实例 } } interface Fruit{ public void eat(); } class Apple implements Fruit{ Override public void eat() { System.out.println(吃苹果...); } } class Banana implements Fruit{ Override public void eat() { System.out.println(吃香蕉....); } } //写自己的annotation Retention(RetentionPolicy.RUNTIME) interface Factory{ public String className() ; }