设计模式--工厂方法模式

来源:互联网 发布:linux killproc 编辑:程序博客网 时间:2024/05/17 01:08
定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
通用类图:


代码如下:

public abstract class Product {  
    public void method1(){  
        System.out.println("method1 invoked");  
    }        
    public abstract void method2();  
}  


public class ConcreteProduct1 extends Product {  
    @Override  
    public void method2() {  
        System.out.println("product1 method2 invoked");  
    }  
}  

public abstract class Creator {  
    /** 
     * 创建一个产品对象,其输入参数类型可以自行设置 
     * 通常为String、Enum、Class等,当然也可以为空 
     * @param c 
     * @return 
     */  
    public abstract <T extends Product> T createProduct(Class<T> c);  
}  

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、缩小为简单工厂模式
即一个模块仅需要一个工厂类,没有必要使用抽象类,使用静态的方法就可以了。代码如下:

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、升级为多个工厂类
即针对每一种产品,单独创建一个工厂类,而不是混合在一起,根据传入参数的类型判断要产生哪种产品,这样的方法更符合单一职责原则,类图如下:




源代码如下:
public abstract class Creator {  
    public abstract Product createProduct();  
}  
[java] view plaincopy
public class Product1Creator extends Creator {  
  
    @Override  
    public Product createProduct() {  
        return new ConcreteProduct1();  
    }  
}  

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

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

代码如下
public class Singleton {  
      
    //定义成私有的构造函数,防止被外部实例化  
    private Singleton(){  
        System.out.println("Singleton is created");  
    }  
    public void doSomething(){  
        System.out.println("do something...");  
    }  
}  


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



延迟工厂类代码如下:

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;  
    }  
}  
0 0
原创粉丝点击