工厂模式概念:
实例化对象的时候,用工厂方法代理new操作
工厂模式包括工厂方法模式和抽象工厂模式
抽象工厂模式是工厂方法模式的扩展
工厂模式的意图:定义一个接口来创建对象,但是让子类来决定哪些类需要被实例化。工厂方法把实例化的工作推到子类中去实现。
什么情况下适合工厂模式?
有一组类似的对象需要被创建
在编码是不能预见需要创建那种类的实例
在系统需要考虑扩展性,不应依赖于产品实例如何被创建、组合和表达的细节
一、应用场景举例
1.1工厂方法模式
要做一个类似于脸萌的软件,应该怎么来构思呢?一发型为例,发型师这个大产品中的一个小部件,如过制作出了发型,其他的部分也都相似。
下边我们使用发型来举例说明工厂方法模式
1.HairInterface.java 首先定义发型接口
public interface HairInterface { /** *实现了发型 */ void draw(); }
2.LeftHair.java 左偏分发型,实现发型接口
public class LeftHair implements HairInterface { /** * 画了一个左偏分发型 */ public void draw() { System.out.printf("-----左偏分发型----"); } }
3.RightHair.java 右偏分发型,实现发型接口
public class RightHair implements HairInterface{ /** * 画了一个右偏分发型 */ public void draw() { System.out.printf("-----右偏分发型----"); } }
4.HairFactory.java 发型工厂,用于创建发型
public class HairFactory { /* * 根据类型来创建对象, * @param key * @return */ public HairInterface getHair(String key) { if ("left".equals(key)) { return new LeftHair(); } else if ("right".equals(key)) { return new RightHair(); } return null; } /** * 根据类名称来生产对象 * * @param className * @return */ public HairInterface getHairByClass(String className) { HairInterface hair = null; try { hair = (HairInterface) Class.forName(className).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return hair; } /** * 根据类型名称的key值来产生对象 * @param key * @return */ public HairInterface getHairByClassKey(String key){ HairInterface hair = null; try { Map<String,String> map = new PropertiesReader().getProperties(); hair = (HairInterface) Class.forName(map.get(key)).newInstance(); }catch (Exception e){ e.printStackTrace(); } return hair; } }
5.type.properties 文件
left=personal.caojx.factory.LeftHair right=personal.caojx.factory.RightHair
6.PropertiesReader.java properties文件读取类
public class PropertiesReader { public Map<String,String> getProperties(){ Properties properties = new Properties(); Map<String,String> map = new HashMap<String, String>(); try{ InputStream in = PropertiesReader.class.getClassLoader().getResourceAsStream("type.properties"); properties.load(in); Enumeration en = properties.propertyNames(); while (en.hasMoreElements()){ String key = (String) en.nextElement(); String property = properties.getProperty(key); map.put(key,property); } }catch (Exception e){ e.printStackTrace(); } return map; } }
7.HairFactoryTest.java 工厂方法模式-发型工厂测试类
public class HairFactoryTest extends TestCase { public static void main(String[] args){ //1.通过工厂创建实例实例一 HairFactory factory = new HairFactory(); HairInterface left = factory.getHair("left"); HairInterface right = factory.getHair("right"); left.draw(); right.draw(); //2.通过工厂创建实例二 HairInterface left2 = factory.getHairByClass("personal.caojx.factory.LeftHair"); left2.draw(); //2.通过工厂创建实例三 HairInterface left3 = factory.getHairByClassKey("left"); left3.draw(); } }
结果
-----左偏分发型---- -----右偏分发型---- -----左偏分发型---- -----左偏分发型----
2.抽象工厂模式
加入我们过圣诞节或新年的时候需要创建圣诞的男孩女孩,和新年系列的男孩女孩,这时候我们可以考虑抽象工厂模式
1.Boy.java 男孩接口
public interface Boy { void drawMan(); }
Girl.java 女孩接口
public interface Girl { void drawWomen(); }
2.HNBoy.java 新年男孩实现类
public class HNBoy implements Boy { public void drawMan() { System.out.println("----------新年系列的男孩-----------"); } }
HNGirl.java 新年女孩实现类
public class HNGirl implements Girl { public void drawWomen() { System.out.println("----------新年系列的女孩-----------"); } }
MCBoy.java 圣诞男孩实现类
public class MCBoy implements Boy { public void drawMan() { System.out.println("----------圣诞系列的男孩-----------"); } }
MCGirl.java 圣诞女孩实现类
public class MCGirl implements Girl { public void drawWomen() { System.out.println("------圣诞系列的女孩---------"); } }
3.PersonFactory.java 人物接口实现类
public interface PersonFactory { //男孩接口 Boy getBoy(); //女孩接口 Girl getGirl(); }
4.MCFactory.java 圣诞工厂
public class MCFactory implements PersonFactory { public Boy getBoy() { return new MCBoy(); } public Girl getGirl() { return new MCGirl(); } }
HNFactory.java 新年工厂
public class HNFactory implements PersonFactory{ public Boy getBoy() { return new HNBoy(); } public Girl getGirl() { return new HNGirl(); } }
5.抽象工厂测试类
public class AbstractFactoryTest extends TestCase { public static void main(String[] args){ //聖誕女孩 PersonFactory factory = new MCFactory(); Girl girl = factory.getGirl(); girl.drawWomen(); //新年男孩 PersonFactory factory1 = new HNFactory(); Boy boy = factory1.getBoy(); boy.drawMan(); } }
结果
------圣诞系列的女孩--------- ------新年系列的男孩---------
3.总结
工厂方法模式和抽象工厂模式對比 1.工厂模式是一种极端情況的抽象工厂模式,而抽工厂模式可以堪称是工厂模式的推广 2.工厂模式用来创建一个产品的等级结构,而抽象工厂模式是用来创建多个产品的等级结构 3.工厂模式只有一个抽象产品类,而抽象工厂模式有多个抽象产品类
工厂模式的实现帮助了我们: 1.系统可以在不修改具体工厂角色的情况下引进新的产品 2.客户端不必关心对象的创建 3.更好的理解面向对象的原则,面向接口编程,而不要面向实现编程