工厂模式
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
介绍
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时。
如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
关键代码:创建过程在其子类执行。
应用实例: 1、您需要一台电脑,可以直接从工厂里面提货,而不用去管台电脑是怎么做出来的,以及这台电脑里面的具体实现。
优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
简单工厂模式
1、首先我们创建一个抽象产品类接口Computer.java,它是工厂类所创建的所有产品对象的父类,所创建的具体产品对象都是其子类对象;
package factory;
/**
* 抽象接口
* @author wf
*/
public interface Computer {
void creatComputer();
}
2、然后我们创建具体产品类DellComputer.java,HaseeComputer.java,LenovoComputer.java,它们是简单工厂模式的创建目标,也是抽象产品接口的子类;
package factory;
/**
* Dell电脑
* @author wf
*/
public class DellComputer implements Computer {
@Override
public void creatComputer() {
System.out.println("Create a dell computer...");
}
}
package factory;
/**
* Hasee电脑
* @author wf
*/
public class HaseeComputer implements Computer {
@Override
public void creatComputer() {
System.out.println("CreateFactory a hasee computer...");
}
}
package factory;
/**
* Lenovo电脑
* @author wf
*/
public class LenovoComputer implements Computer {
@Override
public void creatComputer() {
System.out.println("CreateFactory a lenovo computer...");
}
}
3、准备工作做好后,我们开始创建工厂角色CreateFactory .java,工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象;
package factory;
/**
* 根据传进来的参数的产品类型来 生产/创建 真实的产品实体对象
* @author wf
*/
public class CreateFactory {
public static Computer createComputer(String type) {
if(type.equals("dellcomputer"))
return new DellComputer();
else if (type.equals("haseecomputer"))
return new HaseeComputer();
else if(type.equals("lenovocomputer"))
return new LenovoComputer();
else System.out.println("no "+type +" computer");
return null;
}
}
4、客户端调用工厂类静态方法创建产品:Client.java
package factory;
public class Client {
public static void main(String[] args)
{
Computer computer = CreateFactory.createComputer("haseecomputer");
computer.creatComputer();
}
}
输出为:CreateFactory a hasee computer…
简单工厂类负责了所有产品的创建逻辑,当我们需要新引进一个新产品时,就不得不修改工厂类的产品创建逻辑,在产品类型较多时有可能会造成工厂类的产品创建逻辑过于负责,违背了java设计原则的开-闭原则,不利于系统的维护性和扩展性;
为了解决上面的问题,下面我们介绍工厂模式的第二种,工厂方法模式。
工厂方法模式
工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。工厂方法模式将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类。解决了简单工厂模式中一旦需要生产新产品就需要修改工厂类的方法逻辑的问题。
1、首先我们要创造抽象工厂类AbstractFactory.java,定义具体工厂的公共接口
package factory;
/**
* 抽象工厂类,定义具体工厂的公共接口
* @author wf
*/
public interface AbstractFactory {
public Computer computerFactory();
}
2、创建抽象产品类Computer.java ,定义具体产品的公共接口
package factory;
/**
* 抽象产品类,定义具体产品的公共接口
* @author wf
*/
public interface Computer {
void creatComputer();
}
3、创建具体产品类(继承抽象产品类)DellComputer.java,HaseeComputer.java,LenovoComputer.java, 定义生产的具体产品,以下不一一列出
package factory;
/**
* Dell电脑
* @author wf
*/
public class DellComputer implements Computer {
@Override
public void creatComputer() {
System.out.println("Create a dell computer...");
}
}
4、创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
package factory;
public class DellComputerFactory implements AbstractFactory {
@Override
public Computer computerFactory() {
return new DellComputer();
}
}
5、外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例
package factory;
public class Client {
public static void main(String[] args)
{
DellComputerFactory dellComputerFactory = new DellComputerFactory();
dellComputerFactory.computerFactory().creatComputer();
}
}
输出:Create a dell computer…
优点:
更符合开-闭原则
新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可
符合单一职责原则
每个具体工厂类只负责创建对应的产品
工厂方法模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现。
抽象工厂模式
我们在生产电脑的时候,不同电脑的配置都不同,CPU、主板等配件也不同,这时我们就要用到抽象工厂模式,与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品。
参与者
(1) AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。如上图UML类图中的Factory。
(2) ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。如上图UML类图中的DellComputerFactory和HaseeComputerFactory。
(3) AbstractProduct(抽象产品):它为每种产品声明接口,如上图UML类图中的CPU和MainBoard。
(4) ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。如上图UML类图中的InterCPU,InterMainBorad,AMDCpu,AMDBoard。
为了方便理解,我们在上述的基础上进行修改
1、两种产品类接口: Cpu.java,MainBoard.java
package factory;
/**
* 主板
*/
public interface Cpu{
}
package factory;
/**
* 主板
*/
public interface MainBoard {
}
2、具体产品类AMDCpu.java,AMDMainBoard,InterCpu.java,InterMainBoard.java
package factory;
/**
* InterCPU
*/
public class InterCpu implements Cpu {
public InterCpu()
{
System.out.println("Create a InterCpu");
}
}
package factory;
/**
* Inter主板
*/
public class InterMainBoard implements MainBoard {
public InterMainBoard()
{
System.out.println("Create a nterMainBoard...");
}
}
package factory;
/**
* AMDCPU
*/
public class AMDCpu implements Cpu {
public AMDCpu()
{
System.out.println("Create a AMDCpu");
}
}
package factory;
/**
* AMD主板
*/
public class AMDMainBoard implements MainBoard {
public AMDMainBoard()
{
System.out.println("Create a AMDMainBoard...");
}
}
3、抽象工厂类AbstractFactory .java
package factory;
/**
* 抽象工厂类,定义具体工厂的公共接口
* @author wf
*/
public interface AbstractFactory {
public Computer computerFactory();
public Cpu createCpu();
public MainBoard createMainBoard();
}
4、具体工厂类,只负责生产所需产品
package factory;
public class DellComputerFactory implements AbstractFactory {
@Override
public Computer computerFactory() {
return new DellComputer();
}
@Override
public Cpu createCpu() {
return new InterCpu();
}
@Override
public MainBoard createMainBoard() {
return new InterMainBoard();
}
}
5、生产电脑
package factory;
public class Client {
public static void main(String[] args)
{
AbstractFactory factory=null;
factory = new DellComputerFactory();
factory.createCpu();
factory.createMainBoard();
factory.computerFactory().creatComputer();
}
}
输出:
Create a InterCpu
Create a InterMainBoard…
Create a dell computer…
、抽象工厂模式是工厂方法模式的进一步延伸。在抽象工厂模式中,增加新的产品族很方便,但是增加新的产品等级结构很麻烦。
总体来说,工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。在以上的三种模式中,第一种如果传入的字符串有误,不能正确创建对象,第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式。