Java设计模式 - 工厂模式(简单工厂,工厂方法,抽象工厂)

一、什么是工厂模式

工厂模式:工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式,工厂模式在Java程序中可以说是随处可见。

二、三种工厂模式的区别

模式解释
简单工厂用来生产同一等级结构中的任意产品。
工厂方法用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)

这三种工厂模式在设计模式的分类中都属于创建型模式

三、三种工厂模式

1、简单工厂模式

简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

1、Java代码实现:

水果类:

@Data
public class Fruit {
    private final String name;

    public Fruit(String name) {
        this.name = name;
    }
}
public class Orange extends Fruit {
    public Orange() {
        super("橘子1");
    }
}
public class Apple extends Fruit {
    public Apple() {
        super("苹果1");
    }
}

水果工厂:

public class FruitFactory {
    public static Fruit getFruit(String type){
        switch (type) {
            case "苹果":
                return new Apple();
            case "橘子":
                return new Orange();
            default:
                return null;
        }
    }

}

测试类:

public class Test {
    public static void main(String[] args) {
        // 直接问工厂要,而不是自己去创建
        Apple apple = (Apple) FruitFactory.getFruit("苹果");
        Orange orange = (Orange) FruitFactory.getFruit("橘子");
        System.out.println(apple.getName());
        System.out.println(orange.getName());
    }
}

2、优缺点:

优点:

1、将创建实例得工作与使用实例得工作分开,使用者不必关心类对象如何创建,实现了解耦;
2、把初始化实例时得工作放到工厂里进行,使代码更容易维护。

缺点:

1、工厂类集中了所有实例(产品)得创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响;
2、违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类得逻辑,这样就会造成工厂逻辑过于复杂。
3、简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承得等级结构。

3、应用场景

1.客户如果只知道传入工厂类得参数,对于如何创建对象得逻辑不关心时;
2.客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应得参数
3.当工厂类负责创建得对象具体产品比较少时,由于创建得对象较少,不会造成工厂方法中得业务逻辑太过复杂。

2、工厂方法模式

工厂方法模式:定义一个创建对象的的抽象方法,由子类决定要实例化的类,工厂方法模式将对象的实例化推迟到子类。
工厂方法模式用途:工厂方法模式和简单工厂模式虽然都是通过工厂来创建对象,他们之间最大的不同是——工厂方法模式在设计上完全完全符合“开闭原则”。

1、Java代码实现

业务接口:

public interface User {
    void getUser();
}

实现类:

public class OneUser implements User{
    public void getUser() {
        System.out.println("用户1的信息");
    }
}
public class TwoUser implements User{
    public void getUser() {
        System.out.println("用户2的信息");
    }
}

用户工厂:

public class UserFactory {
    public User getUser(String userType){
    if(userType.equalsIgnoreCase("one")) {
        return new OneUser();
    } else if(userType.equalsIgnoreCase("two")) {
        return new TwoUser();
    }
    return null;
    }
}

测试类:

public class TestUser {
    public static void main(String[] args) {
        UserFactory userFactory=new UserFactory();
        User one = userFactory.getUser("one");
        one.getUser();
    }
}

2、优缺点

优点:

工厂方法模式是为了克服简单工厂模式的缺点(主要是为了满足OCP)而设计出来的

缺点:

每增加一个产品,相应的也要增加一个子工厂,会加大了额外的开发量

3、应用场景

当一个类不知道它所必须创建对象的类或一个类希望由子类来指定它所创建的对象时,当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候,可以使用工厂方法,支持多扩展少修改的OCP原则。

3、抽象工厂模式

抽象工厂:抽象工厂是指一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象。

在工厂方法模式中,我们使用一个工厂创建一个产品,一个具体工厂对应一个具体产品,但有时候我们需要一个工厂能够提供多个产品对象,而不是单一的对象,这个时候我们就需要使用抽象工厂模式。

用来生产不同产品族的全部产品。(增加新产品时,需要修改工厂,增加产品族时,需要增加工厂。符合单一职责原则,部分符合开放-封闭原则,降低了复杂性)

1、Java代码实现

实体类:

//水果
@Data
public class Fruit {
    private final String name;

    public Fruit(String name) {
        this.name = name;
    }
}
//苹果
public class Apple extends Fruit {
    public Apple() {
        super("苹果1");
    }
}
//橘子
public class Orange extends Fruit {
    public Orange() {
        super("橘子1");
    }
}

抽象水果工厂:

public abstract class FruitFactory<T extends Fruit> {
    /**
     * 不同的水果工厂,通过此方法生产不同的水果
     */
    public abstract T getFruit();

}

苹果工厂:

public class AppleFactory extends FruitFactory<Apple> {
    /**
     * 获取苹果对象
     *
     * @return
     */
    @Override
    public Apple getFruit() {
        return new Apple();
    }
}

橘子工厂:

public class OrangeFactory extends FruitFactory<Orange> {
    /**
     * 获取橘子对象
     *
     * @return 橘子对象
     */
    @Override
    public Orange getFruit() {
        return new Orange();
    }
}

测试类:

public class Test1 {
    public static void main(String[] args) {
        Apple apple = new AppleFactory().getFruit();
        Orange orange = new OrangeFactory().getFruit();
        System.out.println(apple.getName());
        System.out.println(orange.getName());

    }
}

2、优缺点

优点:

1、抽象工厂模式主要在于应对“新系列”的需求变化。
2、隔离了具体类的生成,使得客户并不需要知道什么被创建
3、每次可以通过具体工厂类创建一个产品族中的多个对象,增加或者替换产品族比较方便,增加新的具体工厂和产品族很方便;

缺点:

增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性。

3、应用场景

这个系统有多于一个的产品族,而系统只消费其中某一产品族。同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。


其实,无论是简单工厂模式、工厂模式还是抽象工厂模式,它们本质上都是将不变的部分提取出来,将可变的部分留作接口,以达到最大程度上的复用。究竟用哪种设计模式更适合,这要根据具体的业务需求来决定。


版权声明:本文为weixin_44147682原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。