源码分析设计模式之工厂模式(一、简单工厂模式)

我们开发过程中经常听到工厂这个词,工厂顾名思义就是创建产品。根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式抽象工厂模式。该模式用于封装和管理对象的创建

在实际工作中简单工厂用的是比较多的。工厂方法模式抽象工厂模式是 GoF23 种设计模式中的一种,而常使用的简单工厂并不是一种设计模式,可以说是我们自己的一种俗称
/* ----------------------- 服务端 ----------------------- */
/**
 * 抽象产品
 */
interface Food {
    
    
    void production();
}

/**
 * 具体产品
 */
class HanBao implements Food {
    
    
    @Override
    public void production() {
    
    
        System.out.println("生产的汉堡包咯");
    }
}
/* ----------------------- 服务端 ----------------------- */
/* ----------------------- 客户端 ----------------------- */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Food food = new HanBao(); 	// 向上造型
        food.production();
    }
}
/* ----------------------- 客户端 ----------------------- */

上述代码一般是我们在写代码时候会写的样子,可是这样的设计是相当脆弱的,因为一旦服务端修改了具体产品类名,那么客户端也要随之改变,这样的代码会使服务器端代码和客户端代码是耦合的,这样就违反了设计原则中的依赖倒置原则

那么如何改善它呢,既然是耦合的,那么改善方法就是常见也常说的解耦:无论服务端代码怎么样的修改都不会影响到客户端,客户端并不需要关注服务端的变化

一、简单工厂模式

1、定义:定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类

2、在简单工厂模式中用于被创建实例的方法通常为静态(static)方法,因此简单工厂模式又被成为静态工厂方法(Static Factory Method)

3、只需要传入一个正确的参数,就可以获取所需要的对象,而无需知道其实现过程

就好比,我想吃汉堡包,而肯德基有,我们只需要报上汉堡包即可(当然是要付钱的哈),这个时候,肯德基就可以看做工厂(Factory),而生产出来的汉堡包被称之为产品(Product),汉堡包的名称则被称之为参数,工厂可以根据参数的不同返回不同的产品,这就是简单工厂模式

/* ----------------------- 服务端 ----------------------- */
/**
 * 抽象产品
 */
interface Food {
    
    
    void production();
}

/**
 * 具体产品
 */
class HanBao implements Food {
    
    
    @Override
    public void production() {
    
    
        System.out.println("生产的汉堡包咯");
    }
}

class Xiaolongxia implements Food {
    
    
    @Override
    public void production() {
    
    
        System.out.println("生产的小龙虾咯");
    }
}

/**
 * 食物工厂
 */
class FoodFactory {
    
    
    public static Food getFood(String name) {
    
    
        Food food = null;
        switch (name) {
    
    
            case "汉堡包":
                food = new HanBao();
                break;
            case "小龙虾":
                food = new Xiaolongxia();
                break;
        }
        return food;
    }
}
/* ----------------------- 服务端 ----------------------- */
/* ----------------------- 客户端 ----------------------- */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Food food = FoodFactory.getFood("汉堡包");
        food.production();
        food = FoodFactory.getFood("小龙虾");
        food.production();
    }
}
/* ----------------------- 客户端 ----------------------- */
这个时候服务端的改变并不会影响客户端的运行,思维导图:

在这里插入图片描述

简单工厂模式的优点:
  • 具体产品的类型从客户端中脱离出来了,这个时候客户端无需知道所创建的产品类型,只需要知道参数即可
  • 服务端修改具体产品类名,客户端并不知道,这便符合了面向接口编程的思想
  • 工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象
  • 客户端免除了直接创建产品对象的职责
简单工厂模式的缺点:
  • 我们需要记住参数与具体产品的对应关系
  • 由于简单工厂模式的具体产品是基于一个共同的抽象类或者接口,这样一来,一但产品的种类增加,即有不同的产品接口或者抽象类的时候,工厂类就需要判断何时创建何种种类的产品,这就和创建何种种类产品的产品相互混淆在了一起,这样也就违背了设计原则中的单一职责,导致系统丧失灵活性和可维护性
  • 当我需要新增加一个产品,这个时候就必须要修改工厂类,这样一来简单工厂模式违背了设计原则中的开封原则 ,也就是违背了 “系统对扩展开放,对修改关闭”
  • 由于工厂类集中了所有实例的创建逻辑,这就直接导致一旦这个工厂出了问题,所有的客户端都会受到牵连
  • 简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构
  • 丢失原始类型,因为引用类型永远都是接口或者抽象类
虽然简单工厂模式的缺点挺多,但还是有应用场景的: JDK 中 Calendar 日期类

在这里插入图片描述

那么如何解决简单工厂模式所带来的缺点呢,工厂方法模式就要登场啦

Guess you like

Origin blog.csdn.net/qq_39249094/article/details/117330697