工厂模式
设计模式(Design Pattern):
设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结。
设计模式的优点:
设计模式是优秀的使用案例,使用设计模式可提高代码的重用性,让代码更容易被他人理解,保证代码可靠性。
工厂模式的概念:
实例化对象,用工厂方法代替new操作
工厂模式包括工厂方法模式和抽象工厂模式
抽象工厂模式是工厂方法模式的扩展
工厂模式的意图:
定义一个接口来创建对象,但是让子类来决定哪些类需要被实例化
工厂方法把实例化的工作推迟到子类中去实现
什么情况下适合工厂模式?
有一组类似的对象需要创建
在编码时不能预见需要创建那种类的实例
系统需要考虑扩展性,不应依赖于产品类实例如何被创建,组合和表达细节
工厂模式的动机:
项目中的现状:在软件系统中经常面临着“对象”的创建工作,由于需求的变化,这个对象可能也会发生变化,但它拥有比较稳定的接口。
为此我们需要提供一种封装机制来隔离这个易变对象的变化,从而保持系统会中其它依赖该对象的对象不随着需求变化而变化。
基于项目现状将代码进行如下设计:
1.尽量松耦合,一个对象的依赖对象的变化与本身无关
2.具体产品与客户端剥离,责任分割
1.工厂方法模式:
01.创建接口
package com.ltc; /** * 发型接口 */ public interface HairInterface { public void draw(); }
02.创建不同的发型实现该接口
package com.ltc; /** * 右偏分发型 */ public class RightHair implements HairInterface { @Override public void draw() { System.out.println("-----------------左偏分发型-------------------"); } }
package com.ltc;
/**
* 左偏分发型
*/
public class LeftHair implements HairInterface {
@Override
public void draw() {
System.out.println("-----------------左偏分发型-------------------");
}
}
03.创建发型工厂生产不同发型
package com.ltc; import java.util.Map; public class HairFactory { /** * 根据类名称来生产对象 */ public HairInterface getHairByClassKey(String key){ Map<String,String> map = new PropertiesReader().getProperties(); try { //用反射创建对象 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; } }
上述代码中红色字体部分的作用:
代码用反射的方式创建的对象实例,forName(“”)方法中要传全类名,我们可以利用properties文件key-value的存储方式存储全类名,然后读取该文件,返回一个Map根据获得全类名。
读取该文件:
package com.ltc; import java.io.InputStream; import java.util.Properties; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; public class PropertiesReader { public Map<String, String> getProperties() { Properties 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); // System.out.println(key + " " + property); } } catch (Exception e) { e.printStackTrace(); } return map; } }
测试:
package com.ltc; public class Text1 { public static void main(String[] args) { HairFactory factory = new HairFactory(); HairInterface hair1 = factory.getHairByClassKey("right"); hair1.draw(); HairInterface hair2 = factory.getHairByClassKey("left"); hair2.draw(); } }
结果:
2.抽象工厂模式
以新年和圣诞人们的装扮为例:
新年和圣诞人们都会进行不同的装扮,有新年系列装扮的男孩和女孩,也有圣诞系列新年的男孩和女孩,那我们如何实现新年就进行新年装扮,圣诞就进行圣诞装扮呢?
01.创建男孩和女孩接口人的工厂接口
package com.ltc; /** * 男孩 */ public interface Boy { public void drawMan(); }
package com.ltc; /** * 女孩 */ public interface Girl { public void drawWomen(); }
package com.ltc; /** * 任务的实现接口 */ public interface PersonFactory { //男孩接口 public Boy getBoy(); //女孩接口 public Girl getGirl(); }
02,分创建新年男孩和新年女孩类实现男孩女孩接口,并创建新年工厂
package com.ltc; /** * 新年系列的男孩儿 */ public class HNBoy implements Boy { @Override public void drawMan() { System.out.println("-----------------新年系列的男孩子--------------------"); } }
package com.ltc; /** * 新年系列的女孩儿 */ public class HNGirl implements Girl{ @Override public void drawWomen() { System.out.println("-----------------新年系列的女孩子--------------------"); } }
package com.ltc; /** * 新年系列加工厂 */ public class HNFactory implements PersonFactory { @Override public Boy getBoy() { return new HNBoy(); } @Override public Girl getGirl() { return new HNGirl(); } }
03.创建圣诞男孩和圣诞女孩实现男孩和女孩接口,创建圣诞工厂
package com.ltc; /**
*圣诞男孩儿
*/ public class MCBoy implements Boy { @Override public void drawMan() { System.out.println("-----------------圣诞系列的男孩子--------------------"); } }
package com.ltc; public class MCGirl implements Girl { @Override public void drawWomen() { System.out.println("-----------------圣诞系列的女孩子--------------------"); } }
package com.ltc; public class MCFactory implements PersonFactory { @Override public Boy getBoy() { return new MCBoy(); } @Override public Girl getGirl() { return new MCGirl(); } }
04测试:
PersonFactory factory1 = new MCFactory(); Girl girl1 = factory1.getGirl(); Boy boy1 = factory1.getBoy(); girl1.drawWomen(); boy1.drawMan(); System.out.println("=================================================="); PersonFactory factory2 = new HNFactory(); Girl girl2 = factory2.getGirl(); Boy boy2 = factory2.getBoy(); girl2.drawWomen(); boy2.drawMan();
结果:
工厂方法模式和抽象工厂模式对比:
01.工厂方法模式是一种极端情况的抽象工厂模式,而抽象工厂模式可以看成是工厂模式的推广
02.工厂模式用来创建一个产品的等级结构,而抽象工厂是用来创建多个产品的等级结构
03.工厂模式只有一个抽象产品类,而抽象工厂模式有多个抽象产品类
工厂模式的实现帮助我们:
01.系统在不修改具体工厂角色的情况下引进新的产品
02.客户端不必关心对象如何创建,明确了职责
03.更好的理解,面向对象的原则,面向接口编程,而不要面向实现编程
工厂模式适用与哪些场景:
01.一个系统应当不依赖于产品实力被创立,组成,和表示细节。这对于所有形态的工厂模式都是重要的
02.这个系统的产品至少有一个产品族
03.同属于同一产品族的产品是设计成在一起使用。这一约束必须得在系统的设计中体现出来
04.不同的产品以一系列的接口的面貌实现,从而使系统不依赖于接口实现的细节
posted on 2018-01-16 10:32 天天xiangshang 阅读(287) 评论(0) 编辑 收藏 举报