动机
考虑一个简单的场景,不同的动物有不同的叫声(如狗叫是“汪汪汪”,猫叫是“喵喵喵”等),这些狗、猫等等动物都来源于动物这个基类,只是每个动物的叫声不同。不需要知道这具体是什么叫声,只需要知道是什么动物,就可知道每个动物是什么叫声。此时,就可以使用简单工厂模式。
概述
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
角色
简单工厂模式具有如下角色:
- Factory:工厂角色–创建实例对象,可以被外部直接调用
- 工厂角色负责实现创建所有实例的的内部逻辑。
- Product:抽象产品角色–公共接口
- 抽象产品角色是所创建的所有对象的父类,负责描述所有实例所公有的公共接口。
- Concrete Product:具体产品角色–具体类,实现抽象类中声明的抽象方法
- 具体产品角色是创建目标,所有创建的对象都充当这个角色的某个具体类的实例。
- UML类图
案例
-
实质:简单工厂模式的实质是由一个工厂类根据传入的参数进行判断,动态决定应该创建哪一个类(这些类继承自一个父类或接口)的实例。
-
实现:该案例以动物场景来分析,首先创建一个Animal类作为基类,基类中拥有shout()方法,再创建Dog和Cat类继承Animal父类,最后创建AnimalFactory工厂类,按照传入的参数创建实例。
-
UML类图:
-
案例代码:
-
抽象产品角色(Animal类)
//product abstract class Animal{ public abstract void shout(); }
-
具体产品角色(Dog/Cat类)
//concrete Product class Dog extends Animal{ @Override public void shout() { System.out.println("狗叫 ~~ 汪汪汪"); } } class Cat extends Animal{ @Override public void shout() { System.out.println("猫叫 ~~ 喵喵喵"); } }
-
工厂角色(AnimalFactory类)
//factory class AnimalFactory{ private static Animal animal = null; public static Animal animalShout(String name) { if(name.equals("dog")) { animal = new Dog(); }else if(name.equals("cat")) { animal = new Cat(); } return animal; } }
-
测试类:
/** * 简单工厂模式-动物 * @author kime * */ public class SimpleFactoryAnimal { public static void main(String[] args) { dogShout(); catShout(); } private static void dogShout() { String name = "dog"; animalShout(name); } private static void catShout() { String name = "cat"; animalShout(name); } private static void animalShout(String name) { Animal animal = AnimalFactory.animalShout(name); animal.shout(); } }
-
结果:
-
优点
- 工厂类含有必要的逻辑判断,根据外部传入的参数进行判断决定究竟应该创建哪一个具体类的对象。外部不需要对对象进行负责,只需要了解工厂类即可。
- 外部不需要知道具体产品类的类名,只需要知道具体产品类所对应的参数即可。
- 将对象的创建和对象本身业务处理分离可以降低系统的耦合度,使得两者修改起来都相对容易。
- 在调用工厂类的工厂方法时,由于工厂方法是静态方法,使用起来很方便,可通过类名直接调用,而且只需要传入一个简单的参数即可。
- 在实际开发中,还可以在调用时将所传入的参数保存在XML等格式的配置文件中,修改参数时无须修改任何源代码。
缺点
- 工厂类中的责任相对过重,如果工厂类受到影响,则会牵连到整个系统。
- 在系统复杂起来后,会不断对工厂类添加创建实例的个数,增加了系统的复杂性和理解难度。
- 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类过多的情况下,可能会直接造成逻辑混乱不利于系统的扩展与维护。
场景
在以下情况下可以使用简单工厂模式:
- 工厂类负责创建的对象比较少:工厂类中创建的对象较少,不会出现逻辑混乱的问题。
- 客户端只需要传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。