最简单java设计模式:工厂方法模式

前言

在前一篇文章讲解了一下简单工厂模式,在上篇文章中,我们也讲到了简单工厂模式的缺点,就是不满足开闭原则,这对于软件的设计来说,是不太好的,而下面讲解的工厂方法模式,正是为了弥补简单工厂模式的缺点,也可以说是简单工厂模式的改进版。

一、什么是工厂方法模式

工厂方法模式同样属于类的创建型模式又被称为多态工厂模式 。工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系
统在不修改具体工厂角色的情况下引进新的产品。

二、工厂方法模式的角色和职责

1.抽象工厂(Creator)角色 工厂方法模式的核心,任何工厂类都必须实现这个接口。

2.具体工厂( Concrete Creator)角色 具体工厂类是抽象工厂的一个实现,负责实例化产品对象。

3.抽象(Product)角色 工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

4.具体产品(Concrete Product)角色 工厂方法模式所创建的具体实例对象

三、工厂方法模式的UML图

这里写图片描述

  • sports:抽象角色

  • Basketball和Football:具体产品角色

  • sportsFactory:抽象工厂角色

  • BasketballFactory和FootballFactory:具体工厂角色

四、工厂方法模式代码

这个例子和简单工厂方法模式一样,用运动作为抽象角色,足球和篮球作为具体的产品角色来讲解,下面看具体代码。

首先我们创建一个抽象类sports,同时有一个运动的方法

public interface Sports {
    /*
     * 运动
     */
    public void play();
}

然后,定义了一个足球类篮球类,同样有运动方法


public class Basketball implements Sports{
    /*
     * 运动
     */
    public void play(){
        System.out.println("打篮球...");
    }
}

public class Football implements Sports{
    /*
     * 运动
     */
    public void play(){
        System.out.println("踢足球啦...");
    }
}

最后写一个工厂类,用来创造足球运动篮球运动

下面我们来更改简单工厂模式的代码,逐步的改为工厂方法模式

4.1、抽象工厂接口

public interface SportsFactory {

    /*
     * get方法,获得所有产品对象
     */
    public Sports getSports();

}

这里和简单工厂模式不同,我们先需要一个抽象工厂接口,然后将具体的工厂实现到具体的子类中,这样就能够符合开闭原则

4.2、篮球具体工厂

public class BasketballFactory implements SportsFactory{

    @Override
    public Sports getSports() {

        return new Basketball();
    }

}

4.3、足球具体工厂


public class FootballFactory implements SportsFactory {

    @Override
    public Sports getSports() {
        return new Football();
    }

}

这样就将具体的不同产品的实现,放到了具体的工厂来实现,当我们再增加其他的具体的产品时,只需要再增加一个具体的产品的工厂类,而不需要去改变原有的代码,所以符合对扩展开放的思想。

五、测试


public class MainClass {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {

        //创建篮球工厂
        SportsFactory basketballFactory = new BasketballFactory();

        Sports basketball = basketballFactory.getSports();
        basketball.play();

        //创建足球工厂
        SportsFactory footballFactory = new FootballFactory();

        Sports football = footballFactory.getSports();
        football.play();

    }
}

运行结果:
这里写图片描述

六、工厂方法模式的优缺点

工厂方法模式的优点

在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。

基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。

使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

工厂方法模式的缺点

在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。

由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

七、适用场景

一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。

一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。

将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

八、工厂方法模式和简单工厂模式比较

工厂方法模式简单工厂模式在结构上的不同不是很明显。工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。

工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。 当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也
不需要修改客户端,很好的符合了“开放-封闭”原则。

简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。

工厂方法模式退化后可以演变成简单工厂模式。

猜你喜欢

转载自blog.csdn.net/sihai12345/article/details/81584922