工厂模式有三种模式:

  • 简单工厂模式
    能够扩展同一级别的任意产品。
  • 工厂方法模式
    不修改已有类的前提下,通过增加新的工厂类来实现扩展。
  • 抽象工厂模式
    不可以增加产品,可以增加产品族。

简单工厂 (静态工厂模式)

比方说:我们现在有个需求,实现几种口味的蛋糕并且实现对这些蛋糕的订购功能。
图片说明

目前我们的蛋糕有三种,代码也已经实现完了。这时突然要增加一种口味的蛋糕,除了要添加一个类外,三个订单功能类也要修改。也就是在订单类中增加多一个if-else。而在现实生活中,我们的订单远远超出三个。这样一处改,处处都得改,降低开发效率,违反了设计模式的ocp原则,即对扩展开放,对修改关闭

而静态工厂模式就是由一个工厂对象统一创建所有口味的蛋糕实例。就是将蛋糕选择的判断生成交由工厂去实现。但我们新增一种口味蛋糕时,只需要在工厂类中添加即可,然后在需要用到的订单功能类调用工厂类来获取就好了。

//同一等级蛋糕结构,可以进行扩展
public interface Cake {
    void make();
    void cut();
}

//具体的蛋糕实例
public class GreekCake implements Cake{

    @Override
    public void make() {
        System.out.println("GreekCake制作完成");
    }

    @Override
    public void cut() {
        System.out.println("GreekCake已切块");
    }
}

//统一创建蛋糕实例的工厂
public class CakeFactory {
    //方法一
    public static Cake getCake(String cake){
        if ( cake.equals("GreekCake")) {
            return new GreekCake();
        }else if ( cake.equals("SweetCake")){
            return new SweetCake();
        }else{
            return null;
        }
    }

    //方法二
    public static Cake getGreekCake(){
        return new GreekCake();
    }
    public static Cake getSweetCake(){
        return new SweetCake();
    }
}

//用户订单,多个
public class Order1 {
    public static void main(String[] args) {
        Cake greekCake = CakeFactory.getGreekCake();
        Cake sweetCake = CakeFactory.getSweetCake();

        greekCake.make();
        greekCake.cut();
    }
}

工厂方法模式

定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类
比如我们想要不同地方不同口味的蛋糕,我们需要在不同地方设立工厂,一个工厂能够创建出不同口味的蛋糕实例。当某个工厂要新增口味时,对其他工厂不影响。

代码实现:(蛋糕接口和蛋糕类省略)

//工厂接口
public interface Factory {
    Cake getGreekCake();
    Cake getSweetCake();
}

//不同的工厂
public class BeijingFactory implements Factory{

    @Override
    public Cake getGreekCake() {
        return new GreekCake();
    }

    @Override
    public Cake getSweetCake() {
        return new SweetCake();
    }
}

public class XianFactory implements Factory{
    @Override
    public Cake getGreekCake() {
        return new GreekCake();
    }

    @Override
    public Cake getSweetCake() {
        return new SweetCake();
    }

    //可以新增任意一种口味的蛋糕
}

抽象工厂模式

抽象工厂模式可以为我们的工厂增加产品族
比方说,有家电子公司,它负责生产两个牌子的手机和路由器,于是设立了两个牌子的工厂,如下图所示:

图片说明
此时,如果这家公司想要扩大业务,想生产数据线,那只需要添加一个产品接口或者抽象类即可。

代码实现:

public interface IphoneProduct {
    void start();
    void shutdown();
    void callup();
    void sendSMS();
}

public class XiaomiPhone implements IphoneProduct{
    @Override
    public void start() {
        System.out.println("开启小米手机");
    }

    @Override
    public void shutdown() {
        System.out.println("关闭小米手机");
    }

    @Override
    public void callup() {
        System.out.println("小米打电话");
    }

    @Override
    public void sendSMS() {
        System.out.println("小米发短信");
    }
}

public class HuaweiPhone implements IphoneProduct{
    @Override
    public void start() {
        System.out.println("开启华为手机");
    }

    @Override
    public void shutdown() {
        System.out.println("关闭华为手机");
    }

    @Override
    public void callup() {
        System.out.println("华为手机打电话");
    }

    @Override
    public void sendSMS() {
        System.out.println("华为手机发短信");
    }
}

public interface IRouterProduct {
    void start();
    void shutdown();
    void openWifi();
    void setting();
}

public class XiaomiRouter implements IRouterProduct{
    @Override
    public void start() {
        System.out.println("开启小米路由器");
    }

    @Override
    public void shutdown() {
        System.out.println("关闭小米路由器");
    }

    @Override
    public void openWifi() {
        System.out.println("小米打开WiFi");
    }

    @Override
    public void setting() {
        System.out.println("小米设置参数");
    }
}

public class HuaweiRouter implements IRouterProduct{
    @Override
    public void start() {
        System.out.println("打开华为路由器");
    }

    @Override
    public void shutdown() {
        System.out.println("关闭华为路由器");
    }

    @Override
    public void openWifi() {
        System.out.println("华为打开WiFi");
    }

    @Override
    public void setting() {
        System.out.println("华为设置参数");
    }
}

//抽象产品工厂
public interface IProductFactory {
    //生成手机
    IphoneProduct iphoneProduct();


    //生产路由器
    IRouterProduct iRouterProduct();
}

public class HuaweiFactory implements IProductFactory{
    @Override
    public IphoneProduct iphoneProduct() {
        return new HuaweiPhone();
    }

    @Override
    public IRouterProduct iRouterProduct() {
        return new HuaweiRouter();
    }
}

public class XiaomiFactory implements IProductFactory{
    @Override
    public IphoneProduct iphoneProduct() {
        return new XiaomiPhone();
    }

    @Override
    public IRouterProduct iRouterProduct() {
        return new XiaomiRouter();
    }
}

//客户
public class Client {
    public static void main(String[] args) {

        System.out.println("==========小米系列产品=============");
        //小米工厂
        XiaomiFactory xiaomiFactory = new XiaomiFactory();

        IphoneProduct iphoneProduct = xiaomiFactory.iphoneProduct();
        iphoneProduct.callup();
        iphoneProduct.sendSMS();

        IRouterProduct iRouterProduct = xiaomiFactory.iRouterProduct();
        iRouterProduct.openWifi();
        iRouterProduct.setting();

        System.out.println("===========华为系列产品===========");
        //华为工厂
        HuaweiFactory huaweiFactory = new HuaweiFactory();
        iphoneProduct = huaweiFactory.iphoneProduct();
        iphoneProduct.callup();
        iphoneProduct.sendSMS();

        iRouterProduct = huaweiFactory.iRouterProduct();
        iRouterProduct.openWifi();
        iRouterProduct.setting();
    }
}

应用场景

  • JDK中Calender的getInstance方法用了简单工厂模式思想
  • JDBC的Connection对象的获取
  • Spring中IOC容器创建管理bean对象利用了简单工厂模式
  • 反射中Class对象的newInStance方法

工厂模式将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。