一、工厂模型的引入:
1、简单概要:
在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new
操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生
成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象。 在这些情况,新对象的建立就是一个 “过程”,不仅是一个
操作,像一部大机器中的一个齿轮传动。你如何能轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程呢?那我们的就
可以建立一个工厂来创建对象。
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的
2、情景模拟:
(1)还没有工厂时代(自给自足):假如还没有工业革命,如果一个客户要一款宝马车,一般的做法是客户去创建一款宝马车,然后拿
来用。
(2)简单工厂模式(一个工厂全搞定):后来出现工业革命。用户不用去创建宝马车。因为客户有一个工厂来帮他创建宝马,想要什么
车,这个工厂就可以建。比如想要320i系列车。工厂就创建这个系列的车即工厂可以创建所有产品。
(3)工厂方法模式时代(不同工厂生产不同产品):为了满足客户,宝马车系列越来越多,如320i,523i,30li等系列一个工厂无法创建
所有的宝马系列。于是由单独分出来多个具体的工厂。每个具体工厂创建一种系列。即具体工厂类只能创建一个具体产品。但是宝马工厂
还是个抽象工厂。你需要指定某个具体的工厂才能生产车出来。
(4)抽象工厂模式时代(不同工厂生产不同版本的产品,产品多元配套):随着客户的要求越来越高,宝马车必须配置空调。不同的工
厂需要生产不同型号的宝马及配套的空调。这就是抽象工厂模式。
二、工厂模式的分类
1、简单工厂模式(Simple Factory):
一个工厂类全搞定,根据需求传入参数即可创建具体产品实例
2、工厂方法模式(Factory Method)
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
3、抽象工厂模式(Abstract Factory)
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
工厂方法模型和抽象工厂模型的区别:
(1)工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
(2)工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
三、简单工厂模型示例:
1.在示例之前先看一下客户在没有工厂的年代,自己创建宝马车然后使用的例子:
(1)示意图如下:
(2)客户类(测试类):Customer.java
package factorymodel.nofactory;
import org.junit.Test;
/**
* @author jwang
* 客户自己创建产品
*/
public class Customer
{
@Test
public void testProduct()
{
BMW320Product bmw320 = new BMW320Product();
bmw320.getBMW320();
BMW510Product bmw510 = new BMW510Product();
bmw510.getBMW510();
}
}
(3)产品类:BMW320Product.java
package factorymodel.nofactory;
public class BMW320Product
{
public void getBMW320()
{
System.out.println("BMW320汽车制造完毕,请使用!");
}
}
(4)产品类:BMW510Product.java
package factorymodel.nofactory;
public class BMW510Product
{
public void getBMW510()
{
System.out.println("BMW510汽车制造完毕,请使用!");
}
}
2.简单工厂模式:
客户需要知道怎么去创建一款车,客户和车就紧密耦合在一起了.为了降低耦合,就出现了工厂类,把创建宝马的操作细节都放到了工厂里面去,客户直接使用工厂的创建工厂方法,传入想要的宝马车型号就行了,而不必去知道创建的细节.这就是工业革命了:简单工厂模式,即我们建立一个工厂类方法来制造新的对象
(1)简单工厂模型示意图:
(1)构建产品接口类:InProduct.java
package factorymodel.simplefactory;
/**
* @author jwang
* 产品接口类
*/
public interface InProduct
{
public void getProduct();
}
(2)构建产品类:BMW320Product.java
package factorymodel.simplefactory;
public class BMW320Product implements InProduct
{
@Override
public void getProduct()
{
System.out.println("BMW320汽车制造完毕,请使用!");
}
}
(3)构建产品类:BMW510Product.java
package factorymodel.simplefactory;
public class BMW510Product implements InProduct
{
@Override
public void getProduct()
{
System.out.println("BMW510汽车制造完毕,请使用!");
}
}
(4)构建简单工厂类:SimpleFactory.java
package factorymodel.simplefactory;
public class SimpleFactory
{
public static InProduct createProduct(String type)
{
switch (type)
{
case "320":
return new BMW320Product();
case "510":
return new BMW510Product();
default:
break;
}
return null;
}
}
(5)构建客户测试类:Customer.java
package factorymodel.simplefactory;
import org.junit.Test;
public class Customer
{
@Test
public void testProduct()
{
InProduct bm320 = SimpleFactory.createProduct("320");
bm320.getProduct();
InProduct bm510 = SimpleFactory.createProduct("510");
bm510.getProduct();
}
}
分析:
简单工厂模式又称静态工厂方法模式。从命名上就可以看出这个模式简单。它存在的目的很简单:定义一个用于创建对象的接口。
先来看看它的组成:
(1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品
(2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
(3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在Java中由一个具体类实现。
下面我们从开闭原则(对扩展开放;对修改封闭)上来分析下简单工厂模式。当客户不再满足现有的车型号的时候,想要一种速度
快的新型车,只要这种车符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。所以对产品部分来说,它是符合开闭
原则的;但是工厂部分好像不太理想,因为每增加一种新型车,都要在工厂类中增加相应的创建业务逻辑(createBMW(int type)方法需
要新增case),这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类或者
上帝类。
我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应
这些产品,所以这可能会把我们的上帝累坏了,也累坏了我们这些程序员。
于是工厂方法模式作为救世主出现了。 工厂类定义成了接口,而每新增的车种类型,就增加该车种类型对应工厂类的实现,这样工厂的设
计就可以扩展了,而不必去修改原来的代码。
3、工厂方法模式
(1)构建产品模型接口:Inproduct.java
package factorymodel.factorymethod;
/**
* @author jwang
* 产品接口类
*/
public interface InProduct
{
public void getProduct();
}
(2)构建产品的实现类:BMW320Product.java
package factorymodel.factorymethod;
public class BMW320Product implements InProduct
{
@Override
public void getProduct()
{
System.out.println("BMW320汽车制造完毕,请使用!");
}
}
(3)构建产品的实现类:BMW510Product.java
package factorymodel.factorymethod;
public class BMW510Product implements InProduct
{
@Override
public void getProduct()
{
System.out.println("BMW510汽车制造完毕,请使用!");
}
}
(4)构建工厂模型接口:InFactoryMethod.java
package factorymodel.factorymethod;
public interface InFactoryMethod
{
public InProduct createProduct();
}
(5)构建工厂实现类1:FactoryMethod1.java
package factorymodel.factorymethod;
public class FactoryMethod1 implements InFactoryMethod
{
@Override
public InProduct createProduct()
{
return new BMW320Product();
}
}
(6)构建工厂实现类2:Factorymethod2.java
package factorymodel.factorymethod;
public class FactoryMethod2 implements InFactoryMethod
{
@Override
public InProduct createProduct()
{
return new BMW510Product();
}
}
(7)构建客户测试类:Customer.java
package factorymodel.factorymethod;
import org.junit.Test;
public class Customer
{
@Test
public void testProduct()
{
InProduct bm320 = new FactoryMethod1().createProduct();
bm320.getProduct();
InProduct bm510 = new FactoryMethod2().createProduct();
bm510.getProduct();
}
}
分析:
工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力
可以由工厂方法模式里不同的工厂子类来分担。
工厂方法模式组成:
(1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它
由抽象类或者接口来实现。
(2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
(3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
(4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压
力;而且这样使得结构变得灵活 起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被
客户使用,而不必去修改任何已有 的代码。可以看出工厂角色的结构也是符合开闭原则的!
4.抽象工厂模型:
(1)示意图:
(2)产品A的接口模型类:
package factorymodel.abatractfactory;
/**
* @author jwang
* 这是A产品的顶层接口模型类
*/
public interface ProductA
{
public void method1();
public void method2();
}
(3)产品A的第一个版本的实现类:
package factorymodel.abatractfactory;
/**
* @author jwang
* 这是A产品的第一个版本的实现类
*/
public class ProductA1 implements ProductA
{
@Override
public void method1()
{
System.out.println("ProductA1产品已经生产,产品对象的method1方法正在被调用!");
}
@Override
public void method2()
{
System.out.println("ProductA1产品已经生产,产品对象的method2方法正在被调用!");
}
}
(4)产品A的第二个版本的实现类:
package factorymodel.abatractfactory;
/**
* @author jwang
* 这是A产品的第二个版本的实现类
*/
public class ProductA2 implements ProductA
{
@Override
public void method1()
{
System.out.println("ProductA2产品已经生产,产品对象的method1方法正在被调用!");
}
@Override
public void method2()
{
System.out.println("ProductA2产品已经生产,产品对象的method2方法正在被调用!");
}
}
(5)产品B的接口模型类:
package factorymodel.abatractfactory;
/**
* @author jwang
* 这是B产品的顶层接口模型类
*/
public interface ProductB
{
public void method1();
public void method2();
}
(6)产品B的第一个版本的实现类:
package factorymodel.abatractfactory;
/**
* @author jwang
* 这是B产品的第一个版本的实现类
*/
public class ProductB1 implements ProductB
{
@Override
public void method1()
{
System.out.println("ProductB1产品已经生产,产品对象的method1方法正在被调用!");
}
@Override
public void method2()
{
System.out.println("ProductB1产品已经生产,产品对象的method2方法正在被调用!");
}
}
(7)产品B的第二个版本的实现类:
package factorymodel.abatractfactory;
/**
* @author jwang
* 这是B产品的第二个版本的实现类
*/
public class ProductB2 implements ProductB
{
@Override
public void method1()
{
System.out.println("ProductB2产品已经生产,产品对象的method1方法正在被调用!");
}
@Override
public void method2()
{
System.out.println("ProductB2产品已经生产,产品对象的method2方法正在被调用!");
}
}
(8)顶层的工厂接口类:
package factorymodel.abatractfactory;
/**
* @author jwang
* 定义顶层的工厂接口,提供生产A产品和B产品的方法
*/
public interface AbstractFactory
{
public ProductA createPorductA();
public ProductB createPorductB();
}
(9)生产第一个版本产品的工厂类:
package factorymodel.abatractfactory;
/**
* @author jwang
* 工厂实现类,该工厂用于生产所有产品的第一个版本
*/
public class AbstractFactory1 implements AbstractFactory
{
@Override
public ProductA createPorductA()
{
return new ProductA1();
}
@Override
public ProductB createPorductB()
{
return new ProductB1();
}
}
(10)生产第二个版本产品的工厂类:
package factorymodel.abatractfactory;
/**
* @author jwang
* 工厂实现类,该工厂用于生产所有产品的第二个版本
*/
public class AbstractFactory2 implements AbstractFactory
{
@Override
public ProductA createPorductA()
{
return new ProductA2();
}
@Override
public ProductB createPorductB()
{
return new ProductB2();
}
}
(11)客户测试类:
package factorymodel.abatractfactory;
import org.junit.Test;
/**
* @author jwang
* 客户测试类,创建工厂生产产品,使用产品
*/
public class Customer
{
@Test
public void testProductA()
{
//创建工厂
AbstractFactory1 factory1 = new AbstractFactory1();
AbstractFactory2 factory2 = new AbstractFactory2();
//两个工厂分别生产A产品的1版本和2版本
ProductA productA1 = factory1.createPorductA();
productA1.method1();
productA1.method2();
ProductA productA2 = factory2.createPorductA();
productA2.method1();
productA2.method2();
}
@Test
public void testProductB()
{
AbstractFactory1 factory1 = new AbstractFactory1();
AbstractFactory2 factory2 = new AbstractFactory2();
//两个工厂分别生产B产品的1版本和2版本
ProductB productB1 = factory1.createPorductB();
productB1.method1();
productB1.method2();
ProductB productB2 = factory2.createPorductB();
productB2.method1();
productB2.method2();
}
}