Java设计模式(03--工厂模式)
工厂模式概念:
实例化对象用工厂代替new操作。
工厂模式分为工厂方法模式和抽象工厂模式,抽象工厂模式是工厂方法模式的拓展。
工厂模式的意图:
定义一个接口来创建对象,但是让子类决定哪些类需要被实例化。
工厂方法让实例化的工作推迟到子类中去实现。
什么情况下适合工厂模式?
·有一组类似的对象需要创建。
·在编码时不能预见需要创建哪些类的实例。
·系统考虑拓展性,不应该依赖产品类实例如何被创建、组合和表达的细节。
项目中的现状
在软件系统中经常面临“对象”的创建工作,由于需求的变化,这个对象可能也随之发生变化,但是它
却拥有比较稳定的接口。
为此我们需要提供一种封装机制来隔离这个易变化的对象的变化,让系统中其他依赖该对象的对象不因
需求的变化而变化。(也就是做到低耦合)
基于现状将代码设计如下:
1.尽量松耦合,一个对象的依赖对象的变化与本身无关。
2.具体产品与客户端分离,责任分割。
工厂方法模式类图
抽象工厂模式类图
抽象工厂模式类比图
1)先来看看实现工厂方法模式的例子
发型接口,然后有左偏分子类,中分子类,右偏分子类,然后我们需要一个工厂类产生具体类的实例,客户端通过向工厂类传入需要创建类的类名就可以得到具体实现类的实例。
发型接口 HairInterface.java
1 package com.sunny.project; 2 /** 3 * 发型接口 4 * @author Administrator 5 * 6 */ 7 public interface HairInterface { 8 9 /** 10 * 画图 11 */ 12 public void draw(); 13 }
左偏分子类 LeftHair .java
1 package com.sunny.project; 2 /** 3 * 左偏分发型 4 * @author Administrator 5 * 6 */ 7 public class LeftHair implements HairInterface { 8 9 @Override 10 public void draw() { 11 // TODO Auto-generated method stub 12 System.out.println("-----------------左偏分发型-------------------"); 13 } 14 15 }
中分子类 InHair.java
1 package com.sunny.project; 2 /** 3 * 中分发型 4 * @author Administrator 5 * 6 */ 7 public class InHair implements HairInterface { 8 9 @Override 10 public void draw() { 11 // TODO Auto-generated method stub 12 System.out.println("-----------------中分发型-------------------"); 13 14 } 15 16 }
右偏分子类 RightHair.java
1 package com.sunny.project; 2 /** 3 * 右偏分发型 4 * @author Administrator 5 * 6 */ 7 public class RightHair implements HairInterface { 8 9 @Override 10 public void draw() { 11 // TODO Auto-generated method stub 12 System.out.println("-----------------右偏分发型-------------------"); 13 } 14 15 }
工厂类 HairFactory.java
1 package com.sunny.project; 2 3 import java.util.Map; 4 5 /** 6 * 发型工厂 7 * @author Administrator 8 * 9 */ 10 public class HairFactory { 11 12 /** 13 * 根据类型来创建对象 14 * @param key 15 * @return 16 */ 17 public HairInterface getHair(String key){ 18 if("left".equals(key)){ 19 return new LeftHair(); 20 }else if("right".equals(key)){ 21 return new RightHair(); 22 } 23 return null; 24 } 25 /** 26 * 根据类的名称来生产对象 27 * @param className 28 * @return 29 */ 30 public HairInterface getHairByClass(String className){ 31 32 try { 33 HairInterface hair = (HairInterface) Class.forName(className).newInstance(); 34 return hair; 35 } catch (InstantiationException e) { 36 // TODO Auto-generated catch block 37 e.printStackTrace(); 38 } catch (IllegalAccessException e) { 39 // TODO Auto-generated catch block 40 e.printStackTrace(); 41 } catch (ClassNotFoundException e) { 42 // TODO Auto-generated catch block 43 e.printStackTrace(); 44 } 45 return null; 46 } 47 48 49 /** 50 * 根据类的名称来生产对象 51 * @param className 52 * @return 53 */ 54 public HairInterface getHairByClassKey(String key){ 55 56 try { 57 Map<String, String> map = new PropertiesReader().getProperties(); 58 59 HairInterface hair = (HairInterface) Class.forName(map.get(key)).newInstance(); 60 return hair; 61 } catch (InstantiationException e) { 62 // TODO Auto-generated catch block 63 e.printStackTrace(); 64 } catch (IllegalAccessException e) { 65 // TODO Auto-generated catch block 66 e.printStackTrace(); 67 } catch (ClassNotFoundException e) { 68 // TODO Auto-generated catch block 69 e.printStackTrace(); 70 } 71 return null; 72 } 73 }
Key值和类名映射的properties文件 type.properties
1 left=com.sunny.project.LeftHair 2 right=com.sunny.project.RightHair 3 in=com.sunny.project.InHair
读取properties文件的工具类 PropertiesReader.java
1 package com.sunny.project; 2 3 import java.io.InputStream; 4 import java.util.Enumeration; 5 import java.util.HashMap; 6 import java.util.Map; 7 import java.util.Properties; 8 9 /** 10 * properties文件的读取工具 11 * @author Administrator 12 * 13 */ 14 public class PropertiesReader { 15 16 17 public Map<String, String> getProperties() { 18 19 Properties props = new Properties(); 20 Map<String, String> map = new HashMap<String, String>(); 21 try { 22 23 InputStream in = getClass().getResourceAsStream("type.properties"); 24 props.load(in); 25 Enumeration en = props.propertyNames(); 26 while (en.hasMoreElements()) { 27 String key = (String) en.nextElement(); 28 String property = props.getProperty(key); 29 map.put(key, property); 30 // System.out.println(key + " " + property); 31 } 32 } catch (Exception e) { 33 e.printStackTrace(); 34 } 35 return map; 36 } 37 }
客户端 用于测试工厂方法和抽象工厂方法的类 SunnyTest.java
1 package com.sunny.project; 2 3 public class SunnyTest { 4 5 public static void main(String[] args){ 6 7 // HairInterface left = new LeftHair(); 8 // left.draw(); 9 10 HairFactory factory = new HairFactory(); 11 // HairInterface right = factory.getHair("right"); 12 // right.draw(); 13 14 // HairInterface left = factory.getHairByClass("com.sunny.project.LeftHair"); 15 // left.draw(); 16 17 // HairInterface hair = factory.getHairByClassKey("in"); 18 // hair.draw(); 19 20 // PersonFactory facoty = new MCFctory(); 21 // Girl girl = facoty.getGirl(); 22 // girl.drawWomen(); 23 24 PersonFactory facoty = new HNFactory(); 25 Boy boy = facoty.getBoy(); 26 boy.drawMan(); 27 } 28 }
2)抽象工厂模式实例 本实例场景男孩Boy接口有两个实现类,分别是新年男孩实现类和圣诞男孩实现类,女孩Gril接口类有两个实现类,分别是新年女孩实现类和圣诞女孩实现类,有一个获取男孩和女孩的
工厂接口有两个实现类,分别是新年男孩,新年女孩的工厂实现类和获取圣诞男孩,圣诞女孩的工厂实现类。
男孩Boy接口 Boy.java
1 package com.sunny.project; 2 /** 3 * 男孩 4 * @author Administrator 5 * 6 */ 7 public interface Boy { 8 9 10 public void drawMan(); 11 }
新年男孩实现类 HNBoy.java
1 package com.sunny.project; 2 /** 3 * 新年系列的男孩子 4 * @author Administrator 5 * 6 */ 7 public class HNBoy implements Boy { 8 9 @Override 10 public void drawMan() { 11 // TODO Auto-generated method stub 12 System.out.println("-----------------新年系列的男孩子--------------------"); 13 } 14 15 }
圣诞男孩实现类 MCBoy.java
1 package com.sunny.project; 2 /** 3 * 圣诞系列的男孩子 4 * @author Administrator 5 * 6 */ 7 public class MCBoy implements Boy { 8 9 @Override 10 public void drawMan() { 11 // TODO Auto-generated method stub 12 System.out.println("-----------------圣诞系列的男孩子--------------------"); 13 } 14 15 }
女孩Gril接口类 Girl.java
1 package com.sunny.project; 2 /** 3 * 女孩子 4 * @author Administrator 5 * 6 */ 7 public interface Girl { 8 9 public void drawWomen(); 10 }
新年女孩实现类 HNGirl.java
1 package com.sunny.project; 2 /** 3 * 新年系列的女孩子 4 * @author Administrator 5 * 6 */ 7 public class HNGirl implements Girl { 8 9 @Override 10 public void drawWomen() { 11 // TODO Auto-generated method stub 12 System.out.println("-----------------新年系列的女孩子--------------------"); 13 } 14 15 }
圣诞女孩实现类 MCGirl.java
1 package com.sunny.project; 2 /** 3 * 圣诞系列的女孩 4 * @author Administrator 5 * 6 */ 7 public class MCGirl implements Girl { 8 9 @Override 10 public void drawWomen() { 11 // TODO Auto-generated method stub 12 System.out.println("-----------------圣诞系列的女孩子--------------------"); 13 } 14 15 }
获取男孩和女孩的工厂接口 PersonFactory.java
1 package com.sunny.project; 2 /** 3 * 人物的实现接口 4 * @author Administrator 5 * 6 */ 7 public interface PersonFactory { 8 9 //男孩接口 10 public Boy getBoy(); 11 //女孩接口 12 public Girl getGirl(); 13 14 }
新年男孩,新年女孩的工厂实现类 HNFactory.java
1 package com.sunny.project; 2 /** 3 * 新年系列加工厂 4 * @author Administrator 5 * 6 */ 7 public class HNFactory implements PersonFactory { 8 9 @Override 10 public Boy getBoy() { 11 // TODO Auto-generated method stub 12 return new HNBoy(); 13 } 14 15 @Override 16 public Girl getGirl() { 17 // TODO Auto-generated method stub 18 return new HNGirl(); 19 } 20 21 }
圣诞男孩,圣诞女孩的工厂实现类 MCFctory.java
1 package com.sunny.project; 2 /** 3 * 圣诞系列加工厂 4 * @author Administrator 5 * 6 */ 7 public class MCFctory implements PersonFactory { 8 9 @Override 10 public Boy getBoy() { 11 // TODO Auto-generated method stub 12 return new MCBoy(); 13 } 14 15 @Override 16 public Girl getGirl() { 17 // TODO Auto-generated method stub 18 return new MCGirl(); 19 } 20 21 }