第一讲:简单工厂模式

Posted 绿茵好莱坞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第一讲:简单工厂模式相关的知识,希望对你有一定的参考价值。

Apple和Banana具有共同的父类Fruit。工厂:它能够创建其他类的实例。

专门创建一个类FruitFactory来创建其他类的实例.FruitFactory创建其他类的实例的方法是静态方法.

这就是简单工厂模式的实现.


FruitFactory:工厂角色

Fruit:抽象角色

Apple、Banana:具体产品角色


把具体类的判断都放在了getFruit()方法里面.


 

比第二种方式少了对具体实现类的判断,直接传入类名动态加载这个类.适用性更广,但是客户端调用这个工厂类的时候不能区分type的大小写,灵活性比第二种方式低,因为必须传入类名才行.


 

FruitFactory的第二种实现方式包含了这种判断逻辑,根据type决定创建哪个具体类对象.客户端只需要调用工厂类FruitFactory的getFruit(String type)方法而无需了解这些对象是如何产生的.有利于软件体系的优化.

对于客户端来说,Apple和Banana以及Fruit是透明的,客户只需了解FruitFactory即可.

缺点是"高内聚"方面做的不好.特别是工厂类的第二种实现方式集中了所有实例的创建逻辑,而且还带有判断,当具体产品不断增加时工厂类也是要做修改的,扩展性不好.即使是第三种实现方式反射和动态加载类也不能从根本上解决这个问题,只是有所改造和改善.

因为第三种方式客户端调用的时候非常麻烦.客户端调用你必须给定这个类,而这个类(Apple和Banana)你又必须知道.对于客户来说第三种实现方式是非常麻烦的,所以一般使用第二种实现方式.因为采用第二种实现方式type的大小写判断客户端是不用考虑的.

而且第二种方式逻辑判断是时候可以传ap而不是apple,第三种方式就不可以这样了,完全被束缚了.所以一般会使用第二种方式.第三种方式扩展性上有所增强,但是适应性上非常的弱.


工厂模式在DAO层用的比较多.

JDBC连接MSSQL和JDBC连接mysql的代码对于客户端MainClass来说是透明的了,不需要new了,直接从工厂类里面拿.interface是把两份连接数据库的代码抽象出来的接口.由工厂类来决定返回哪一个MSSQL和MySQL的连接的实例.MainClass只需要了解工厂类里面有哪些具体实例,不需要了解JDBC连接MSSQL和JDBC连接MySQL的这两份代码,直接从工厂类里面拿.


 

public class Apple implements Fruit{
   /*
    * 采集
    * 
    */
    public void get(){
        System.out.println("采集苹果");    
    }
    
}
public class Banana implements Fruit{
    /*
     * 采集
     * 
     */
    public void get(){
        System.out.println("采集香蕉");
        
    }
}
public interface Fruit {
   /*
    * 采集
    */
    public void get();
}
public class FruitFactory {
     /*
      * 获得Apple类的实例
      * 
      */
    //public Fruit getApple(){
/*    public static Fruit getApple(){//静态方法
        return new Apple();
    }*/
      /*
       * 
       * 获得Banana类实例
       * 
       */
    //public Fruit getBanana(){
    /*    public static Fruit getBanana(){//静态方法
        return new Banana();
    }*/
    /*
     * get方法,获得所有产品对象
     */
    public static  Fruit getFruit(String type) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
/*        if(type.equalsIgnoreCase("apple")){
            //return Apple.class.newInstance();
            
        }else if(type.equalsIgnoreCase("banana")){
        return Banana.class.newInstance();
        }else{
            System.out.println("找不到相应的实例化类");
            return null;
        }
*/
//try {
    Class fruit = Class.forName(type);//Class.forName()动态加载这个类,加载的是type=Apple这个类(type是类名,你需要实例化的两个类),必须传的是Apple,比上一种方式少了判断,适用性更广一些.但是客户端调用的时候不能区分大小写,变得很死板了,失去了灵活性
    return (Fruit) fruit.newInstance();//return fruit的实例化对象.
//} catch (ClassNotFoundException e) {
    // TODO Auto-generated catch block
    //e.printStackTrace();
//}
    }
}
public class MainClass {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        
    
/*    //实例化一个Apple
    Apple apple = new Apple();
    //实例化一个Banana
    Banana banana = new Banana();
    
    apple.get();
    banana.get();*/
    
    //实例化一个Apple,用到了多态.
/*    Fruit apple = new Apple();//父类引用指向一个子类对象
    //实例化一个Banana
    Fruit banana = new Banana();
    apple.get();
    banana.get();*/
    
    //实例化一个Apple
    /*Fruit apple  = new FruitFactory().getApple();//getApple()是一个动态方法
    Fruit banana  = new FruitFactory().getBanana();//getBanana()是一个动态方法
*/    
/*        Fruit apple  = FruitFactory.getApple();//getApple()是一个动态方法
        Fruit banana  = FruitFactory.getBanana();//getBanana()是一个动态方法
        apple.get();
    banana.get();*/
   /*Fruit apple = FruitFactory.getFruit("apple");
   Fruit banana = FruitFactory.getFruit("banana");
   */
        Fruit apple = FruitFactory.getFruit("Apple");//第三种方式调用的时候必须传类名.
   Fruit banana = FruitFactory.getFruit("Banana");
         
        
   apple.get();
   banana.get();
}
}

 

以上是关于第一讲:简单工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

第一话-简单工厂模式

大话设计模式第一章-简单工厂模式

大话设计模式之简单的工厂模式

大话设计模式第一章之简单工厂模式

《大话设计模式》——读后感 代码无错就是优?——简单工厂模式

设计模式大冒险第三关:工厂模式,封装和解耦你的代码