可参考的资料:
http://www.cnblogs.com/zhangchenliang/p/3700820.html
1.
简单工厂
它由三种角色组成:
工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,根据逻辑不同,产生具体的工厂产品。
抽象产品角色:它一般是具体产品继承的父类或者实现的接口。由接口或者抽象类来实现。
具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
eg:
package factory.simple;
public interface Phone {
void call();
}
package factory.simple;
public class Iphone implements Phone {
private String name;
private double price;
@Override
public void call() {
System.out.println("Iphone can make telephone call!");
}
}
package factory.simple;
public class Android implements Phone {
private String name;
private double price;
@Override
public void call() {
System.out.println("Android can make telephone call!");
}
}
package factory.simple;
public class SimpleFactory {
public Phone productMobile(String name){
if("Iphone".equals(name)){
return new Iphone();
}else if("Android".equals(name)){
return new Android();
}else{
return null;
}
}
}
package factory.simple;
public class ClientDemo {
public static void main(String[] args) {
SimpleFactory factory = new SimpleFactory();
Phone phone = factory.productMobile("Iphone");
if (phone != null) {
phone.call();
}
}
}
改进:
利用java的反射机制,通过类名创建对象。
public Phone productMobileByClassName(String className){
try {
return (Phone)Class.forName(className).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
此时客户端测试代码:
SimpleFactory factory = new SimpleFactory();
Phone phone = factory.productMobile("Iphone");
if (phone != null) {
phone.call();
}
//这里不友好
Phone ph1 = factory.productMobileByClassName("factory.simple.Android");
if (ph1 != null) {
ph1.call();
}
Phone ph = factory.productMobileByProp("Iphone");
if (ph != null) {
ph.call();
}
客户须要知道要生产的手机的完全限定名,不友好
改进:
使用properties文件来存储key-class的映射,用户只需输入该类对应的key值,即可找到类的完全限定名,进而通过反射机制获取类的实例。
package factory.simple;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class PropertiesReader {
public Map<String, String> getProperties() {
Properties prop = new Properties();
InputStream is = this.getClass().getResourceAsStream("props.properties");
try {
prop.load(is);
} catch (IOException e) {
throw new RuntimeException(e);
}
Enumeration names = prop.propertyNames();
Map<String,String> properties=new HashMap<String,String>();
String key=null;
while(names.hasMoreElements()){
key=(String) names.nextElement();
properties.put(key, prop.getProperty(key));
}
return properties;
}
}
////////////////////////////////////
package factory.simple;
import java.util.Map;
public class SimpleFactory {
public Phone productMobile(String name){
if("Iphone".equals(name)){
return new Iphone();
}else if("Android".equals(name)){
return new Android();
}else{
return null;
}
}
public Phone productMobileByClassName(String className){
try {
return (Phone)Class.forName(className).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public Phone productMobileByProp(String key){
try {
Map<String, String> classNameMap=new PropertiesReader().getProperties();
return (Phone)Class.forName(classNameMap.get(key)).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
此时客户端测试代码:
package factory.simple;
public class ClientDemo {
public static void main(String[] args) {
SimpleFactory factory = new SimpleFactory();
Phone phone = factory.productMobile("Iphone");
if (phone != null) {
phone.call();
}
//使用properties文件的方式,客户端只需要输入一个名称
Phone ph=factory.productMobileByProp("Iphone");
if (ph != null) {
ph.call();
}
}
}
简单工厂分析
首先,符合现实中的情况;而且客户端免除了直接创建产品对象的责任,而仅仅负责“消费”产品。
下面我们从开闭原则上来分析下简单工厂模式。当增加了一种手机的时候,只要符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。(即创建一个新的手机类,实现抽象产品Phone)那么 对于产品部分来说,它是符合开闭原则的——对扩展开放、对修改关闭;但是工厂类不太理想,因为每增加一种手机,都要在工厂类中增加相应的商业逻辑和判 断逻辑,这显自然是违背开闭原则的。而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝类坏了。
正如我前面提到的简单工厂模式适用于业务简单的情况下或者具体产品很少增加的情况。而对于复杂的业务环境可能不太适应了。这就应该由工厂方法模式来出场了!!
2.
工厂方法:
抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
eg:
public interface Factory {
Phone productMobile();
}
public class IphoneFactory implements Factory{
@Override
public Phone productMobile() {
return new Iphone();
}
}
public class AndroidFactory implements Factory{
@Override
public Phone productMobile() {
return new Android();
}
}
public class ClientDemo {
public static Factory getFactoryByProp(String key) {
try {
Map<String, String> classNameMap = new PropertiesReader().getProperties();
return (Factory) Class.forName(classNameMap.get(key)).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
/*
* SimpleFactory factory = new SimpleFactory(); Phone phone =
* factory.productMobile("Iphone"); if (phone != null) { phone.call(); }
* Phone ph1=factory.productMobileByClassName("factory.simple.Android");
* if (ph1 != null) { ph1.call(); } Phone
* ph=factory.productMobileByProp("Iphone"); if (ph != null) {
* ph.call(); }
*/
Factory factory = getFactoryByProp("IphoneF");
Phone phone = factory.productMobile();
if (phone != null) {
phone.call();
}
}
}
工厂方法分析:
使用开闭原则来分析下工厂方法模式。当有新的产品(即windowsPhone)产生时,只要按照抽象产品、抽象工厂提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。(即当有新产品时,只要创建并实现抽象产品接口;新建具体工厂实现抽象工厂接口;而不用修改任何一个类)工厂方法模式是完全符合开闭原则的!使用工厂方法模式足以应付我们可能遇到的大部分业务需求。
但是当产品种类非常多时,就会出现大量的与之对应的工厂类,这不应该是我们所希望的。所以我建议在这种情况下使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。当然特殊的情况,就要特殊对待了:对于系统中存在不同的产品树,而且产品树上存在产品族(下一节将解释这个名词)。那么这种情况下就可能可以使用抽象工厂模式了。
3.
抽象工厂未完待续。。。。。。