网站首页 文章专栏 设计模式之 ——【工厂模式】
设计模式之 ——【工厂模式】

一,工厂模式概念及使用场合

1,工厂模式概念:

        实例化对象,使用工厂方法代替new的操作

        工厂模式包括工厂方法模式和抽象工厂模式

        抽象工厂是工厂方法模式的拓展

2,工厂模式的意图

        定义一个借口来创建对象,让子类来决定什么对象需要被实例化

        工厂方法把实例化的操作放在子类中去实现

3,适合使用的场景

        有一组类似的对象需要被创建

        在编码是不能预见哪些对象需要被创建

        系统考虑拓展性,不需要考虑依赖对象的创建过程细节

二,两种模式的示意图

KGK_($G7ZLGR{)O_~XSZLK8.png


U9BCM`VU$$E4I47HL9V1NCA.png

三,简单工厂模式

1,定义需要被实例化的实体类

/**
 * 定义车辆
 */
public interface Car {

    /**
     * 车辆会跑
     */
   public void run();

}

/**
 * 奥迪
 */
public class AoDi implements Car {

    @Override
    public void run () {
        System.out.println("--------奥迪车--------");
    }
}

/**
 * 宝马车
 */
public class BaoMa implements Car {

    @Override
    public void run(){
        System.out.println("--------宝马车-------");
    }
}

2,创建车辆工厂类

/**
 * 车辆工厂
 */
public class CarFactory {

    /**
     * 根据车名获取车辆实例
     * @param carName
     * @return
     */
    public static Car getCarInstance(String carName){
        if("aodi".equals(carName)){
            return new AoDi();
        }else if("baoma".equals(carName)){
            return new BaoMa();
        }
        return null;
    }
}
// 使用工厂类实例化一辆奥迪车
Car aodi = CarFactory.getCarInstance("aodi");
aodi.run();

这便是简单工厂,实例化不需要显示new 一个车,通过车辆工厂类来创建,缺点也是很明显,违背了设计模式的开闭原则(对扩展开放,对修改关闭),因为要想增加车类型就要对工厂进行改建,而且如果传参数不对的话,变会报错。

2,使用反射实现

在工厂类里面新建以下方法

public static  T getCarInstanceByClass(Class clz) {
    T result = null;
    try {
        result = (T) Class.forName(clz.getName()).newInstance();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}
Car baoma = CarFactory.getCarInstanceByClass(BaoMa.class);
baoma.run();

这种方式的优点在于想增加一个新的车辆时不需要额外修改工厂方法,只需要添加一个车辆实体类继承自Car就行

缺点:

这种写法粗看牛逼,细想之下,不谈reflection的效率还有以下问题:

1 个人觉得不好,因为Class.forName(clz.getName()).newInstance()调用的是无参构造函数生成对象,它和new Object()是一样的性质,而工厂方法应该用于复杂对象的初始化 ,当需要调用有参的构造函数时便无能为力了,这样像为了工厂而工厂。

2 不同的产品需要不同额外参数的时候 不支持。

四,多方法工厂

还有一种实现方式,在工厂类里写多个方法实例化。

public static Car createBaoMa(){
    return new BaoMa();
}

public static Car createAoDi(){
    return new AoDi();
}
Car aodi = CarFactory.createAoDi();
aodi.run();

这种方式优点在于可以传入构造参数来实例化,为不同产品提供不同生产方法,需要实例化哪个就用哪个,且不需要传入类名等参数,容错率较高。

缺点:需要添加新车型时,需要在工厂类新建相应的函数

五,工厂方法模式

// 定义一个抽象车辆工厂
public abstract class AbstractCarFactory {

    public abstract Car create();
}
// 定义奥迪工厂并继承与抽象工厂
public class AoDiFactory extends AbstractCarFactory {

    @Override
    public Car create () {
        return new AoDi();
    }
}
// 定义宝马工厂并继承与抽象工厂
public class BaoMaFactory extends AbstractCarFactory {

    @Override
    public Car create () {
        return new BaoMa();
    }
}
AoDiFactory factory = new AoDiFactory();
Car aodi = factory.create();
aodi.run();

工厂方法模式就是为了解决简单工厂模式的弊端,工厂方法模式拥有一个抽象工厂,用户需要的不同产品,需要不同的继承了该抽象工厂的实例工厂去创建,工厂方法使一个产品类的实例化延迟到其具体工厂子类,这样每当用户需要生产不同的产品的时候只需要取实例化对应的工厂实例和产品模型,扩展性要比简单工厂优秀的多,但是其缺点也是比较明显的,就是需要取创建很多工厂实例,类的数量增加的比较多。

六,抽象工厂

以上介绍的工厂都是单产品系的。抽象工厂是多产品系 (也有产品家族的说法)

我们的车辆不仅有品牌之分,(假如这些车都是由一家公司创造),还有排量,座位数之分,假如现在我们要生产奥迪2.0 T,1.0 T排量 和 宝马2.0 T,1.0 T排量的车。

public interface AoDi {

    public void createAodi();

}

public interface BaoMa {

    public void createBaoma();
}
public class AoDi1T implements AoDi {

    @Override
    public void createAodi () {
        System.out.println("----------创建一个1T的奥迪-----------");
    }
}

public class AoDi2T implements AoDi {

    @Override
    public void createAodi () {
        System.out.print("--------创建一个2.0T的奥迪---------");
    }
}
public class BaoMa1T implements BaoMa {

    @Override
    public void createBaoma () {
        System.out.println("--------创建一个1T的宝马---------");
    }
}
public class BaoMa2T implements BaoMa{

    @Override
    public void createBaoma () {
        System.out.println("---------创建一个2.0T的宝马----------");
    }
}
/**
 * 车辆实现接口
 */
public interface CarFactory {

    //奥迪接口
    public AoDi getAoDi();
    // 宝马接口
    public BaoMa getBaoMa();
}
/**
 * 1.0T系列车辆
 */
public class Car1TFactory implements CarFactory {

    @Override
    public AoDi getAoDi () {
        return new AoDi1T();
    }

    @Override
    public BaoMa getBaoMa () {
        return new BaoMa1T();
    }
}
/**
 * 2.0T系列车辆
 */
public class Car2TFactory implements CarFactory {

    @Override
    public AoDi getAoDi () {
        return new AoDi2T();
    }

    @Override
    public BaoMa getBaoMa () {
        return new BaoMa2T();
    }
}
public static void main(String[] args){
    CarFactory factory2t = new Car2TFactory(); // 2.0T车辆工厂
    AoDi aoDi2t = factory2t.getAoDi();    // 2t奥迪
    BaoMa baoma2T = factory2t.getBaoMa(); // 2t宝马

    CarFactory factory1t = new Car1TFactory(); // 1.0T车辆工厂
    AoDi aoDi1t = factory1t.getAoDi(); // 1.0t奥迪
    BaoMa baoma1T = factory1t.getBaoMa(); // 1.0t宝马
}

抽象工厂将车辆,以及工厂全部抽象,实例工厂可以生产多种产品,有多个抽象产品,每个实例工厂相当于一个家族(1.0t,2.0t),众多家族中的产品种类 ( 宝马,奥迪 ) 相同,这里的实例工厂有了定制一个产品的不同规格配件的功能。

 总结: 工厂模式在实际工作中会经常接触到,比如 jdbc 连接就是通过客户端发送参数获得相应的连接,还有spring beanFactory,作为spring 的IOC容器,是spring的一个bean工厂,但从工厂模式角度理解,其就是用来生产bean ,提供给客户端。


水平有限,总结到此,希望大牛不吝赐教





版权声明:本文由星尘阁原创出品,转载请注明出处!

本文链接:http://www.52xingchen.cn/detail/44




赞助本站,网站的发展离不开你们的支持!
来说两句吧
最新评论