前言(一些废话,可以忽略)
- 工厂模式是非常重要的一种设计模式,相比单例模式来说,更有结构上的设计,有思想上深一层的东西,但是和跟复杂的模式相比,其实也是很简单的。
- 网络上有很多工厂模式的讲解,如果你看得比较多,你会发现,一会这么实现,一会那么实现,怎么感觉每一篇文章讲得都大同小异,又感觉不太一样,让人很是迷糊。
- 是的,开始的时候我也是这样迷茫,当我继续阅读更多的设计模式的时候,恍然大悟。这不就是大师打拳的境界么,神似而形异。
- 其实设计模式就是这样的,不要说同一种设计模式都有相似的地方,哪怕是不同的设计模式,它们的结构也大同小异,我们要做的,是将设计的原则精神掌握内化,而这些设计模式,只是一个工具,帮主你内化代码设计精神的工具,举个例子,具体A讲的工厂模式和B说的工厂模式可能不一样,这不重要,重要的是他们所讲的工厂模式的精髓是一样的。
- 所以在你学习设计模式的时候,期望大家能够自己进行演化,这样更能方便大家,使大家更容易,更快速的内化掌握代码设计精髓。
- PS.部分类实现见文末
简单工厂模式
- 这是将类创建进行简单封装的模式,很容易就能够想到,将需要的对象封装在一个方法,通过参数判断需要创建哪个类对象
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:09
**/
public class SimpleAeratedWaterFactory {
public ColaAeratedWater getAeratedWater(String type){
if("ColaOriginal".equals(type)){
return new ColaOriginal();
}else if("ColaBule".equals(type)){
return new ColaBule();
}else if("ColaDiet".equals(type)){
return new ColaDiet();
}else{
throw new RuntimeException("没有此类型可乐");
}
}
}
- 调用也简单,无需解释
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:09
**/
public class SimpleFactoryMode {
public static void main(String[] args) {
SimpleAeratedWaterFactory factory = new SimpleAeratedWaterFactory();
ColaAeratedWater water = factory.getAeratedWater("ColaOriginal");
System.out.println(water.getName());
}
}
- 存在一个问题,如果要增加的新的可乐口味,我们不仅需要新增实现不同味道的可乐,而且还需要在工厂中添加if else代码,据说这里是违反ocp原则,是的,自己仔细想一想也是,工厂代码被修改了
工厂方法模式
- 我们将可乐的不同味道,实现在不同的类中,让这个类去实现一个统一的创建可乐的工厂,即所谓网络上流传的将具体的实现延迟到子类中进行实现
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:10
**/
public interface ColaFactory {
ColaAeratedWater createCola();
}
- 蓝色口味的可乐,实现可乐工厂ColaFactory实现其方法,返回蓝色可乐对象
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:10
**/
public class BuleColaFactory implements ColaFactory {
@Override
public ColaAeratedWater createCola() {
return new ColaBule();
}
}
同理,无糖口味可乐的工厂
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:10
**/
public class DietColaFactory implements ColaFactory {
@Override
public ColaAeratedWater createCola() {
return new ColaDiet();
}
}
- 在使用的时候,通过创建对应口味的可乐工厂,调用同样的创建可乐方法
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:08
**/
public class FactoryMethodMode {
public static void main(String[] args) {
ColaFactory factory = new BuleColaFactory();
ColaAeratedWater water = factory.createCola();
System.out.println(water.getName());
}
}
- 简单画一下工厂方法模式的uml图
抽象工厂模式
- 在工厂方法模式的基础上进行扩展,比如要新增雪碧Sprite,工厂方法模式似乎就不能满足设计模式原则的扩展需求了
- 将蓝色可乐工厂进一步抽象为蓝色汽水工厂,这样不仅可以生产蓝色可乐,也可以生产蓝色雪碧(当然,我们目前没有蓝色雪碧,这种情况如何处理,我是有点木讷,是实现一个空方法还是在实现的方法里抛出异常,又或是有更好的方法,希望看到此文的同学能告诉我)或其他蓝色口味汽水
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:11
**/
public abstract class BuleAeratedWaterFactory implements AeratedWaterFactory {
@Override
public ColaAeratedWater createColaAeratedWater() {
return new ColaBule();
}
@Override
public SpriteAeratedWater createSpriteAeratedWater() {
return null;
}
}
- 接下来是原味的汽水,可乐和雪碧都有,都得实现
/**
*
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:11
**/
public class OriginalAeratedWaterFactory implements AeratedWaterFactory{
@Override
public ColaAeratedWater createColaAeratedWater() {
return new ColaOriginal();
}
@Override
public SpriteAeratedWater createSpriteAeratedWater() {
return new SpriteOriginal();
}
}
抽象工厂,即可以生产可乐也可以生产雪碧,在扩展的时候,直接添加其他汽水饮料
/**
* absFactory
*
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:10
**/
public interface AeratedWaterFactory {
ColaAeratedWater createColaAeratedWater();
SpriteAeratedWater createSpriteAeratedWater();
//增加其他汽水
//SodaAeratedWater createSodaAeratedWater();
}
- 使用,创建不同口味的汽水工程,然后生产需要的汽水
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:10
**/
public class AbsFactoryMode {
public static void main(String[] args) {
AeratedWaterFactory originalAeratedWaterFactory = new OriginalAeratedWaterFactory();
AeratedWater water = originalAeratedWaterFactory.createColaAeratedWater();
System.out.println(water.getName());
}
}
其他类
/**
* 汽水
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:11
**/
public interface AeratedWater {
String getName();
}
/**
* 工厂方法模式
* 使用的可乐父接口(也可以不要 用AeratedWater代替 个人认为这些就是所谓的在学习过程中或初学时__不需要特别纠结的细节__ 在使用过程中遇到情况再随机应变)
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:09
**/
public interface ColaAeratedWater extends AeratedWater{
}
/**
* 蓝色可乐
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:09
**/
public class ColaBule implements ColaAeratedWater {
@Override
public String getName() {
return "ColaBule";
}
}
/**
* 原味可乐
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:09
**/
public class ColaOriginal implements ColaAeratedWater {
@Override
public String getName() {
return "ColaOriginal";
}
}
/**
* 雪碧
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:10
**/
public interface SpriteAeratedWater extends AeratedWater{
}
/**
* 原味雪碧
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-21 21:11
**/
public class SpriteOriginal implements SpriteAeratedWater {
@Override
public String getName() {
return "SpriteOriginal";
}
}
总结
- 工厂模式的三种基本分支大概就是这样了,个人感觉自己还是要理解其精神内涵,不要盲目的生搬硬套,不能钻牛角尖,特别在当前博客泛滥相互借鉴质量不高的情况下,要有自己的理解,才能有所提升。
愿你不舍爱与自由。