您的位置:首页 > 其它

设计模式学习笔记——工厂方法模式

2014-07-16 16:43 375 查看
原文:http://blog.csdn.net/hackerain/article/details/7531049

定义:

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

通用类图:



代码如下:

[java] view
plaincopy

public abstract class Product {

public void method1(){

System.out.println("method1 invoked");

}

public abstract void method2();

}

[java] view
plaincopy

public class ConcreteProduct1 extends Product {

@Override

public void method2() {

System.out.println("product1 method2 invoked");

}

}

[java] view
plaincopy

public abstract class Creator {

/**

* 创建一个产品对象,其输入参数类型可以自行设置

* 通常为String、Enum、Class等,当然也可以为空

* @param c

* @return

*/

public abstract <T extends Product> T createProduct(Class<T> c);

}

[java] view
plaincopy

public class ConcreteCreator extends Creator {

@Override

public <T extends Product> T createProduct(Class<T> c) {

Product product=null;

try {

product=(Product)Class.forName(c.getName()).newInstance();

} catch (Exception e) {

e.printStackTrace();

}

return (T)product;

}

}

工厂方法模式的优点:

1、良好的封装性,代码结构清晰

2、扩展性很好

3、屏蔽产品类

工厂模式的扩展:

1、缩小为简单工厂模式

即一个模块仅需要一个工厂类,没有必要使用抽象类,使用静态的方法就可以了。代码如下:

[java] view
plaincopy

public class SimpleCreator {

public static <T extends Product> T createProduct(Class<T> c){

Product product=null;

try {

product=(Product)Class.forName(c.getName()).newInstance();

} catch (Exception e) {

e.printStackTrace();

}

return (T)product;

}

}

简单工厂模式的缺点是工厂类的扩展比较困难,不符合开闭原则,但是非常实用。

2、升级为多个工厂类

即针对每一种产品,单独创建一个工厂类,而不是混合在一起,根据传入参数的类型判断要产生哪种产品,这样的方法更符合单一职责原则,类图如下:



源代码如下:

[java] view
plaincopy

public abstract class Creator {

public abstract Product createProduct();

}

[java] view
plaincopy

public class Product1Creator extends Creator {

@Override

public Product createProduct() {

return new ConcreteProduct1();

}

}

[java] view
plaincopy

public class Product2Creator extends Creator {

@Override

public Product createProduct() {

return new ConcreteProduct2();

}

}

多工厂类应用在每个实现类的初始化都不一样的情况下,而这种情况更为普遍,但是这样就增加了维护的难度,一种产品就有一个对应的工厂类。当然,也可以将各个子工厂类进行封装,向外提供统一的接口,这样就避免了代码混乱。

3、替代单例模式

前面所说的单例模式有一定的缺点,比如说对测试不利,因为它没有接口,不能用来mock的方法虚拟一个对象。我们可以用工厂方法模式的方法,来写一个单例模式的例子,抓住主要矛盾:单例模式要求在内存中,只存在一个实例。其类图如下:



代码如下:

[java] view
plaincopy

public class Singleton {

//定义成私有的构造函数,防止被外部实例化

private Singleton(){

System.out.println("Singleton is created");

}

public void doSomething(){

System.out.println("do something...");

}

}

[java] view
plaincopy

public class SingletonFactory {

private static Singleton singleton;

static{

try{

Class clss=Class.forName(Singleton.class.getName());

//获得无参构造函数

Constructor constructor=clss.getDeclaredConstructor();

//设置无参构造函数是可访问的

constructor.setAccessible(true);

//产生一个实例

singleton=(Singleton)constructor.newInstance();

}catch(Exception e){

e.printStackTrace();

}

}

public static Singleton getSingleton(){

return singleton;

}

}

4、延迟初始化

延迟初始化,即一个对象被消费完后,并不立即释放,工厂类保存其初始状态,等待再次被使用,通用类图如下:



延迟工厂类代码如下:

[java] view
plaincopy

public class LazyCreator {

private static final Map<String,Product> map=new HashMap<String,Product>();

public static synchronized Product createProduct(String key){

Product product=null;

if(map.containsKey(key)){

return map.get(key);

}

else{

if(key.equals("Product1")){

product=new ConcreteProduct1();

}

else if(key.equals("Product2")){

product=new ConcreteProduct2();

}

map.put(key, product);

}

return product;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息