-
2022-01-10 17:16:33
1.工厂方法模式:定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。
在工厂方法模式中不再提供一个统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不通的工厂,从而让子工厂去创建对象。
/**抽象工厂可以是接口,也可以是抽象类或者具体类*/ public interface Factory{ public Product factoryMethod(); }
/**具体工厂类的实现*/ public class ConcreateFactory implements Factory{ public Product factoryMethod(){ return new ConcreateProduct();//不同的具体工厂可以返回不同的具体产品 } }
/**客户端代码中测试*/ ··· Factory factory; factory = new ConcreateFactory();//也可以通过配置文件与反射机制实现 Product product; Product = factory.factoryMethod();//获取与该具体工厂相匹配的具体产品 ···
上面也可以通过配置文件来存储具体工厂类ConcreateFactory的类名,再通过反射机制创建具体的工厂对象。
2.工厂方法模式的应用实例:还是小明吃水果的问题。下面代码中水果工厂相当于水果树,苹果工厂或者桔子工厂相当于桔子树。小明要吃苹果,就要从苹果树上摘下苹果吃,即苹果工厂生产苹果。而苹果树(苹果工厂)继承水果树(抽象工厂),苹果继承水果,桔子同理。小明想吃香蕉,只要继承苹果树新栽种香蕉树(香蕉工厂即子工厂)后,从香蕉树上摘香蕉就可以了。
/**日志记录器接口,充当抽象产品角色*/ public interface Fruit { public void eatFruit(); } /**苹果,充当具体产品角色*/ public class AppleFruit implements Fruit { public void eatFruit(){ System.out.println("吃了一个苹果"); } } /**桔子,充当具体产品角色*/ public class OrangeFruit implements Fruit { public void eatFruit(){ System.out.println("吃了一个桔子"); } } /**水果工厂接口,相当于水果树,充当抽象工厂角色*/ public interface FruitFactory { public Fruit createFruit();//抽象工厂方法 } /**苹果树工厂类,充当具体工厂角色*/ public class AppleFruitFactory implements FruitFactory { public Fruit createFruit(){ Fruit apple = new AppleFruit();//苹果树长出了一个苹果 System.out.println("苹果树长出了一个苹果"); return apple; } } /**桔子树工厂类,充当具体工厂角色*/ public class OrangeFruitFactory implements FruitFactory { public Fruit createFruit(){ Fruit orange = new OrangeFruit();//桔子树长出了一个桔子 System.out.println("桔子树长出了一个桔子"); return orange; } } /**客户端测试类*/ public class Client{ public static void main(String args[]){ FruitFactory factory; Fruit fruit; factory = new OrangeFruitFactory();//也可以引入配置文件和反射机制实现 fruit = factory.createFruit(); fruit.eatFruit(); } }
运行结果如下图:
简单工厂模式和工厂模式的异同你弄清楚了嘛?不急下一篇文章,我们还将会学习抽象工厂模式,然后再进行总结。
更多相关内容 -
java工厂方法模式和抽象工厂模式实例
2015-04-04 14:17:06用java语言实现工厂方法模式和抽象工厂模式 -
Java使用设计模式中的工厂方法模式实例解析
2020-09-02 09:30:59当系统准备为用户提供某个类的子类的实例,又不想让用户代码和该子类形成耦合时,就可以使用...工厂方法模式的关键是在一个接口或抽象类中定义一个抽象方法,下面我们会具体介绍Java使用设计模式中的工厂方法模式实例解析. -
Java设计模式之抽象工厂模式实例详解
2020-08-29 08:14:14主要介绍了Java设计模式之抽象工厂模式,结合实例形式分析了抽象工厂模式的概念、功能、定义与使用方法,需要的朋友可以参考下 -
Java设计模式之工厂方法模式实例简析
2020-09-03 04:34:19主要介绍了Java设计模式之工厂方法模式,较为详细的分析了Java工厂模式的功能、定义并给出了实例代码加以总结分析,需要的朋友可以参考下 -
工厂方法模式java实例demo
2016-01-11 21:11:11工厂方法模式java实例demo,来自刘伟老师的《设计模式》一书.rar -
java设计模式之工厂模式实例详解
2020-08-29 08:12:31主要介绍了java设计模式之工厂模式,结合具有实例形式分析了java工厂模式的概念、原理、实现与使用方法,需要的朋友可以参考下 -
Java中工厂模式案例
2019-01-17 16:36:011.简单工厂模式(simple factory)2.工厂方法模式(factory mathoud)3.抽象工厂模式(abstract factory) -
Java设计模式编程中简单工厂与抽象工厂模式的使用实例
2020-09-02 11:58:31主要介绍了Java设计模式编程中简单工厂与抽象工厂模式的使用实例,简单工厂与抽象工厂都可以归类于设计模式中的创建型模式,需要的朋友可以参考下 -
Java设计模式之工厂模式实现方法详解
2020-08-28 13:31:34主要介绍了Java设计模式之工厂模式实现方法,结合实例形式较为详细的分析了工厂模式的分类、原理、实现方法与相关注意事项,需要的朋友可以参考下 -
java 单例模式和工厂模式实例详解
2020-08-30 19:52:45主要介绍了Java设计模式编程中的单例模式和简单工厂模式以及实例,使用设计模式编写代码有利于团队协作时程序的维护,需要的朋友可以参考下 -
java 工厂模式的实例详解
2020-08-29 11:53:26主要介绍了java 工厂模式的实例详解的相关资料,这里举例说明该如何实现工厂模式,需要的朋友可以参考下 -
Java工厂模式定义与用法实例分析
2020-08-25 19:00:18主要介绍了Java工厂模式定义与用法,结合具体实例形式分析了java工厂模式定义、使用相关操作技巧,并总结了类图原理,需要的朋友可以参考下 -
java工厂模式实例(设计模式)
2021-01-26 19:20:35java工厂模式 开篇声明,此理解为作者自身理解,不一定正确,如有错误请大佬们指正。 工厂模式,在作者看来,从现实生活来说,就是一个工厂,里面有N个车间, 每个车间会生产不同的产品,而租户只需要告诉这个...目录
java工厂模式
开篇声明,此理解为作者自身理解,不一定正确,如有错误请大佬们指正。
工厂模式,在作者看来,从现实生活来说,就是一个工厂,里面有N个车间,
每个车间会生产不同的产品,而租户只需要告诉这个工厂的老板我需要一个
什么产品,老板会去找到对应的车间返回给租户使用。
画个图理解:
如果使用java语言来描述则是,对具有相同动作,不同动作执行过程的一
类方法抽象出一个接口类,然后不同的实现类对接口类中的接口进行不同的
实现,并且编写一个工厂类,根据传入获取不同的实现类实例返回给调用者,调用者使用得到的实例
执行具体的方法。画个图(简单的加减乘除做示例,没怎么画过UML图,如果有错误,请见谅):
TestServiceImpl为业务逻辑实现类,MathFactory为工厂类,MathOperation为算法抽象接口类,
xxxOpreation为算法具体实现类,Class为java原生类,主要是要使用反射机制,会用到
工厂模式其实又分为三种
1.简单工厂模式:
不提供工厂接口只有工厂,提供实例的接口与实现
简单工厂模式(非静态)
就是提供一个接口interface,然后不同的实现类实现interface,再提供一个
工厂类,在工厂类中通过if条件判断,new出具体的实现类给调用者使用。
算法抽象接口
public interface MathOperation { double apply(int a, int b); }
算法抽象接口实现 (顺序-加减乘除):
import com.liu.test.factory.simplefactory.MathOperation; public class AddOperation implements MathOperation { @Override public double apply(int a, int b) { return (double) a + b; } }
import com.liu.test.factory.simplefactory.MathOperation; public class SubOperation implements MathOperation { @Override public double apply(int a, int b) { return (double) a - b; } }
import com.liu.test.factory.simplefactory.MathOperation; public class MultiplyOperation implements MathOperation { @Override public double apply(int a, int b) { return (double) a * b; } }
import com.liu.test.factory.simplefactory.MathOperation; public class DivideOperation implements MathOperation { @Override public double apply(int a, int b) { return (double) a / b; } }
工厂类:
import com.liu.test.factory.simplefactory.operation.AddOperation; import com.liu.test.factory.simplefactory.operation.DivideOperation; import com.liu.test.factory.simplefactory.operation.MultiplyOperation; import com.liu.test.factory.simplefactory.operation.SubOperation; public class MatchFactory { /** * 获得具体的操作类型 * @author kevin * @param operator : * @return java.util.Optional<com.liu.test.math.MathOperation> * @date 2021/1/25 11:36 */ public static Optional<MathOperation> getOperation(String operator) { MathOperation result = null; if("add".equals(operator)){ result = new AddOperation(); }else if("sub".equals(operator)){ result = new SubOperation(); }else if("multiply".equals(operator)){ result = new MultiplyOperation(); }else if("divide".equals(operator)){ result = new DivideOperation(); } return Optional.ofNullable(result); } }
使用类
MathOperation operation = MathFactory.getOperation(operator).orElseThrow(() -> new IllegalArgumentException("未知的操作")); result = operation.apply(first, second); return result;
简单工厂模式(静态):
就是在第一步的基础之上,将new的动作提出来,放到static块中执行,然后
将产生的实现类实例存放到静态的map中,用户调用的时候,直接从map中get对应的实例。
此模式不符合java的闭环原则(对扩展开放,对修改关闭)
静态只需调整工厂类即可,其他不变
import com.liu.test.factory.simplefactory.operation.AddOperation; import com.liu.test.factory.simplefactory.operation.DivideOperation; import com.liu.test.factory.simplefactory.operation.MultiplyOperation; import com.liu.test.factory.simplefactory.operation.SubOperation; import java.lang.reflect.InvocationTargetException; import java.util.Optional; import java.util.HashMap; import java.util.Map; public class MatchFactory { static Map<String, MathOperation> operationMap = new HashMap<>(); static { operationMap.put("add", new AddOperation()); operationMap.put("sub", new SubOperation()); operationMap.put("multiply", new MultiplyOperation()); operationMap.put("divide", new DivideOperation()); } public static Optional<Operation> getOperation(String operator) { return Optional.ofNullable(operationMap.get(operator)); } }
简单工厂模式(反射):
就是在第一步的基础之上,将new的动作去掉,换成反射的方式实现,将接口实现类统一放
在一个包中,然后统一命名规范,最后根据传入反射产生实例对象;用户调用的时候,直接传入
调用类型即可(统一实现类命名规范xxxOperation);只需调整工厂类即可,其他不变:
import java.lang.reflect.InvocationTargetException; import java.util.Optional; /** * * <p>Title:工厂类</p > * <p>ClassName:MatchFactory</p > * @author kevin * @date 2021/1/26 */ public class MathFactory { private MathFactory() { //do nothing } /** * 获得具体的操作类型 * @author kevin * @param operator : * @return java.util.Optional<com.liu.test.math.MathOperation> * @date 2021/1/26 11:36 */ public static Optional<MathOperation> getOperation(String operator) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { //因为类名首字母大写,所以转换操作类型为类名格式 String operate = operator.substring(0,1).toUpperCase() + operator.substring(1).toLowerCase(); Class<?> operation = Class.forName("com.liu.test.math.operation." + operate+"Operation"); return Optional.of((MathOperation)operation.getDeclaredConstructor().newInstance()); } }
2.工厂方法模式:
工厂提供接口与实现,实例提供接口与实现
为了解决第一种简单工厂模式的缺陷,产生了工厂方法模式,把工厂方法再次进行抽象,
为不同的实现类,提供不同的工厂,通过实现抽象工厂接口类的方法,实现不同工厂获取
业务实现类的不同实例,调用的时候,通过判断,使用不同的工厂(在简单工厂模式基础上)
抽象一个工厂接口:
import java.util.Optional; public interface MathFactoryInterface { Optional<MathOperation> getOperation(String operator) ; }
工厂接口实现(顺序-加减乘除):
import com.liu.test.factory.simplefactory.MathOperation; import com.liu.test.factory.factorymethod.MathFactoryInterface; import com.liu.test.factory.simplefactory.operation.AddOperation; import java.util.Optional; public class AddFactory implements MathFactoryInterface { @Override public Optional<MathOperation> getOperation() { return Optional.of(new AddOperation()); } }
import com.liu.test.factory.simplefactory.MathOperation; import com.liu.test.factory.factorymethod.MathFactoryInterface; import com.liu.test.factory.simplefactory.operation.SubOperation; import java.util.Optional; public class SubFactory implements MathFactoryInterface { @Override public Optional<MathOperation> getOperation() { return Optional.of(new SubOperation()); } }
import com.liu.test.factory.factorymethod.MathFactoryInterface; import com.liu.test.factory.factorymethod.operation.MultiplyOperation; import com.liu.test.factory.simplefactory.MathOperation; import java.util.Optional; public class MultiplyFactory implements MathFactoryInterface { @Override public Optional<MathOperation> getOperation() { return Optional.of(new MultiplyOperation()); } }
import com.liu.test.factory.factorymethod.MathFactoryInterface; import com.liu.test.factory.factorymethod.operation.DivideOperation; import com.liu.test.factory.simplefactory.MathOperation; import java.util.Optional; public class DivideFactory implements MathFactoryInterface { @Override public Optional<MathOperation> getOperation() { return Optional.of(new DivideOperation()); } }
将原有的工厂类MathFactory删除,使用类中调整-增加方法:
/** * 工厂方法模式 * @author kevin * @param operator : * @return com.liu.test.math.factorymethod.MathFactoryInterface * @date 2021/1/26 18:41 */ private MathFactoryInterface getFactory(String operator){ MathFactoryInterface result = null; if("add".equals(operator)){ result = new AddFactory(); }else if("sub".equals(operator)){ result = new SubFactory(); }else if("multiply".equals(operator)){ result = new MultiplyFactory(); }else if("divide".equals(operator)){ result = new DivideFactory(); } return Optional.ofNullable(result).orElseThrow(() -> new IllegalArgumentException("未知的操作")); }
使用类中调整-更改调用方式:
double result; MathFactoryInterface factory = getFactory(operator); MathOperation operation = factory.getOperation().orElseThrow(() -> new IllegalArgumentException("未知的操作")); result = operation.apply(first, second); return String.valueOf(result);
3.抽象工厂模式:
提供工厂的接口与实现,提供实例的接口与实现,有不同类型的实例(每个类型下有多个实例)
就是将操作归类,然后分别提供接口,同类下的具体事物实现同一个接口。然后抽象一个工厂接口,
按照不同类别,提供不同的待实现工厂方法;再提供具体的工厂实现类,实现抽象的工厂接口,并在不
同的方法(同一类事物的获取方法)中根据入参返回同类事物中具体的事物,最后给到调用者执行。
比如,阿里与百度都有开发人员与产品人员:
首先定义开发人员接口、产品人员接口:
/** * * <p>Title:开发人员</p > * <p>ClassName:IDeveloper</p > * @author kevin * @date 2021/1/27 */ public interface IDeveloper { String work(); String skill(); }
/** * * <p>Title:产品人员</p > * <p>ClassName:IProductor</p > * @author kevin * @date 2021/1/27 */ public interface IProductor { String work(); String skill(); }
开发人员接口实现:
import com.liu.test.factory.abstractfactory.cases.IDeveloper; public class AliDeveloper implements IDeveloper { @Override public String work() { return "我是阿里开发人员,我的工作是:为阿里服务!"; } @Override public String skill() { return "我是阿里开发人员,我的技能是:java、python、vue、react、js、c、c++、c#......无所不能!"; } }
import com.liu.test.factory.abstractfactory.cases.IDeveloper; public class BaiduDeveloper implements IDeveloper { @Override public String work() { return "我是百度开发人员,我的工作是:为百度服务!"; } @Override public String skill() { return "我是百度开发人员,我的技能是:人工智能、java、python、vue、react、js、c、c++、c#......我也无所不能!"; } }
产品人员接口实现:
import com.liu.test.factory.abstractfactory.cases.IProductor; public class AliProductor implements IProductor { @Override public String work() { return "我是阿里产品,我的工作是:为阿里提供优秀的产品!"; } @Override public String skill() { return "我是阿里产品,我的技能是:需求与利益的平衡能力,缜密的逻辑思维和较高的业务理解能力!"; } }
import com.liu.test.factory.abstractfactory.cases.IProductor; public class BaiduProductor implements IProductor { @Override public String work() { return "我是百度产品,我的工作是:为百度提供优秀的产品!"; } @Override public String skill() { return "我是百度产品,我的技能是:需求与利益的平衡能力,缜密的逻辑思维和较高的业务理解能力!"; } }
定义工厂接口:
import com.liu.test.factory.abstractfactory.cases.IDeveloper; import com.liu.test.factory.abstractfactory.cases.IProductor; import java.lang.reflect.InvocationTargetException; public interface IFactory { IProductor getProductor(String type) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException; IDeveloper getDeveloper(String type) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException; }
阿里工厂接口实现(反射获得实例):
import com.liu.test.factory.abstractfactory.IFactory; import com.liu.test.factory.abstractfactory.cases.IDeveloper; import com.liu.test.factory.abstractfactory.cases.IProductor; import java.lang.reflect.InvocationTargetException; import java.util.Optional; public class AliFactory implements IFactory { @Override public IProductor getProductor(String type) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //因为类名首字母大写,所以转换操作类型为类名格式 String operate = type.substring(0,1).toUpperCase() + type.substring(1).toLowerCase(); Class<?> operation = Class.forName("com.liu.test.factory.abstractfactory.cases.impl." + operate + "Productor"); return Optional.of((IProductor)operation.getDeclaredConstructor().newInstance()).orElseThrow(() -> new IllegalArgumentException("未知的公司")); } @Override public IDeveloper getDeveloper(String type) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //因为类名首字母大写,所以转换操作类型为类名格式 String operate = type.substring(0,1).toUpperCase() + type.substring(1).toLowerCase(); Class<?> operation = Class.forName("com.liu.test.factory.abstractfactory.cases.impl." + operate + "Developer"); return Optional.of((IDeveloper)operation.getDeclaredConstructor().newInstance()).orElseThrow(() -> new IllegalArgumentException("未知的公司")); } }
百度工厂接口实现(反射获得实例):
import com.liu.test.factory.abstractfactory.IFactory; import com.liu.test.factory.abstractfactory.cases.IDeveloper; import com.liu.test.factory.abstractfactory.cases.IProductor; import java.lang.reflect.InvocationTargetException; import java.util.Optional; public class BaiduFactory implements IFactory { @Override public IProductor getProductor(String type) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //因为类名首字母大写,所以转换操作类型为类名格式 String operate = type.substring(0,1).toUpperCase() + type.substring(1).toLowerCase(); Class<?> operation = Class.forName("com.liu.test.factory.abstractfactory.cases.impl." + operate + "Productor"); return Optional.of((IProductor)operation.getDeclaredConstructor().newInstance()).orElseThrow(() -> new IllegalArgumentException("未知的公司")); } @Override public IDeveloper getDeveloper(String type) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //因为类名首字母大写,所以转换操作类型为类名格式 String operate = type.substring(0,1).toUpperCase() + type.substring(1).toLowerCase(); Class<?> operation = Class.forName("com.liu.test.factory.abstractfactory.cases.impl." + operate + "Developer"); return Optional.of((IDeveloper)operation.getDeclaredConstructor().newInstance()).orElseThrow(() -> new IllegalArgumentException("未知的公司")); } }
通过调用不同的抽象工厂的实现获得具体的实例,执行方法得到想要的结果。
String result = ""; //获得具体的工厂(反射) String operate = operator.substring(0,1).toUpperCase() + operator.substring(1).toLowerCase(); Class<?> operation = Class.forName("com.liu.test.factory.abstractfactory.factory." + operate + "Factory"); IFactory factory = (IFactory)operation.getDeclaredConstructor().newInstance(); //通过工厂获得公司开发人员 IDeveloper developer = factory.getDeveloper(operate); result += developer.work() +"\n"; result += developer.skill() +"\n"; //通过工厂获得公司产品人员 IProductor productor = factory.getProductor(operate); result += productor.work() +"\n"; result += productor.skill() +"\n"; return result;
-
Java设计模式之工厂模式分析【简单工厂、工厂方法、抽象工厂】
2020-08-27 15:41:15主要介绍了Java设计模式之工厂模式,结合实例形式分析了简单工厂、工厂方法、抽象工厂等相关功能、实现与使用方法,需要的朋友可以参考下 -
Java简单工厂模式定义与用法实例分析
2020-08-25 19:05:13主要介绍了Java简单工厂模式定义与用法,结合实例形式分析了java简单工厂模式的相关定义与使用技巧,并给出了原理类图进行总结,需要的朋友可以参考下 -
java抽象工厂模式实例----手机工厂
2014-12-22 17:45:11java设计模式之抽象工厂模式,实例----手机工厂,一个简单的例子,有助于理解抽象工厂模式。 -
java简单工厂模式源码实例
2013-01-02 20:37:32java简单工厂模式源码实例,可用于java简单工厂模式学习! -
Java设计模式之创建型:工厂模式详解(简单工厂+工厂方法+抽象工厂)
2021-09-12 17:57:40工厂模式将目的将创建对象的具体过程屏蔽隔离起来,从而达到更高的灵活性,工厂模式可以分为三类:简单工厂模式、工厂方法模式、抽象工厂模式;简单工厂模式的核心是定义一个创建对象的接口,将对象的创建和本身的...在面向对象编程中,创建对象实例最常用的方式就是通过 new 操作符构造一个对象实例,但在某些情况下,new 操作符直接生成对象会存在一些问题。举例来说,对象的创建需要一系列的步骤:可能需要计算或取得对象的初始位置、选择生成哪个子对象实例、或在生成之前必须先生成一些辅助对象。 在这些情况,新对象的建立就是一个 “过程”,而不仅仅是一个操作,就像一部大机器中的一个齿轮传动。
针对上面这种情况,我们如何轻松方便地构造对象实例,而不必关心构造对象示例的细节和复杂过程?解决方案就是使用一个工厂类来创建对象。
一、什么是工厂模式:
工厂模式将目的将创建对象的具体过程屏蔽隔离起来,从而达到更高的灵活性,工厂模式可以分为三类:
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Method)
- 抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。《设计模式》一书中将工厂模式分为两类:工厂方法模式与抽象工厂模式。将简单工厂模式看为工厂方法模式的一种特例,两者归为一类。 我们先从以下案例对工厂模式做个初步的了解:
(1)在没有工厂的时代,如果客户需要一款宝马车,那么就需要客户去创建一款宝马车,然后拿来用。
(2)简单工厂模式:后来出现了工厂,用户不再需要去创建宝马车,由工厂进行创建,想要什么车,直接通过工厂创建就可以了。比如想要320i系列车,工厂就创建这个系列的车。
(3)工厂方法模式:为了满足客户,宝马车系列越来越多,如320i、523i等等系列,一个工厂无法创建所有的宝马系列,于是又单独分出来多个具体的工厂,每个具体工厂创建一种系列,即具体工厂类只能创建一个具体产品。但是宝马工厂还是个抽象,你需要指定某个具体的工厂才能生产车出来。
(4)抽象工厂模式:随着客户要求越来越高,宝马车必须配置空调,于是这个工厂开始生产宝马车和需要的空调。最终是客户只要对宝马的销售员说:我要523i空调车,销售员就直接给他523i空调车了。而不用自己去创建523i空调车宝马车。
下面我们就针对几种不同的工厂模式进行详细的说明:
二、简单工厂模式:
简单工厂模式的核心是定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可。
如果不使用工厂,用户将自己创建宝马车,具体UML图和代码如下:
public class BMW320 { public BMW320(){ System.out.println("制造-->BMW320"); } } public class BMW523 { public BMW523(){ System.out.println("制造-->BMW523"); } } public class Customer { public static void main(String[] args) { BMW320 bmw320 = new BMW320(); BMW523 bmw523 = new BMW523(); } }
用户需要知道怎么创建一款车,这样子客户和车就紧密耦合在一起了,为了降低耦合,就出现了简单工厂模式,把创建宝马的操作细节都放到了工厂里,而客户直接使用工厂的创建方法,传入想要的宝马车型号就行了,而不必去知道创建的细节。
1、简单工厂模式的UML图:
- 工厂类角色: 该模式的核心,用来创建产品,含有一定的商业逻辑和判断逻辑
- 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
- 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
2、代码实现:
产品类:
abstract class BMW { public BMW(){} } public class BMW320 extends BMW { public BMW320() { System.out.println("制造-->BMW320"); } } public class BMW523 extends BMW{ public BMW523(){ System.out.println("制造-->BMW523"); } }
工厂类:
public class Factory { public BMW createBMW(int type) { switch (type) { case 320: return new BMW320(); case 523: return new BMW523(); default: break; } return null; } }
用户类:
public class Customer { public static void main(String[] args) { Factory factory = new Factory(); BMW bmw320 = factory.createBMW(320); BMW bmw523 = factory.createBMW(523); } }
3、简单工厂模式的优缺点:
简单工厂模式提供专门的工厂类用于创建对象,实现了对象创建和使用的职责分离,客户端不需知道所创建的具体产品类的类名以及创建过程,只需知道具体产品类所对应的参数即可,通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
但缺点在于不符合“开闭原则”,每次添加新产品就需要修改工厂类。在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
为了解决简单工厂模式的问题,出现了工厂方法模式。
三、工厂方法模式:
工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。在使用时,用于只需知道产品对应的具体工厂,关注具体的创建过程,甚至不需要知道具体产品类的类名,当我们选择哪个具体工厂时,就已经决定了实际创建的产品是哪个了。
但缺点在于,每增加一个产品都需要增加一个具体产品类和实现工厂类,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
1、工厂方法的 UML 结构图如下:
- 抽象工厂 AbstractFactory: 工厂方法模式的核心,是具体工厂角色必须实现的接口或者必须继承的父类,在 Java 中它由抽象类或者接口来实现。
- 具体工厂 Factory:被应用程序调用以创建具体产品的对象,含有和具体业务逻辑有关的代码
- 抽象产品 AbstractProduct:是具体产品继承的父类或实现的接口,在 Java 中一般有抽象类或者接口来实现。
- 具体产品 Product:具体工厂角色所创建的对象就是此角色的实例。
2、代码实现:
产品类:
abstract class BMW { public BMW(){} } public class BMW320 extends BMW { public BMW320() { System.out.println("制造-->BMW320"); } } public class BMW523 extends BMW{ public BMW523(){ System.out.println("制造-->BMW523"); } }
工厂类:
interface FactoryBMW { BMW createBMW(); } public class FactoryBMW320 implements FactoryBMW{ @Override public BMW320 createBMW() { return new BMW320(); } } public class FactoryBMW523 implements FactoryBMW { @Override public BMW523 createBMW() { return new BMW523(); } }
客户类:
public class Customer { public static void main(String[] args) { FactoryBMW320 factoryBMW320 = new FactoryBMW320(); BMW320 bmw320 = factoryBMW320.createBMW(); FactoryBMW523 factoryBMW523 = new FactoryBMW523(); BMW523 bmw523 = factoryBMW523.createBMW(); } }
四、抽象工厂模式:
在工厂方法模式中,我们使用一个工厂创建一个产品,一个具体工厂对应一个具体产品,但有时候我们需要一个工厂能够提供多个产品对象,而不是单一的对象,这个时候我们就需要使用抽象工厂模式。
在介绍抽象工厂模式前,我们先厘清两个概念:
- 产品等级结构:产品等级结构指的是产品的继承结构,例如一个空调抽象类,它有海尔空调、格力空调、美的空调等一系列的子类,那么这个空调抽象类和他的子类就构成了一个产品等级结构。
- 产品族:产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。比如,海尔工厂生产海尔空调、海尔冰箱,那么海尔空调则位于空调产品族中。
产品等级结构和产品族结构示意图如下:
1、什么是抽象工厂模式:
抽象工厂模式主要用于创建相关对象的家族。当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,能够保证客户端始终只使用同一个产品族中的对象;并且通过隔离具体类的生成,使得客户端不需要明确指定具体生成类;所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
但该模式的缺点在于添加新的行为时比较麻烦,如果需要添加一个新产品族对象时,需要更改接口及其下所有子类,这必然会带来很大的麻烦。
2、UML结构图:
- 抽象工厂 AbstractFactory:定义了一个接口,这个接口包含了一组方法用来生产产品,所有的具体工厂都必须实现此接口。
- 具体工厂 ConcreteFactory:用于生产不同产品族,要创建一个产品,用户只需使用其中一个工厂进行获取,完全不需要实例化任何产品对象。
- 抽象产品 AbstractProduct:这是一个产品家族,每一个具体工厂都能够生产一整组产品。
- 具体产品 Product
3、代码实现:
通过抽象工厂模式,我们可以实现以下的效果:比如宝马320系列使用空调型号A和发动机型号A,而宝马230系列使用空调型号B和发动机型号B,在为320系列生产相关配件时,就无需制定配件的型号,它会自动根据车型生产对应的配件型号A。
也就是说,当每个抽象产品都有多于一个的具体子类的时候(空调有型号A和B两种,发动机也有型号A和B两种),工厂角色怎么知道实例化哪一个子类呢?抽象工厂模式提供两个具体工厂角色(宝马320系列工厂和宝马230系列工厂),分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化,每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。
产品类:
//发动机以及型号 public interface Engine {} public class EngineA implements Engine{ public EngineA(){ System.out.println("制造-->EngineA"); } } public class EngineB implements Engine{ public EngineB(){ System.out.println("制造-->EngineB"); } } //空调以及型号 public interface Aircondition {} public class AirconditionA implements Aircondition{ public AirconditionA(){ System.out.println("制造-->AirconditionA"); } } public class AirconditionB implements Aircondition{ public AirconditionB(){ System.out.println("制造-->AirconditionB"); } }
创建工厂类:
//创建工厂的接口 public interface AbstractFactory { //制造发动机 public Engine createEngine(); //制造空调 public Aircondition createAircondition(); } //为宝马320系列生产配件 public class FactoryBMW320 implements AbstractFactory{ @Override public Engine createEngine() { return new EngineA(); } @Override public Aircondition createAircondition() { return new AirconditionA(); } } //宝马523系列 public class FactoryBMW523 implements AbstractFactory { @Override public Engine createEngine() { return new EngineB(); } @Override public Aircondition createAircondition() { return new AirconditionB(); } }
客户:
public class Customer { public static void main(String[] args){ //生产宝马320系列配件 FactoryBMW320 factoryBMW320 = new FactoryBMW320(); factoryBMW320.createEngine(); factoryBMW320.createAircondition(); //生产宝马523系列配件 FactoryBMW523 factoryBMW523 = new FactoryBMW523(); factoryBMW523.createEngine(); factoryBMW523.createAircondition(); } }
工厂模式小结:
1、工厂方法模式与抽象工厂模式的区别在于:
(1)工厂方法只有一个抽象产品类和一个抽象工厂类,但可以派生出多个具体产品类和具体工厂类,每个具体工厂类只能创建一个具体产品类的实例。
(2)抽象工厂模式拥有多个抽象产品类(产品族)和一个抽象工厂类,每个抽象产品类可以派生出多个具体产品类;抽象工厂类也可以派生出多个具体工厂类,同时每个具体工厂类可以创建多个具体产品类的实例
设计模式系列文章:
参考文章:
设计模式读书笔记----简单工厂模式_chenssy 的技术博客-CSDN博客
设计模式读书笔记----工厂方法模式_chenssy 的技术博客-CSDN博客
-
Java设计模式:简单工厂模式(附实例代码)每天一学设计模式
2022-01-10 14:37:47简单工厂模式又称为静态工厂模式:定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有相同的父类。虽然不属于23中设计模式其一,但是经常会被使用。 /**Product抽象产品角色*/ public...1.简单工厂模式又称为静态工厂模式:定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有相同的父类。虽然不属于23中设计模式其一,但是经常会被使用。
/**Product抽象产品角色*/ public abstract class Product{ //所有产品类的公共业务方法 public void methodSame(){ //公共方法的实现 } //声明抽象业务方法 public abstract void methodDiff(); }
/**具体抽象产品类*/ public class ConcreateProduct extends Product{ //实现业务方法 public void methodDiff(){ //业务方法的实现 } }
/**工厂类*/ public class Factory{ //静态工厂方法 public static Product getProduct(String arg){ Product product = null; if(arg.equalsIgnoreCase("A")){ product = new ConcreateProductA(); //初始化设置product } else if(arg.equalsIgnoreCase("B")){ product = new ConcreateProductB(); //初始化设置product } return product; } }
/***在客户端测试*/ public class Client{ public static void main(String args[]){ Product product; product = Factory.getProduct("A");//通过工厂类创建产品对象 product.methodSame(); product.methodDiff(); } }
简单工厂模式的核心是工厂类,在没有工厂类之前,客户端一般会使用new关键字之间创建对象,而引入工厂类之后客户端可以通过工厂类来创建产品。
2.简单工厂模式实例描述:一个果篮中有一些水果,小明想吃水果时不用去其他地方去拿,只用在果篮里取就可以。所以要创建一个比较有灵活性的果篮,可以方便的忘果篮中添加或者取出水果。这个果篮就充当工厂。下面代码中Fruit即充当果篮。
/**抽象水果接口,充当抽象产品类*/ public interface Fruit { public void eat(); } /**苹果类,充当具体产品类*/ public class Apple implements Fruit { public Apple(){ System.out.println("拿来了一个苹果"); } @Override public void eat() { System.out.println("吃苹果"); } } /**桔子类,充当具体产品类*/ public class Orange implements Fruit { public Orange(){ System.out.println("拿来了一个桔子"); } @Override public void eat() { System.out.println("吃桔子"); } } /**香蕉类,充当具体产品类*/ public class Banana implements Fruit { public Banana(){ System.out.println("拿来了一个香蕉"); } @Override public void eat() { System.out.println("吃香蕉"); } } /**水果工厂类,充当工厂类*/ public class FruitFactory { public static Fruit getFruit(String type){ Fruit fruit = null; if(type.equalsIgnoreCase("apple")){ fruit = new Apple(); System.out.println("洗苹果"); } else if(type.equalsIgnoreCase("orange")){ fruit = new Banana(); System.out.println("洗桔子"); } else if(type.equalsIgnoreCase("banana")){ fruit = new Orange(); System.out.println("洗香蕉"); } return fruit; } } /**客户端测试*/ public class Client{ public static void main(String args[]){ Fruit chart; chart = FruitFactory.getFruit("apple");//通过静态工厂方法创建产品,还可以换为orange或者banner chart.eat(); } }
实例结果:
3.反思:但是有一个问题就是如果想在客户端修改图表的类型需要在客户端代码上修改,违反了开闭原则,解决方法之一是可以将静态工厂方法的参数存储到XML文件中,通过XML.Util来获取字符串。在客户端引用获取到的字符串来创建图表。
所有的工厂模式都强调一点:两个类A和B之间的关系应该仅仅只是A创建B或者A使用B,而不能两种关系都有,将对象的创建和使用分离,使得系统更加符合单一职责原则,有利于对系统的复用和系统的维护。
简单工厂模式的简化可以将抽象产品类和工厂类合并,将静态工厂方法移至抽象产品类中。
-
JAVA工厂方法模式
2016-10-15 10:53:57基础知识讲解分析+工厂模式实例代码以及分析,浅显易懂,不会辜负你的三分 -
Java工厂模式
2021-09-11 15:08:37Java工厂模式 介绍 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,... -
JAVA设计模式之抽象工厂模式案例
2017-07-09 13:20:52抽象工厂模式 JAVA设计模式 -
java23种设计模式+23个实例demo
2018-09-03 13:28:11java23种设计模式+23个实例demo: 关于代码的几点说明: 1. 代码为根据个人对Design Pattern的学习理解写出, 2. 每个Pattern均是一个目录,其目录名即是Pattern的名字, 所有代码用JDeveloper 9i 和JBuilder 6.0编写... -
java-简单工厂模式实例及讲解
2019-05-15 18:55:40工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个... -
java三种工厂模式文档+三个实例.rar
2015-01-24 00:18:54java三种工厂模式文档+三个实例,里面有个word文档是学习文档 然后配套有三个项目学习 -
实例解析Java单例模式编程中对抽象工厂模式的运用
2020-09-02 20:08:12主要介绍了实例解析Java单例模式编程中对抽象工厂模式的运用,抽象工厂模式可以看作是工厂方法模式的升级版,本需要的朋友可以参考下 -
java抽象工厂模式源码实例
2012-01-07 18:31:09本人大四,根据老师要求写的一份抽象工厂模式的例子。你们下载下来导入myclipse中即可使用。其中在测试Test.java中,你们可以看看运行效果 -
java工厂模式
2021-02-12 08:51:50java工厂模式分三种:简单工厂模式、工厂方法模式、抽象工厂模式。简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建... -
java 三种工厂模式(简单工厂+工厂方法+抽象工厂)
2019-06-04 10:51:15因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法模式,它属于类创建型模式。 工厂模式结构图 简单工厂模式角色 在简单工厂模式结构图中包含如下几个角色: ...