工厂三兄弟之简单工厂模式
模式定义:
简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的 实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是 静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属 于类创建型模式。
多读几遍定义 然后我们来看下它的结构:
简单工厂模式的要点在于:当你需要什么,只需要传入一个正确的参数,就可以获取你所需 要的对象,而无须知道其创建细节。
来来来 举个栗子:
Sunny软件公司欲基于Java语言开发一套图表库,该图表库可以为应用系统提供各种不同外观 的图表,例如柱状图、饼状图、折线图等。Sunny软件公司图表库设计人员希望为应用系统开 发人员提供一套灵活易用的图表库,而且可以较为方便地对图表库进行扩展,以便能够在将 来增加一些新类型的图表。
然后程序员出了个设计方案,并将图表的实现代码封装在Chart类中:
|
客户端代码通过调用Chart类的构造函数来创建图表对象,根据参数type的不同可以得到不同 类型的图表,然后再调用display()方法来显示相应的图表。
不难看出,Chart类是一个“巨大的”类,在该类的设计中存在如下几个问题:
(1) 在Chart类中包含很多“if…else…”代码块,整个类的代码相当冗长,代码越长,阅读难度、 维护难度和测试难度也越大;而且大量条件语句的存在还将影响系统的性能,程序在执行过 程中需要做大量的条件判断。
(2) Chart类的职责过重,它负责初始化和显示所有的图表对象,将各种图表对象的初始化代码 和显示代码集中在一个类中实现,违反了“单一职责原则”,不利于类的重用和维护;而且将大 量的对象初始化代码都写在构造函数中将导致构造函数非常庞大,对象在创建时需要进行条 件判断,降低了对象创建的效率。
(3) 当需要增加新类型的图表时,必须修改Chart类的源代码,违反了“开闭原则”。
(4) 客户端只能通过new关键字来直接创建Chart对象,Chart类与客户端类耦合度较高,对象的 创建和使用无法分离。
(5) 客户端在创建Chart对象之前可能还需要进行大量初始化设置,例如设置柱状图的颜色、高 度等,如果在Chart类的构造函数中没有提供一个默认设置,那就只能由客户端来完成初始设 置,这些代码在每次创建Chart对象时都会出现,导致代码的重复。
面对这种如此巨大、职责如此重,且与客户端代码耦合度非常高的类,我们应该怎么办?
先上代码 看看我们用简单工厂模式改造后的效果:
|
现在的代码结构:
是不是对强迫症很治愈!!!当我们需要切换实例时唯一的改动只是客户端的入参:
chart = ChartFactory.getChart("pie");
但是还是有改动,不符合开闭原则了,我要换图表还是要改客户端的代码。这时候我们的解决办法是将静态工厂方法的参数存储在properties中然后在程序中引用它:
String type = XMLUtil.getChartType(); //读取配置文件中的参数
chart = ChartFactory.getChart(type); //创建产品对象
至此简单工厂模式的设计demo就讲完了。
下面我们分析下这种模式:
简单工厂模式的优点:
1.客户端免除了创建产品对象的职责,仅仅是“消费“产品,实现了对象和使用的分离;
2.客户端无需知道具体产品类的类名,只需知道对应产品的对应入参,减少记忆量;
3.通过引入配置文件可以不修改客户端的情况下更换产品,提高灵活性;
缺点:
1.工厂类集中了所有产品的创建逻辑,职责过重;
2.式势必会增加系统中类的个数,增加了系统的复杂 度和理解难度;
3. 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成 工厂逻辑过于复杂,不利于系统的扩展和维护。
4.由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
适用场景:
(1) 工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太 过复杂。
(2) 客户端只知道传入工厂类的参数,对于如何创建对象并不关心。
来来思考下为啥静态?
static方法可以通过类名访问,也可以通过类的实例访问。
static方法不能访问类中非static的数据。
比如
class A { static void F(){} };
在main函数中可以
A a;
a.F();
也可以 A.F();
普通方法又叫实例方法,只能通过类的实例访问。
他只能a.F();
一个JAVA类被加载的顺序:
1.加载静态成员、代码块
2.加载非静态成员、代码块
3.调用构造方法。
其实不用静态方法也可以,只是用静态方法之后,就不用初始化工厂而直接得到产品。