一、前言
由于近期项目实在太忙,导致木有继续更新,今天缓过来了。这一期主要是设计模式实战的一些应用,由于自己在重构项目时,看到之前的老代码实在是惨不忍睹,所以打算优化一波,那么设计模式是很好的选择,会先写工厂模式======>>>>策略模式,然后应用这几种模式来解决项目里面的究极老代码======= if else ......
二、概述
工厂模式属于创建型设计模式,需要生成的对象叫做产品,生成对象的地方叫做工厂。
2.1 使用场景
在任何需要生成复杂对象的场景,都可以使用工厂模式。划重点直接用new可以完成的不需要用工厂模式。
下面逐个介绍我所知道的各种工厂模式以及它们的特点,使用场景,并尽可能的找出JDK里它们的身影。
三、简单(静态)工厂
3.1 举栗子
我们经常会去餐馆吃面,那么我们用工厂模式的思维去思考,可以理解为:不同的面条就是产品,而餐馆就是一个工厂。
首先来一个产品的抽象类
package com.MyMineBug.demoRun.factory;
public abstract class INoodles {
/**
* 不同面条的描述
*/
public abstract void desc();
}
再来一份兰州拉面(具体的实现类)
package com.MyMineBug.demoRun.factory;
public class LzNoodles extends INoodles{
@Override
public void desc() {
System.out.println("兰州拉面 深圳的好贵,想吃家里的热干面!");
}
}
程序猿加完班后,必备泡面(具体的实现类)
package com.MyMineBug.demoRun.factory;
public class PaoNoodles extends INoodles{
@Override
public void desc() {
System.out.println("不多说,程序员加班必备,回家吃泡面!");
}
}
还有最爱吃老家的热干面(具体的实现类)
package com.MyMineBug.demoRun.factory;
public class HotNoodles extends INoodles{
@Override
public void desc() {
System.out.println("还是家里的热干面好吃,又便宜,5快一碗!");
}
}
面条原料都准备好了,接下来就要进入面馆(简单工厂)去点餐了,面馆菜单如下:
package com.MyMineBug.demoRun.factory;
public class SimpleNoodlesFactory {
public static final int TYPE_LZ = 1; //兰州拉面
public static final int TYPE_HOT = 2; //热干面
public static final int TYPE_PAO = 3; //泡面
public static INoodles createNoodies(int type) {
switch (type) {
case TYPE_LZ:
return new LzNoodles();
case TYPE_PAO:
return new PaoNoodles();
default:
return new HotNoodles();
}
}
}
这个简单面馆(简单工厂)里面,就只有三种面条(产品),那么你可以想点你喜欢吃的面条,比如我,老板来份热干面:
package com.MyMineBug.demoRun.factory;
public class TestSimpleFactory {
public static void main(String[] args) {
INoodles nodies = SimpleNoodlesFactory.createNoodies(3);
nodies.desc();
}
}
输出如下:
还是家里的热干面好吃,又便宜,5快一碗!
3.2 特点
1 它是一个具体的类,非接口抽象类。有一个重要的createNoodles()方法,利用if或者 switch创建产品并返回。
2 createNoodles()方法通常是静态的,所以也称之为静态工厂。
3.3 缺点
1 扩展性差(我想增加一种面条,除了新增一个面条产品类,还需要修改工厂类方法)。
2 不同的产品需要不同额外参数的时候 不支持。
3.4 工厂类实现的另外一种方式----(反射)
这里贴一下代码,其实原理跟上面一样,跟new Object()性质是一样的;主要是用Class.forName(clz.getName()).newInstance() 代码如下:
package com.MyMineBug.demoRun.factory;
public class ReflectNoodiesFactory {
public static <T extends INoodles> T createNoodles(Class<T> clz) {
T result = null;
try {
result = (T) Class.forName(clz.getName()).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
}
三、多方法工厂
多方法的工厂模式为不同产品,提供不同的生产方法,使用时需要哪种产品就调用该种产品的方法,使用方便、容错率高。 工厂代码如下:
package com.MyMineBug.demoRun.factory;
public class ManyWayNoodlesFactory {
/**
* 模仿Executors 类
* 生产泡面
*
* @return
*/
public static INoodles createPm() {
return new PaoNoodles();
}
/**
* 模仿Executors 类
* 生产兰州拉面
*
* @return
*/
public static INoodles createLz() {
return new LzNoodles();
}
/**
* 模仿Executors 类
* 生产热干面
*
* @return
*/
public static INoodles createHOT() {
return new HotNoodles();
}
}
输出如下:
==============================模仿Executor类==============================
这种我比较青睐,增加一个新面条,只要去增加一个static方法即可,也不修改原方法逻辑
兰州拉面 深圳的好贵,想吃家里的热干面!
还是家里的热干面好吃,又便宜,5快一碗!
3.1 JDK 相关源码实现多方法工厂模式

个人的话,比较推荐使用这种方法作为工厂。
三、普通工厂
普通工厂就是把简单工厂中具体的工厂类,划分成两层:抽象工厂层+具体的工厂子类层。
3.1 举栗子
面条工厂(抽象工厂类),作用就是生产面条:
package com.MyMineBug.demoRun.factory;
public abstract class NoodlesFactory {
public abstract INoodles create();
}
兰州拉面工厂 (具体工厂子类):
package com.MyMineBug.demoRun.factory;
public class LzNoodlesFactory extends NoodlesFactory{
@Override
public INoodles create() {
return new LzNoodles();
}
}
后面俩个具体实现工厂类似,就不贴代码了,接下来看使用时的代码:
package com.MyMineBug.demoRun.factory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class TestSimpleFactory {
public static void main(String[] args) {
// INoodles nodies = SimpleNoodlesFactory.createNoodies(2);
// nodies.desc();
/**
* 多方法静态工厂(模仿Executor类)
*/
// System.out.println("==============================模仿Executor类==============================" +
// "\n 这种我比较青睐,增加一个新面条,只要去增加一个static方法即可,也不修改原方法逻辑");
// INoodles lz2 = ManyWayNoodlesFactory.createLz();
// lz2.desc();
// String ssString = null;
// INoodles gk2 = ManyWayNoodlesFactory.createHOT();
// gk2.desc();
/**
* 普通工厂方法:
*/
System.out.println("===========================普通工厂方法==============================" +
"\n 这种要多写一个类,不过更面向对象吧 = = ,实际中我更倾向于使用【模仿Executor类】的方式");
NoodlesFactory factory1 = new LzNoodlesFactory();
INoodles gk3 = factory1.create();
gk3.desc();
}
}
输出:
===========================普通工厂方法==============================
这种要多写一个类,不过更面向对象吧 = = ,实际中我更倾向于使用【模仿Executor类】的方式
兰州拉面 深圳的好贵,想吃家里的热干面!
3.2 优缺点
可以看出,普通工厂模式特点:不仅仅做出来的产品要抽象, 工厂也应该需要抽象。
工厂方法使一个产品类的实例化延迟到其具体工厂子类.
工厂方法的好处就是更拥抱变化。当需求变化,只需要增删相应的类,不需要修改已有的类。
而简单工厂需要修改工厂类的create()方法,多方法静态工厂模式需要增加一个静态方法。
个人推荐使用多方法静态工厂
四、抽象工厂
抽象工厂其实可以理解为,多产品的多抽象工厂,比如:举个例子来说,每个店(工厂)不仅仅卖面条,还提供饮料卖,那么就会维护多个工厂,需要把工厂抽象出来,而且每次拓展新产品种类,例如不仅卖吃卖喝,我还想卖睡,提供床位服务,这需要修改抽象工厂类,因此所有的具体工厂子类,都被牵连,需要同步被修改。 这里具体实现,我就不贴代码,读者自行百度,因为这次优化代码也没用到这个。
五、总结
一句话总结工厂模式:方便创建 同种产品类型的 复杂参数 对象。具体使用可以根据实际业务场景进行选择使用,工厂模式的理解到此为止,写一篇会讲一下策略模式。
如果觉得还不错,请点个赞!!!
Share Technology And Love Life