一、概述
工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
简单来说:工厂就是一种创建型的设计模式,常用于封装变化,一般遵循那里有变化就封装那里的原则。这里我们以一个快餐店为示例讲解,FastFood表示快餐,KFC表示肯德基,Mac表示麦当劳。

FastFood.java代码如下:
package com.Design_mode.Factory_pattern;
//快餐
public abstract class FastFood {
//品牌
public String brand;
//展示
public abstract void show();
}
KFC.java代码如下:
package com.Design_mode.Factory_pattern;
public class KFC extends FastFood {
@Override
public void show() {
this.brand = "肯德基";
System.out.println("欢迎来到"+ this.brand);
}
}
Mac.java代码如下:
package com.Design_mode.Factory_pattern;
public class Mac extends FastFood {
@Override
public void show() {
this.brand = "麦当劳";
System.out.println("欢迎来到"+ this.brand);
}
}
Student.java代码如下:
package com.Design_mode.Factory_pattern;
public class Student {
public static void main(String[] args) {
KFC kfc = new KFC();
kfc.show();
}
}
运行结果:

从Student类中可以看到学生只允许吃KFC,如果他想吃别的东西就不允许了,违背DIP(依赖倒转原则),解决:

package com.Design_mode.Factory_pattern;
public class Student {
public static void main(String[] args) {
//这里可以指定任意FastFood子类,LSP
//如果这里是稳定的,不会经常变化,则代码是没有问题的
//如果这里要不断的变化,new KFC(),new Mac,new Kongfu()...
FastFood kfc = new KFC();
kfc.show();
}
}
new KFC()就是一个变化点,封装。
二、简单工厂(Simple Factory)
简单工厂并不是GOF所著的书中提出的一种设计模式,但这种模式是学习设计模式一个很好的入口点,让我们能更容易理解设计模式是如何达到设计原则的要求的。
简单工厂设计模式是一种创建型的模式,主要是用来解决对象的创建问题。


上面的类图反映的就是将一组相似对象(继承自同一个类)的实例的创建放到另外一个对象中完成,即通过 ProductFactory 这个类来按需创建对象

在第一节中我们提出了“封装变化”的概念,这里使用简单工厂解决问题,代码如下:
FastFoodFactory.java代码如下:
package com.Design_mode.Factory_pattern;
/**
* 快餐工厂
*/
public class FastFoodFactory {
/***
* 用于实现不同类型快餐品牌的创建
* @param brand 类型
* @return 快餐品牌
*/
public static FastFood GetFastFood(String brand) {
switch (brand) {
case "KFC":
return new KFC();
case "Mac":
return new Mac();
default:
throw new IllegalArgumentException("没有该品牌");
}
}
}
Student.java代码如下
package com.Design_mode.Factory_pattern;
import java.util.Scanner;
public class Student {
public static void main(String[] args) {
//这里可以指定任意FastFood子类,LSP
//如果这里是稳定的,不会经常变化,则代码是没有问题的
//如果这里要不断的变化,new KFC(),new Mac,new Kongfu()...
Scanner input=new Scanner(System.in);
System.out.print("您想吃什么:");
String brand=input.next();
FastFood kfc = FastFoodFactory.GetFastFood(brand);
kfc.show();
}
}
运行结果:

简单工厂的优点:
简单工厂的工厂类中包含了必要的逻辑判断,这样就可以根据客户端的选择条件来动态的实例化相关的类,对于客户端来说,其去除了与具体产品之间的依赖
简单工厂的缺点:
违背了开-闭原则
三、工厂方法(Factory Method)
工厂方法模式,定义了一个用于创建对象的接口,让子类来决定要实例化哪一个类,工厂方法让类把实例化延迟到其子类。
在工厂方法模式中主要有以下几个组成部分:
抽象工厂:是工厂方法模式的核心,任何在模式中创建的具体工厂必须实现这个接口。
具体工厂:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
抽象产品:方法方法模式所要创建的对象的父类型,也就是产品对象的共同父类或共同拥有的接口。
具体产品:这是实现了抽象产品所定义的接口的具体产品类的实例。这是客户端最终需要的东西。

示例:

KFC肯德基,Mac麦当劳,Chips薯条,Ham汉堡
Chips.java代码如下:
package com.Design_mode.Factory_pattern;
/**
* 抽象产品,薯条
*/
public abstract class Chips {
/**
* 显示薯条信息
*/
public abstract void info();
}
KFCChips.java代码如下:
package com.Design_mode.Factory_pattern;
public class KFCChips extends Chips {
@Override
public void info() {
System.out.println("肯德基薯条");
}
}
MacChips.java代码如下:
package com.Design_mode.Factory_pattern;
public class MacChips extends Chips {
@Override
public void info() {
System.out.println("麦当劳薯条");
}
}
Ham.java代码如下:
package com.Design_mode.Factory_pattern;
/**
* 抽象产品,汉堡
*/
public abstract class Ham {
/**
* 显示汉堡信息
*/
public abstract void show();
}
KFCHam.java代码如下:
package com.Design_mode.Factory_pattern;
public class KFCHam extends Ham {
@Override
public void show() {
System.out.println("肯德基汉堡");
}
}
MacHam.java代码如下:
package com.Design_mode.Factory_pattern;
public class MacHam extends Ham {
@Override
public void show() {
System.out.println("麦当劳汉堡");
}
}
FastFoodFactoryAb.java代码如下:
package com.Design_mode.Factory_pattern;
/**
* 抽象工厂 快餐工厂
*/
public abstract class FastFoodFactoryAb {
/**
* 生产汉堡
*/
public abstract Ham CreateHam();
/**
* 生产薯条
*/
public abstract Chips CreateChips();
/***
* 用于实现不同类型快餐品牌的创建
* @param brand 类型
* @return 快餐品牌
*/
public static FastFoodFactoryAb GetFastFood(String brand) {
switch (brand) {
case "KFC":
return new KFCFactory();
case "Mac":
return new MacFactory();
default:
throw new IllegalArgumentException("没有该品牌");
}
}
}
KFCFactory.java代码如下:
package com.Design_mode.Factory_pattern;
public class KFCFactory extends FastFoodFactoryAb {
@Override
public Ham CreateHam() {
return new KFCHam();
}
@Override
public Chips CreateChips() {
return new KFCChips();
}
}
MacFactory.java代码如下:
package com.Design_mode.Factory_pattern;
public class MacFactory extends FastFoodFactoryAb {
@Override
public Ham CreateHam() {
return new MacHam();
}
@Override
public Chips CreateChips() {
return new MacChips();
}
}
Student.java代码如下:
package com.Design_mode.Factory_pattern;
import java.util.Scanner;
public class Student {
public static void main(String[] args) {
//这里可以指定任意FastFood子类,LSP
//如果这里是稳定的,不会经常变化,则代码是没有问题的
//如果这里要不断的变化,new KFC(),new Mac,new Kongfu()...
Scanner input=new Scanner(System.in);
System.out.print("您想吃什么:");
String brand=input.next();
FastFoodFactoryAb fastFood = FastFoodFactoryAb.GetFastFood(brand);
fastFood.CreateHam().show();
fastFood.CreateChips().info();
}
}
运行结果:
