1.简介
工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。使用工厂模式,在创建对象的时候就不需要亲自去new了,而是直接交由工厂来创建,就像是一个老板需要一批货,他不是直接亲自动手制造这些货,而是直接告诉工厂自己的需求,然后由工厂制造出这些货后自己过来取。工厂方法可以屏蔽创建对象的一些细节,也可以对创建的对象做一些增量操作,而这些操作,在客户端的角度是完全看不到的,客户端只需要告诉工厂自己需要的类即可。一般认为工厂模式可以分为:简单工厂模式,工厂方法模式和抽象工厂模式三类
2.简单工厂模式
简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例,说白了就是由同一个工厂去生产不同的产品。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。这里以一个简单生产手机例子作为切入点,详细讲解一下
手机的共同接口:
package com.factory;
/**
* 声明类的共同接口
*/
public interface Phone {
// 此接口只有一个共同方法:描述手机
void description();
}
手机的实现类A:“小米”手机
package com.factory;
/**
* 声明“小米”手机
*/
public class MiPhone implements Phone {
@Override
public void description() {
System.out.println("小米手机");
}
}
手机的实现类B:“华为”手机
package com.factory;
/**
* 声明“华为”手机
*/
public class HuaWeiPhone implements Phone {
@Override
public void description() {
System.out.println("华为手机");
}
}
简单工厂类:
package com.factory.simpleFactory;
import com.factory.HuaWeiPhone;
import com.factory.MiPhone;
import com.factory.Phone;
/**
* 创建简单工厂类
*/
public class SimpleFactory {
/**
* 生产手机的方法
* @param brandName 品牌名称
* @return
*/
public static Phone createPhone(String brandName) {
if ("MiPhone".equals(brandName)) {
return new MiPhone();
}
if ("HuaWeiPhone".equals(brandName)) {
return new HuaWeiPhone();
}
return null;
}
}
客户端
package com.factory.simpleFactory;
import com.factory.HuaWeiPhone;
import com.factory.MiPhone;
import com.factory.Phone;
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
// 原始方式
// 需要小米手机的时候
Phone miPhone = new MiPhone();
miPhone.description();
// 需要华为手机的时候
Phone huaWeiPhone = new HuaWeiPhone();
huaWeiPhone.description();
// 使用简单方法创建(全部交给工厂去创建,只需要传入自己的需求:品牌名称)
// 小米手机
Phone miPhone2 = SimpleFactory.createPhone("MiPhone");
miPhone2.description();
// 华为手机
Phone huaWeiPhone2 = SimpleFactory.createPhone("HuaWeiPhone");
huaWeiPhone2.description();
}
}
简单工厂方法的总结:
- 优点:实现了生成产品类的代码跟客户端代码分离,并且能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。
- 缺点:工厂类集中了所有实例的创建逻辑,要加一个产品类C,你就要修改工厂类里面的生成产品的代码,在这里你就要增加if-else判断,违反了“开放-封闭”原则
3.工厂方法模式
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现“开放-封闭”原则,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。在工厂方法模式中,创建实例不再是由一个工厂集中去创建了(注意与简单工厂的区别:简单工厂是由一个工厂去创建不同的产品),而是将具体创建的工作交给子类工厂去做,而自己只提供一个具体的标准即接口,类比生产手机的例子,本来小米手机和华为手机都是由同一个富土康流水线工厂来生产的,而现在由于业务调整,富土康流水线不再亲自生产各种品牌的手机了,而是只提供了一套标准,具体的生产转交给了那些专门生产小米手机的工厂和专门生产华为手机的工厂,而这些工厂全部都要按照富土康提供的生产标准去执行。
如果要在手机的品牌中新添加一个“魅族”手机,使用工厂方法模式应该怎么做呢?
首先需要定义一个工厂的接口:
package com.factory.factoryMethod;
import com.factory.Phone;
/**
* 工厂的接口
*/
public interface Factory {
// 声明生产手机的方法
Phone createPhone();
}
定义生产“小米”手机的工厂:
package com.factory.factoryMethod;
import com.factory.MiPhone;
import com.factory.Phone;
/**
* 专门生产小米的工厂
*/
public class MiFactory implements Factory{
@Override
public Phone createPhone() {
return new MiPhone();
}
}
定义生产“华为”手机的工厂:
package com.factory.factoryMethod;
import com.factory.HuaWeiPhone;
import com.factory.Phone;
/**
* 专门生产华为手机的工厂
*/
public class HuaWeiFactory implements Factory {
@Override
public Phone createPhone() {
return new HuaWeiPhone();
}
}
如果需要新生产一个“魅族”手机,则只需要添加一个魅族生产魅族手机的工厂:
package com.factory.factoryMethod;
import com.factory.MeiZuPhone;
import com.factory.Phone;
/**
* 专门生产魅族手机的工厂
*/
public class MeiZuFactory implements Factory {
@Override
public Phone createPhone() {
return new MeiZuPhone();
}
}
工厂方法模式的客户端:
package com.factory.factoryMethod;
import com.factory.Phone;
/**
* 工厂方法模式的客户端
*/
public class Client {
public static void main(String[] args) {
// 需要生产魅族手机
Factory factory = new MeiZuFactory();
Phone phone = factory.createPhone();
phone.description();
// 生产其他手机则创建其他手机的工厂
}
}
工厂方法模式的总结:
- 优点:完全实现开闭原则,扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 屏蔽产品的具体实现,调用者只关心产品的接口即可。
- 缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖
4.抽象工厂模式
抽象工厂模式是对上面的工厂方法模式的一种抽象,同时也是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。类比生产手机的例子:手机可以有多种尺寸,有的客户喜欢大尺寸大屏手机,而有的客户喜欢小尺寸小屏手机,制作手机的方式和工艺都一模一样,如果用上面的工厂方法模式,我想生产一个小屏幕的小米手机,那么我就必须再增加一个生产小屏幕小米手机的工厂,实际上是没有必要的,因为我们有“专门生产小米的手机的工厂”,此工厂既然是专门生产小米手机的,那么各种尺寸的小米手机它都是可以生产的,即一个工厂可以生产多个产品。
现在我们既要生产大屏幕的手机又要生产正常屏幕的手机,该怎么做呢?
正常屏幕手机的接口我们已经有了,现在需要再定义一个大屏幕手机的接口:
package com.factory;
/**
* 定义大屏幕手机的接口
*/
public interface BIgPhone {
// 此接口只有一个共同方法:描述手机
void description();
}
定义大屏幕的小米手机实现类:
package com.factory;
public class MiBigPhone implements BIgPhone {
@Override
public void description() {
System.out.println("我是大屏的小米手机");
}
}
定义大屏幕的华为手机的实现类:
package com.factory;
public class HuaWeiBigPhone implements BIgPhone {
@Override
public void description() {
System.out.println("我是大屏的华为手机");
}
}
定义抽象工厂的共同接口:
package com.factory.abstractFactoryMethod;
import com.factory.BIgPhone;
import com.factory.Phone;
public interface Factory {
// 声明生产正常尺寸手机的方法
Phone createPhone();
// 声明生产大尺寸手机的方法
BIgPhone createBigPhone();
}
定义专门生产小米手机的工厂:
package com.factory.abstractFactoryMethod;
import com.factory.BIgPhone;
import com.factory.MiBigPhone;
import com.factory.MiPhone;
import com.factory.Phone;
/**
* 声明专门生产小米手机的工厂
*/
public class MiFactory implements Factory {
// 生产正常尺寸的手机
@Override
public Phone createPhone() {
return new MiPhone();
}
// 生产大屏幕大尺寸的手机
@Override
public BIgPhone createBigPhone() {
return new MiBigPhone();
}
}
定义专门生产华为手机的工厂:
package com.factory.abstractFactoryMethod;
import com.factory.BIgPhone;
import com.factory.HuaWeiBigPhone;
import com.factory.HuaWeiPhone;
import com.factory.Phone;
/**
* 声明专门生产华为手机的工厂
*/
public class HuaWeiFactory implements Factory{
// 生产正常尺寸手机方法
@Override
public Phone createPhone() {
return new HuaWeiPhone();
}
// 生产大屏幕手机的方法
@Override
public BIgPhone createBigPhone() {
return new HuaWeiBigPhone();
}
}
抽象工厂模式的客户对端:
package com.factory.abstractFactoryMethod;
import com.factory.BIgPhone;
import com.factory.Phone;
/**
* 抽象工厂方法的客户端
*/
public class Client {
public static void main(String[] args) {
// 需求:生产一个正常尺寸的小米手机和一个大屏幕的华为手机
// 生产小米手机无论大屏还是小屏都需要去找专门生产小米手机的工厂
Factory miFactory = new MiFactory();
// 生产正常尺寸的
Phone miPhone = miFactory.createPhone();
miPhone.description();
// 生产华为手机无论大屏还是小屏都需要去找专门生产华为手机的工厂
Factory huaWeiFactory = new HuaWeiFactory();
// 生产大屏幕大尺寸的华为手机
BIgPhone huaWeiBigPhone = huaWeiFactory.createBigPhone();
huaWeiBigPhone.description();
}
}
抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式