zoukankan      html  css  js  c++  java
  • 工厂设计模式--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 }
  • 相关阅读:
    eclipse——插件报错:Could not find node.js
    常用css设置
    前端跨域常见的处理方法
    刷新建设批次为空的sql
    PostgreSQL 添加字段语句
    查询在A表有记录数据,B表没有记录数据的SQL
    postgreSql 备份复制表结构和数据 SQL语句
    删除site_planning_id 和version 重复的,如果有多个版本,留下版本号最高的
    leetcode 精选top面试题
    leetcode 精选top面试题
  • 原文地址:https://www.cnblogs.com/littleQin/p/3675702.html
Copyright © 2011-2022 走看看