工厂模式

工厂模式

介绍

作用

实现了创建者和调用者的分离

OPP七大原则

  • 开闭原则:一个软件的实体应当对扩展开放,对修改关闭
  • 依赖倒转原则:要针对接口编程,不要针对实现编程
  • 迪米特法则:只要与你直接的朋友通信,而避免和陌生人通信

核心本质

  • 实例化对象不使用 new ,而用工厂方法代替
  • 将选择实现类,创建对象统一管理和控制,从而将调用者跟我们的实现类分离

三种模式

  • 简单工厂模式:用来生产同一等级结构中的任意产品(对于增加新的产品,需要扩展已有代码)
  • 工厂方法模式:用来生产统一等级结构中的固定产品(支持增加任意产品)
  • 抽象工厂模式:围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。

应用场景

  • JDK中Calendar的getInstance()方法
  • JDBC中的Connection对象的获取
  • Spring中IOC容器创建管理bean对象
  • 反射中Class对象的newInstance()方法

简单(静态)工厂模式

假设有一个消费者买车场景,定义一个Car接口:

package simple;

public interface Car {
    void name();
}

然后分别由五零宏光和特斯拉两款车:

package simple;

public class WuLing implements Car {
    @Override
    public void name() {
        System.out.println("五菱宏光");
    }
}
package simple;

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

普通情况下,消费者买车要用 new 去实例化某款车的类,再调用车的name()方法:

package simple;

public class Consumer {
    public static void main(String[] args) {
        // 接口,所有的实现类!
        Car car = new WuLing();
        Car car2 = new Tesla();

        car.name();
        car2.name();
    }
}

而使用简单工厂模式下,定义一个 CarFactory 类,去代替 Consumer 去执行 new 这个操作:

package simple;

// 静态工厂模式
//增加一个新的产品,如果不修改代码,做不到

// 开闭原则
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 static Car getWuLing(){
        return new WuLing();
    }
    public static Car getTesla(){
        return new Tesla();
    }
}

此时,Consumer 只需调用 CarFactory 里面的方法即可得到对应 Car 的实例:

package simple;

public class Consumer {
    public static void main(String[] args) {
        // 接口,所有的实现类!
//        Car car = new WuLing();
//        Car car2 = new Tesla();

        // 使用工厂
        // 方法一
        Car car = CarFactory.getCar("五菱");
        Car car2 = CarFactory.getCar("特斯拉");
        // 方法二
        Car car = CarFactory.getWuLing();
        Car car2 = CarFactory.getTesla();
        car.name();
        car2.name();
    }
}
image-20220314114619706

缺点:当我们想要增加一个Car的实现类的时候,还需要去CarFactory去增加里面的代码。

工厂方法模式

接着上面的Consumer买车的例子,现在想增加一个大众品牌的车,为了避免简单工厂模式需要去修改CarFactory,这里使用工厂方法。

这里把CarFactory也定义为接口:

package method;

public interface CarFactory {
    Car getCar();
}

各自品牌的Factory去实现这个CarFactory接口,如TeslaFactory:

package method;

public class TeslaFactory implements CarFactory{
    @Override
    public Car getCar() {
        return new Tesla();
    }
}

其他车的Factory也一样,这时候Consumer通过对应品牌车的Factory去获取各品牌车的实例:

package method;

public class Consumer {
    public static void main(String[] args) {
        Car car = new WuLingFactory().getCar();
        Car car2 = new TeslaFactory().getCar();

        car.name();
        car2.name();
    }
}

加入我们想加入大众品牌车,就只需要去新建一个DaZhongFactory类去实现CarFactory这个接口,无需去修改CarFactory里面的代码,从而遵循了开闭原则。

image-20220314114128625

抽象工厂模式

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

适用场景:

  • 客户端(应用层)不依赖于产品实例如何被创建、实现等细节
  • 强调一系列相关产品对象(属于统一产品族)一起使用创建对象需要大量的重复代码
  • 提供一个产品类的库,所有的产品以供养的接口出现,从而使得客户端不依赖于具体的实现

优点:

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

缺点:

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

现在定义手机和路由器的产品接口:

package abstract1;

// 手机产品接口
public interface IPhoneProduct {
    void start();
    void shutdown();
    void callup();
    void sendSMS();
}
package abstract1;

// 路由器产品接口
public interface IRouterProduct {
    void start();
    void shutdown();
    void openwifi();
    void setting();
}

然后又小米对应的手机和路由器的实现类:(华为同理)

package abstract1;

// 小米手机
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("小米发短信");
    }
}
package abstract1;

// 小米路由器
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("小米设置");
    }
}

再定义一个产品工厂接口,里面由手机和路由器两款产品:

package abstract1;

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

    // 生成手机
    IPhoneProduct phoneProduct();

    IRouterProduct routerProduct();
}

然后就是小米的工厂:(华为同理)

package abstract1;

public class XiaomiFactory implements IProductFactory{
    @Override
    public IPhoneProduct phoneProduct() {
        return new XiaomiPhone();
    }

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

最后客户端像获取某品牌的产品对象,只需要去对应品牌的工厂那里使用相应的函数即可:

package abstract1;

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

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

        IPhoneProduct xiaomiPhoneProduct = xiaomiFactory.phoneProduct();
        xiaomiPhoneProduct.callup();
        xiaomiPhoneProduct.sendSMS();

        IRouterProduct xiaomiRouterProduct = xiaomiFactory.routerProduct();
        xiaomiRouterProduct.openwifi();
        xiaomiRouterProduct.setting();


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

        IPhoneProduct huaweiPhoneProduct = huaweiFactory.phoneProduct();
        huaweiPhoneProduct.callup();
        huaweiPhoneProduct.sendSMS();

        IRouterProduct huaweiRouterProduct = huaweiFactory.routerProduct();
        huaweiRouterProduct.openwifi();
        huaweiRouterProduct.setting();
    }
}

当需要新增一个产品族的时候需要不同的产品实现类、产品工厂接口和不同品牌工厂实现类都进行修改,十分麻烦,因此抽线工厂模式适用于产品族稳定的情形。

总结

简单工厂模式:虽然某种程度上不符合设计原则,但实际使用最多

工厂方法模式:不修改已有类的前提下,通过增加新的工厂类实现扩展

抽象工厂模式:不可以增加产品,可以增加产品族

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇