工厂设计模式--Factory

  模拟场景:女娲造人,第一次经验不足造出白人,第二次时间太紧,造出黑人,第三次才造出黄种人。

  Human接口: 

1 package com.zqz.dp.factorymethod;
2 /**
3  * @author Qin
4  * human接口,因为不同色种的human会有相同的动作,只是实现不同
5  */
6 public interface Human {
7          void getColor();        //得到肤色
8          void doSomething();         //一些其他动作
9 }

  创建不同肤色的human

  WhiteHuman类: 

 1 package com.zqz.dp.factorymethod;
 2 /**
 3  * @author Qin
 4  * 白人,肯定是human,所以从human接口继承
 5  */
 6 public class WhiteHuman implements Human {
 7          public void getColor() {
 8                    System.out.println("白人的肤色是白色的。。。");
 9          }
10          public void doSomething() {
11                    System.out.println("我是白人");
12         }
13 }

  BlackHuman类: 

 1 package com.zqz.dp.factorymethod;
 2 /**
 3  * @author Qin
 4  * 黑人,肯定是human,所以从human接口继承
 5  */
 6 public class BlackHuman implements Human {
 7          public void getColor() {
 8                   System.out.println("黑人的肤色是黑色的。。。");
 9          }
10          public void doSomething() {
11                   System.out.println("我是黑人");
12          }
13 }

  YellowHuman类: 

 1 package com.zqz.dp.factorymethod;
 2 /**
 3  * @author Qin
 4  * 黄种人,肯定是human,所以从human接口继承
 5  */
 6 public class YellowHuman implements Human {
 7          public void getColor() {
 8                    System.out.println("黄种人的肤色是黄色的。。。");
 9          }
10          public void doSomething() {
11                    System.out.println("我是黄种人");
12          }
13 } 

  AbstractHumanFactory接口: 

1 package com.zqz.dp.factorymethod;
2 /**
3  * @author Qin
4  * 生产human的工厂,可以进行human的生产
5  */
6 public interface AbstractHumanFactory {
7          abstract <T extends Human> T createHuman(Class<T> c);   //根据class类型创建出指定的human
8 }

  HumanFactory类: 

 1 package com.zqz.dp.factorymethod;
 2 /**
 3  * @author Qin human工厂的具体实现类,创建具体的human对象
 4  */
 5 public class HumanFactory implements AbstractHumanFactory {
 6 @SuppressWarnings("unchecked")
 7          public <T extends Human> T createHuman(Class<T> c) {
 8                    Human human = null; // 声明human对象,不管是什么肤色的human,肯定都是human的子类
 9                    try {
10                             //反射创建human对象,注意human中要有一个午餐的构造器
11                             human = (Human) Class.forName(c.getName()).newInstance();  
12                    } catch (Exception e) {
13                             e.printStackTrace();
14                    }
15                    return (T)human;     //返回human对象,泛型
16          }
17 }  

  NvWa 

 1 package com.zqz.dp.factorymethod;
 2 /**
 3  * @author Qin
 4  * 女娲类,要用humanFactory来生成human
 5  */
 6 public class NvWa {
 7          public static void main(String[] args) {
 8                    //创建一个human生成工厂
 9                    AbstractHumanFactory factory=new HumanFactory(); //父类实例指向子类对象
10                    System.out.println("第一次经验不足生成白人=======================:");
11                    Human whiteHuman=factory.createHuman(WhiteHuman.class);         //反射生成对象
12                    whiteHuman.getColor();
13                    whiteHuman.doSomething();
14                    System.out.println("第二次烤太久生成黑人=======================:");
15                    Human blackHuman=factory.createHuman(BlackHuman.class);  //反射生成对象
16                    blackHuman.getColor(); 
17                    blackHuman.doSomething();
18                    System.out.println("第三次终于生成黄种人=======================:");
19                    Human yellowHuman=factory.createHuman(YellowHuman.class);                 //反射生成对象
20                    yellowHuman.getColor();        
21                    yellowHuman.doSomething();} 

  这样就完成了human的创建

  工厂方法是指定义一个创建对象的接口,让子类决定实例化哪一个类。也就是说工厂方法将子类的实例化延迟到了子类。

工厂方法的优点:

  1、  良好的封装性,代码结构清晰;有约束,规定xxxHuman要继承Human类。

  2、  可拓展性高;如上面的例子如果要再创建一个其他肤色的Otherhuman,只需要让Otherhuamn类继承Huamn类即可,工厂类不需要进行修改。

  3、  屏蔽产品类;也就是说在生成Human的时候,不需要知道Human的任何属性或者方法,只知道我要创建一个Human即可。即我可以不管Human类怎么实现,我只关心如果创建一个Human。

  4、  解耦性强。

工厂方法的使用场景

  1、  工厂方法模式是new一个对象实例化的一个替代品,所以在所有需要生成对象的地方都可以使用。但是在使用的时候要考虑清楚是否真的需要,会否添加代码的复杂度。

  2、  需要灵活的,可拓展的框架时可以考虑

  3、  异构项目中

  4、  测试驱动开发的框架下

工厂方法的拓展

  1、  缩小为简单工厂

  在上面的场景中,只需要一个工厂的存在即可,那么就可以把创建human实例的createHuman()方法定义成static的,那么就可以不需要abstractHumanFactory的存在了。

修改的代码如下:

  HumanFactory 

 1 package com.zqz.dp.staticfactory;
 2 /**
 3  * @author Qin human工厂的具体实现类,创建具体的human对象
 4  */
 5 public class HumanFactory{
 6          @SuppressWarnings("unchecked")
 7          public static <T extends Human> T createHuman(Class<T> c) {
 8                    Human human = null; // 声明human对象,不管是什么肤色的human,肯定都是human的子类
 9                    try {
10                             //反射创建human对象,注意human中要有一个午餐的构造器
11                             human = (Human) Class.forName(c.getName()).newInstance();  
12                    } catch (Exception e) {
13                             e.printStackTrace();
14                    }
15                    return (T)human;     //返回human对象,泛型
16          }
17 }

  NvWa 

 1 package com.zqz.dp.staticfactory;
 2 /**
 3  * @author Qin
 4  * 女娲类,要用humanFactory来生成human
 5  */
 6 public class NvWa {
 7          public static void main(String[] args) {
 8                    //创建一个human生成工厂
 9                    System.out.println("第一次经验不足生成白人=======================:");
10                    Human whiteHuman=HumanFactory.createHuman(WhiteHuman.class);         
11 //反射生成对象
12                    whiteHuman.getColor();
13                    whiteHuman.doSomething();
14                    System.out.println("第二次烤太久生成黑人=======================:");
15                    Human blackHuman=HumanFactory.createHuman(BlackHuman.class);             //反射生成对象
16                    blackHuman.getColor(); 
17                    blackHuman.doSomething();
18                    System.out.println("第三次终于生成黄种人=======================:");
19                    Human yellowHuman=HumanFactory.createHuman(YellowHuman.class);           //反射生成对象
20                    yellowHuman.getColor();        
21                    yellowHuman.doSomething(); }
22 } 

2、  升级为多个工厂

  在上面的操作中,是否会觉得humanFactory兼顾的任务太多了呢?因为要创建白种人、黑种人和黄种人三种不同肤色的human。可能你会觉得说不会啊,这样刚好啊。但是可能在项目中,如果只用一个humanFactory(这里只是举例而已),那么要创建好几百中不同肤色的human,那这个时候你是否还会觉得说很乱呢?

所以在这里,可以升级为多个工厂,在这个场景中就是要有三个Factory,来生成不同的Human。

修改代码如下:

  AbstractHumanFactory 

1 package com.zqz.dp.manyfactory;
2 /**
3  * @author Qin
4  * 生产human的工厂,可以进行human的生产
5  */
6 public interface AbstractHumanFactory {
7          abstract Human createHuman();    //生成human的工厂,具体生成什么肤色的交给具体的factory
8 }

  WhiteFactory 

 1 package com.zqz.dp.manyfactory;
 2 /**
 3  * @author Qin
 4  * 创建白种人的factory
 5  */
 6 public class WhiteFactory implements AbstractHumanFactory {
 7          public Human createHuman() {
 8                    return new WhiteHuman();     //返回白种人实例
 9          }
10 } 

  BlackFactory 

 1 package com.zqz.dp.manyfactory;
 2 /**
 3  * @author Qin
 4  * 创建黑种人的factory
 5  */
 6 public class BlackFactory implements AbstractHumanFactory {
 7          public Human createHuman() {
 8                    return new BlackHuman();      //返回黑种人实例
 9          }
10

  YellowFactory 

 1 package com.zqz.dp.manyfactory;
 2 /**
 3  * @author Qin
 4  * 创建黄种人的factory
 5  */
 6 public class YellowFactory implements AbstractHumanFactory {
 7          public Human createHuman() {
 8                    return new YellowHuman();    //返回黄种人实例
 9          }
10 } 

  NvWa 

 1 package com.zqz.dp.manyfactory;
 2 /**
 3  * @author Qin
 4  * 女娲类,要用humanFactory来生成human
 5  */
 6 public class NvWa {
 7          public static void main(String[] args) {
 8                    //创建一个human生成工厂
 9                    System.out.println("第一次经验不足生成白人=======================:");
10                    Human whiteHuman=(new WhiteFactory()).createHuman();                  //指定的工厂生成指定的实例
11                    whiteHuman.getColor();
12                    whiteHuman.doSomething();
13                    System.out.println("第二次烤太久生成黑人=======================:");
14                    Human blackHuman=(new BlackFactory()).createHuman();           //指定的工厂生成指定的实例
15                    blackHuman.getColor(); 
16                    blackHuman.doSomething();
17                    System.out.println("第三次终于生成黄种人=======================:");
18                    Human yellowHuman=(new YellowFactory()).createHuman();                //指定的工厂生成指定的实例
19                    yellowHuman.getColor();        
20                    yellowHuman.doSomething();
21          }
22

  在这里是反而麻烦了,只是简单举个实例而已

3、  替代单例模式

  Singleton类: 

1 package com.zqz.dp.singletonfactory;
2 /**
3  * @author Qin
4  * 单例类
5  */
6 public class Singleton {
7          private Singleton(){};                  //构造方法私有化
8          public void doSomething(){};    //自己的操作
9 } 

  SingletonFactory 

 1 package com.zqz.dp.singletonfactory;
 2 import java.lang.reflect.Constructor;
 3 /**
 4  * @author Qin
 5  * 生成单例的factory
 6  */
 7 public class SingletonFactory {
 8          private static Singleton singleton=null;
 9          static {      //静态代码块进行加载
10                    try {
11                             Class<?> c1=Class.forName(Singleton.class.getName()); //反射取得对象
12                             Constructor<?> con=c1.getDeclaredConstructor();               //取得singleton的构造器
13                             con.setAccessible(true); //因为singleton构造器被私有化,在这里设置为可访问
14                             singleton=(Singleton) con.newInstance();       //反射取得对象
15                    } catch (Exception e) {
16                             e.printStackTrace();
17                    }       
18          }
19          public static Singleton getSingleton(){
20                   return singleton;      //返回实例
21          }
22 }
原文地址:https://www.cnblogs.com/littleQin/p/3675702.html