简介
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
简单工厂模式
顾名思义我来举一个小例子,小明与小红去商场玩,小红说“我想吃冰激凌,你快去给我买吧”,小明走到第一个店内,买到的是一个草莓味的冰激凌,拿去给小红,小红说“我不想吃这个口味的,我要吃巧克力的”,那小明又得回去买了,这时可惜了,那家店内刚好没这款卖,小明又跑到另外一家店内买好在回来拿给小红,这个例子我在下面用编码方式来说明一下
优缺点
优点:
- 调用对象只需要知道名称即可
- 后期扩展方便,如需在增加不同工作,只需添加一个工厂类即可
- 屏蔽产品的具体实现,调用者只关心产品的接口
缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,这样一来还是增加了系统的复杂度
场景
日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方
数据库访问配置:在访问不同的数据库时也可以使用
例子一(未使用工厂模式)
package demo;
/**
* @Date 2021/7/13 10:55
* @Version SpringBoot 2.2.2
* @packageName 草莓味冰激凌
*/
public class Strawberry{
public void strawberryTest(){
System.out.println("第一家店:草莓味冰激凌");
}
}
package demo;
/**
* @Date 2021/7/13 11:14
* @Version SpringBoot 2.2.2
* @packageName 巧克力冰激凌
*/
public class Chocolate {
public void chocolateTest(){
System.out.println("第二家店:巧克力冰激凌");
}
}
package main;
import demo.Chocolate;
import demo.Strawberry;
/**
* @Date 2021/7/13 10:59
* @Version SpringBoot 2.2.2
* @packageName
*/
public class Main {
public static void main(String[]args){
//草莓味
Strawberry strawberry = new Strawberry();
strawberry.strawberryTest();
//巧克力味
Chocolate chocolate = new Chocolate();
chocolate.chocolateTest();
//.....橘子味、西瓜味
}
}
就如我上所说,要是小红还想吃橘子味、西瓜味的呢?那如是又遇上商家没有的情况岂不是跑的很累吗,这时候小明就去向商场管理员提交了一个建议,说可以在商场放置一台冰激凌机器,而这个机器呢,可以有不同口味,现在你去看门面基本上也是一台冰激凌机器制作多种口味的是吧,那这个机器是什么呢,这个时候就如工厂模式的工厂了,把机器比做工厂来运行,下面我把上面的例子化为工厂实现
例子二(使用工厂模式)
package demo;
/**
* @Date 2021/7/13 11:48
* @Version SpringBoot 2.2.2
* @packageName 出口
*/
public interface Exit {
void draw();
}
package demo;
/**
* @Date 2021/7/13 10:55
* @Version SpringBoot 2.2.2
* @packageName 草莓味冰激凌
*/
public class Strawberry implements Exit{
@Override
public void draw() {
System.out.println("出口一:草莓味冰激凌");
}
}
package demo;
/**
* @Date 2021/7/13 11:14
* @Version SpringBoot 2.2.2
* @packageName 巧克力冰激凌
*/
public class Chocolate implements Exit {
@Override
public void draw() {
System.out.println("出口二:巧克力冰激凌");
}
}
package demo;
/**
* @Date 2021/7/13 11:50
* @Version SpringBoot 2.2.2
* @packageName 机器
*/
public class Machine {
public Exit getExit(String exit) {
if (exit.equalsIgnoreCase("草莓")) {
return new Strawberry();
} else if (exit.equalsIgnoreCase("巧克力")) {
return new Chocolate();
}
return null;
}
}
package main;
import demo.Exit;
import demo.Machine;
import java.util.Scanner;
/**
* @Date 2021/7/13 10:59
* @Version SpringBoot 2.2.2
* @packageName
*/
public class Main {
public static void main(String[]args){
Scanner input = new Scanner(System.in);
System.out.println("小红在机器面前选择了:");
String selector = input.next();
Machine machine = new Machine();
switch (selector){
case "草莓":
Exit exit = machine.getExit("草莓");
exit.draw();
break;
case "巧克力":
Exit exit1 = machine.getExit("巧克力");
exit1.draw();
break;
}
}
}
main方法就当我们在机器选择的出口,后期需要什么口味的直接选择即可,下面我在来说一下工厂模式的实现原理
当客户在机器面前选择不同口味的冰激凌,这个机器也就是上面的Machine类,选择的时候有出口这个出口就是Eixt()接口,这个接口里存放着不同口味的冰激凌,当需求者选择后方可在不同的类实现中,也就是Chocolate类与Strawberry中吐出想要的冰激凌,这就是简单的工厂模式
抽象工厂模式
接下来机器是解决了出不同口味的冰激凌,但是每个人的食量又不同了吧,这个时候怎么办呢,那就讲一讲抽象工厂模式的作用吧,抽象工厂模式也是创建型模式,只是在简单工厂模式上的复杂程度要高一些,下面带着吃货们的大小中杯来解决这个疑虑,既然名字就叫抽象,那么肯定是用到abstract这个关键词了吧,我们先画一张图,根着这张图的思路往下走着
根据这个图,我们在刚刚所创建的工厂模式中进行改变,例子我已写好,代码放在下面
package demo;
/**
* @Date 2021/7/13 11:48
* @Version SpringBoot 2.2.2
* @packageName 出口
*/
public interface Exit {
void draw();
}
package demo;
/**
* @Date 2021/7/13 11:14
* @Version SpringBoot 2.2.2
* @packageName 巧克力冰激凌
*/
public class Chocolate implements Exit {
@Override
public void draw() {
System.out.println("巧克力冰激凌");
}
}
package demo;
/**
* @Date 2021/7/13 10:55
* @Version SpringBoot 2.2.2
* @packageName 草莓味冰激凌
*/
public class Strawberry implements Exit{
@Override
public void draw() {
System.out.println("草莓味冰激凌");
}
}
package demo;
/**
* @Date 2021/7/13 14:57
* @Version SpringBoot 2.2.2
* @packageName 规格
*/
public interface Sepc {
void size();
}
package demo;
/**
* @Date 2021/7/13 15:01
* @Version SpringBoot 2.2.2
* @packageName 小杯
*/
public class Adj implements Sepc {
@Override
public void size() {
System.out.println("小杯");
}
}
package demo;
/**
* @Date 2021/7/13 15:00
* @Version SpringBoot 2.2.2
* @packageName 中
*/
public class Centre implements Sepc {
@Override
public void size() {
System.out.println("中杯");
}
}
package demo;
/**
* @Date 2021/7/13 14:58
* @Version SpringBoot 2.2.2
* @packageName 大杯
*/
public class Big implements Sepc {
@Override
public void size() {
System.out.println("大杯");
}
}
package demo;
import java.util.logging.Logger;
/**
* @Date 2021/7/13 11:50
* @Version SpringBoot 2.2.2
* @packageName 机器
*/
public abstract class Machine {
public abstract Exit getExit(String exit);
public abstract Sepc getSepc(String sepc);
}
package demo;
/**
* @Date 2021/7/13 15:09
* @Version SpringBoot 2.2.2
* @packageName 口味实现
*/
public class ExitFactory extends Machine {
@Override
public Exit getExit(String exit) {
if (exit.equalsIgnoreCase("草莓")){
return new Strawberry();
}else if (exit.equalsIgnoreCase("巧克力")){
return new Chocolate();
}
return null;
}
@Override
public Sepc getSepc(String sepc) {
return null;
}
}
package demo;
/**
* @Date 2021/7/13 15:20
* @Version SpringBoot 2.2.2
* @packageName 规格实现
*/
public class SepcFactory extends Machine {
@Override
public Exit getExit(String exit) {
return null;
}
@Override
public Sepc getSepc(String sepc) {
if (sepc.equalsIgnoreCase("大杯")){
return new Big();
}else if (sepc.equalsIgnoreCase("中杯")){
return new Centre();
}else if (sepc.equalsIgnoreCase("小杯")){
return new Adj();
}
return null;
}
}
package demo;
/**
* @Date 2021/7/13 15:22
* @Version SpringBoot 2.2.2
* @packageName 生成器
*/
public class Production {
public static Machine getMachine(String machine){
if (machine.equalsIgnoreCase("exit")){
return new ExitFactory();
}else if (machine.equalsIgnoreCase("sepc")){
return new SepcFactory();
}
return null;
}
}
package main;
import demo.Exit;
import demo.Machine;
import demo.Production;
import demo.Sepc;
import java.util.Scanner;
/**
* @Date 2021/7/13 10:59
* @Version SpringBoot 2.2.2
* @packageName
*/
public class Main {
public static void main(String[]args){
Scanner input = new Scanner(System.in);
System.out.println("口味选择:");
String selector = input.next();
Machine machine = Production.getMachine("exit");
switch (selector){
case "草莓":
Exit exit = machine.getExit("草莓");
exit.draw();
break;
case "巧克力":
Exit exit1 = machine.getExit("巧克力");
exit1.draw();
break;
}
Machine machine1 = Production.getMachine("sepc");
System.out.println("规格选择:");
String secp = input.next();
switch (secp){
case "大杯":
Sepc sp =machine1.getSepc("大杯");
sp.size();
break;
case "中杯":
Sepc sp1 =machine1.getSepc("中杯");
sp1.size();
break;
case "小杯":
Sepc sp2 =machine1.getSepc("小杯");
sp2.size();
break;
}
}
}