设计模式 — 工厂模式

简单工厂模式

  1. 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例

  2. 简单工厂模式(静态工厂模式):定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)

  3. 在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式.

注意:简单工厂模式不是23中设计模式之一

  • 优点

    1. 工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。

    2. 客户端无需知道所创建具体产品的类名,只需知道参数即可。

    3. 也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。

  • 缺点

    1. 简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则。
    2. 使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
    3. 系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
    4. 简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。

应用场景

  • 对于产品种类相对较少的情况

  • 只知道传入工厂类的参数,不关心如何创建对象的逻辑

案例

image

public interface Car {
    void name();
}

// 产品1
public class Tesla implements Car {
    @Override
    public void name() {
        System.out.println("特斯拉");
    }
}

// 产品1
public class WuLing implements Car {
    @Override
    public void name() {
        System.out.println("五菱");
    }
}

// 当我们再添加一个产品,要修改CarFactory中的代码,违反了开闭原则
public class CarFactory {

    public static Car getCar(String car){
        if (car.equals("五菱")){
            return new WuLing();
        } else if (car.equals("特斯拉")){
            return new Tesla();
        } else {
            return null;
        }
    }
    
}


public class Consumer {

    public static void main(String[] args){
        // 使用new创建对象
//        Car car1 = new Tesla();
//        Car car2 = new WuLing();

        // 通过简单工厂模式创建
        Car car1 = CarFactory.getCar("五菱");
        Car car2 = CarFactory.getCar("特斯拉");

        car1.name();
        car2.name();

    }

}

工厂方法模式

用来生产同一等级结构中的固定产品(支持增加任意产品)

案例

image

public interface Car {

    void name();

}

// 工厂方法
public interface CarFactory {

    Car getCar();

}

public class BaoMa implements Car {
    @Override
    public void name() {
        System.out.println("宝马");
    }
}
public class BaoMaFactory implements CarFactory {
    @Override
    public Car getCar() {
        return new BaoMa();
    }
}

public class Tesla implements Car {
    @Override
    public void name() {
        System.out.println("特斯拉");
    }
}
public class TeslaFactory implements CarFactory {
    @Override
    public Car getCar() {
        return new Tesla();
    }
}

public class WuLing implements Car {
    @Override
    public void name() {
        System.out.println("五菱");
    }
}
public class WuLingFactory implements CarFactory{
    @Override
    public Car getCar() {
        return new WuLing();
    }
}

public class Consumer {

    public static void main(String[] args){

        // 通过工厂方法模式创建
        Car car1 = new WuLingFactory().getCar();
        Car car2 = new TeslaFactory().getCar();

        // 添加新的产品,不需要修改之前的代码
        Car car3 = new BaoMaFactory().getCar();

        car1.name();
        car2.name();
        car3.name();
    }

}

抽象工厂模式

抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的类

image

适用场景

  • 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节

  • 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量的重复代码

  • 提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现

优点

  • 具体产品在应用层的代码隔离,无需关心创建的细节
  • 将一个系列的产品统一到一起创建

缺点

  • 规定了所有可能被创建的产品集合,产品簇中扩展新的产品困难
  • 增加了系统的抽象性和理解难度

案例

image

public interface IPhoneProduct {

    void start();
    void shutdown();
    void callUp();
    void sendEmail();

}

public interface IRouterProduct {

    void start();
    void shutdown();
    void setWife();
    void setting();

}

// 抽象产品工厂
public interface ProductFactory {

    // 生产手机
    IPhoneProduct iphoneProduct();

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

}


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 sendEmail() {
        System.out.println("小米手机 发短信");
    }
}


public class HuaweiiPhone 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 sendEmail() {
        System.out.println("华为手机 发短信");
    }
}

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

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

    @Override
    public void setWife() {
        System.out.println("小米路由器 设置wife");
    }

    @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 setWife() {
        System.out.println("华为路由器 设置wife");
    }

    @Override
    public void setting() {
        System.out.println("华为路由器 相关设置");
    }
}

public class XiaomiProductFactory implements ProductFactory {
    @Override
    public IPhoneProduct iphoneProduct() {
        return new XiaomiPhone();
    }

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

public class HuaweiProductFactory implements ProductFactory {
    @Override
    public IPhoneProduct iphoneProduct() {
        return new HuaweiiPhone();
    }

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


// 测试
public class Client {

    public static void main(String[] args){

        System.out.println("===== 小米系列产品 =====");
        XiaomiProductFactory xiaomiProductFactory = new XiaomiProductFactory();

        IPhoneProduct iPhoneProduct = xiaomiProductFactory.iphoneProduct();
        iPhoneProduct.start();
        iPhoneProduct.callUp();
        iPhoneProduct.sendEmail();

        IRouterProduct routerProduct = xiaomiProductFactory.iRouterProduct();
        routerProduct.start();
        routerProduct.setWife();
        routerProduct.setting();


        System.out.println("===== 华为系列产品 =====");
        HuaweiProductFactory huaweiProductFactory = new HuaweiProductFactory();

        IPhoneProduct iPhoneProduct2 = huaweiProductFactory.iphoneProduct();
        iPhoneProduct2.start();
        iPhoneProduct2.callUp();
        iPhoneProduct2.sendEmail();

        IRouterProduct routerProduct2 = huaweiProductFactory.iRouterProduct();
        routerProduct2.start();
        routerProduct2.setWife();
        routerProduct2.setting();


    }

}

image

小结

  • 简单工厂模式(静态工厂模式)
    虽然某种程度上不符合设计原则,但实际使用最多
  • 工厂方法模式
    不修改已有类的前提下,通过增加新的工厂类实现扩展。
  • 抽象工厂模式
    不可以增加产品,可以增加产品族