工厂模式之工厂方法模式

来源:互联网 发布:cf号怎么解封软件 编辑:程序博客网 时间:2024/06/05 02:27

工厂模式:

 概念:
    1、实例化对象,用工厂方法代替new操作
    2、工厂模式包括工厂方法模式和抽象工厂模式
    3、抽象工厂模式是工厂方法模式的扩展

 意图:
    定义一个接口来创建对象,但是让子类来决定哪些类需要被实例化
    工厂方法把实例化的工作推迟到子类中去实现

 场景:
    1、有一组类似的对象需要创建
    2、在编码时不能预见需要创建哪种类的实例
    3、系统需要考虑扩展性,不应依赖于产品类实例如何被创建、
          组合和表达的细节(低耦合,这个对象的变化尽量不影响到别的对象发生变化)

 设计:
    1、尽量松耦合,一个对象的依赖对象的变化与本身无关
    2、具体产品与客户端剥离,责任分割

抽象工厂模式:系列、家族

     生产一个产品:工厂    
     生产多个产品:抽象工厂  

以脸萌为例:(正常实现)

1> HairInterface.java

package com.zy.factoryProject;public interface HairInterface {// 生成发型public void draw();}

2> leftHair.java

package com.zy.factoryProject;public class leftHair implements HairInterface {/** * 画一个左偏分发型 */@Overridepublic void draw() {System.out.println("---左偏分发型---");}}

3> rightHair.java

package com.zy.factoryProject;public class rightHair implements HairInterface {/** * 画一个右偏分发型 */@Overridepublic void draw() {System.out.println("---右偏分发型---");}}

4> Test.java

package com.zy.factoryProject;public class Test {/** * 模拟客户端 * @param args */public static void main(String[] args) {HairInterface left = new leftHair();left.draw();}}

*上述做法明显有缺陷,就是每次要创建一个新的发型都要建立新的xxxhair.java,并且都要在客户端显式的调用

为了解决上述问题:

1> 创建发型工厂,用于根据客户端需求创建发型:(HairFactory.java)

package com.zy.factoryProject;/** * 发型工厂 *  * @author Administrator *  */public class HairFactory {/** * 根据类型来创建对象 *  * @param key * @return */public HairInterface getHair(String key) {// 这里把key放在equals里面,因为进来没对key进行是否为空的判断,这样可以避免抛空指针// 如果关键字是左偏分,则产生一个左偏分发型if ("left".equals(key)) {return new leftHair();} else if ("right".equals(key)) {return new rightHair();}return null;}}

2> 客户端根据需求调用工厂进行发型的创建:(Test.java)

package com.zy.factoryProject;public class Test {/** * 模拟客户端 *  * @param args */public static void main(String[] args) {HairFactory factory = new HairFactory();HairInterface left = factory.getHair("left");left.draw();}}

*但是反观上述HaorFactory工厂,每当要产生一个新发型都要if else判断,不能智能的创建

为了解决上述问题,应用类的反射,进行智能创建

1>在HairFactory.java中添加方法:

/** * 根据类名来产生对象 *  * @param className * @return */public HairInterface getHairByClass(String className) {try {HairInterface hair = (HairInterface)Class.forName(className).newInstance();return hair;} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return null;}

2> 在客户端调用:

HairFactory factory = new HairFactory();HairInterface left = factory.getHairByClass("com.zy.factoryProject.leftHair");left.draw();

*上述这样实现的好处:增加一个发型时,只要增加这个发型的类,并告知客户端存在这个发型的类,通过工厂进行调用即可

*但是这样在客户端调用也不方便,类名太长(com.zy.factoryProject.leftHair),需要做映射


1>创建type.properties文件进行映射信息的配置

left=com.zy.factoryProject.leftHairright=com.zy.factoryProject.rightHair

2>创建PropertiesReader对properties文件进行读取

package com.zy.factoryProject;import java.io.IOException;import java.io.InputStream;import java.util.Enumeration;import java.util.HashMap;import java.util.Map;import java.util.Properties;/** * properties文件读取工具 *  * @author Administrator *  */public class PropertiesReader {public Map<String, String> getProperties() {// 这里Properties对象导的包是java.util.PropertiesProperties props = new Properties();Map<String, String> map = new HashMap<String, String>();try {InputStream in = getClass().getResourceAsStream("type.properties");props.load(in);Enumeration en = props.propertyNames();while (en.hasMoreElements()) {// 按行读取,以等号为分割String key = (String) en.nextElement();String property = props.getProperty(key);map.put(key, property);}} catch (Exception e) {e.printStackTrace();}return map;}}

3>HairFactory增加根据配置文件创建发型的方法:

/** * 根据配置文件来产生对象 *  * @param className * @return */public HairInterface getHairByKey(String key) {try {// 类名从配置文件中读取Map<String, String> map = new PropertiesReader().getProperties();HairInterface hair = (HairInterface)Class.forName(map.get(key)).newInstance();return hair;} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return null;}

4>进行测试:

HairFactory factory = new HairFactory();HairInterface hair = factory.getHairByKey("right");hair.draw();

*通过上述设置,这时,如果需要加入新的发型,则:

1>创建对应新发型的类:(inHair.java中分发型)

package com.zy.factoryProject;public class inHair implements HairInterface {@Overridepublic void draw() {System.out.println("---中分发型---");}}

2>在配置文件中添加对应的映射:

in=com.zy.factoryProject.inHair

3>告知客户端实现中分发型:

HairInterface hair = factory.getHairByKey("in");hair.draw();

*如此一来,只需要新增对象时,只需要增加对象的实现方法和在配置文件中写好映射,并且告知客户端映射的key值即可,不需要改变factory


0 0
原创粉丝点击