实际开发中,接口的主要作用是为了不用层提供有一个操作的标准,如果直接实例化了类的操作【用new关键字来实例化】,则一定存在耦合问题,可以用工厂模式解决此问题。

接下来用一个店主开早餐店的经历来阐述反射与工厂模式。

店主的经历如下:简单的早餐店 --> 增加西式早餐 --> 多种早餐需求 --> 拓展业务。

简单的早餐店

店主起初想开个简单的早餐店,就经营简单的早餐业务,所以创建了一个简单的工厂来生产对应的早餐服务。

BreakfastService

package javabase.service;
public interface BreakfastService {void cookIt();
}

Breakfast

package javabase.entity;
import javabase.service.BreakfastService;
public class Breakfast implements BreakfastService {@Overridepublic void cookIt() {System.out.println("====我正在做一份美味的早餐呢!====>");}
}

MyFactory

package javabase.factory;
import javabase.entity.Breakfast;
import javabase.service.BreakfastService;
public class Myfactory {private Myfactory(){}public static BreakfastService getBreakFast(String name){//判断传来的是否是美味的早餐的名字if("Breakfast".equals(name)){//如果是则返回对应的实例化对象return new Breakfast();}return null;}
}

Main

package javabase;
import javabase.factory.Myfactory;
import javabase.service.BreakfastService;
public class Main {public static void main(String[] args) {//开始买早餐咯BreakfastService breakfastService = Myfactory.getBreakFast("Breakfast");breakfastService.cookIt();}
}

运行结果

====我正在做一份美味的早餐呢!====>

增加西式早餐

店主开店之后,生意火爆,有顾客跟店长反应,要不再开多一个西式的早餐业务?店主想了想,如果品种再多一点的话,说不定客户会更多呢!于是就创建了对应的西式早餐服务,然后再添加到对应的工厂里。

EastBreakfast

package javabase.entity;
import javabase.service.BreakfastService;
public class EastBreakfast implements BreakfastService {@Overridepublic void cookIt() {System.out.println("====我正在做一份美味的西式早餐呢!====>");}
}

那么店主的工厂得开始加工了,再来生产西式早餐。

MyFactory

package javabase.factory;
import javabase.entity.Breakfast;
import javabase.entity.EastBreakfast;
import javabase.service.BreakfastService;
public class Myfactory {private Myfactory(){}public static BreakfastService getBreakFast(String name){//根据客户端传入的名字来判断客户端需要什么早餐if("Breakfast".equals(name)){//返回普通早餐的实例化return new BreakFast();}else if("EastBreakfast".equals(name)){//返回西式早餐的实例化return new EastBreakfast();}return null;}
}

Main

package javabase;
import javabase.factory.Myfactory;
import javabase.service.BreakfastService;
public class Main {public static void main(String[] args) {//生产美味的早餐BreakfastService breakfastService = Myfactory.getBreakFast("Breakfast");breakfastService.cookIt();//生产美味的西式早餐BreakfastService eastBreakfast = Myfactory.getBreakFast("EastBreakfast");eastBreakfast.cookIt();}
}

运行结果

====我正在做一份美味的早餐呢!====>
====我正在做一份美味的西式早餐呢!====>

多种早餐需求

要知道,顾客就是上帝,近期许多顾客都向店主提要求说要中式早餐,日式早餐等不同品种的早餐?要是像增加西式早餐那样直接添加对应的实例化西式早餐对象代码的话,日后代码就变得冗长且难读,而且会浪费大量的时间在阅读工厂代码以及修改工厂代码上。如果每天店主都这样工作的话,恐怕会英年早逝。

这次店长灵光一闪,想到用反射来进行获取对应的早餐,所以工厂的代码修改如下。

MyFactory

//少了两行import *^_^*
package javabase.factory;
import javabase.service.BreakfastService;
public class Myfactory {private Myfactory(){}public static BreakfastService getBreakFast(String breakfastName){BreakfastService breakfastService = null;try {/***  使用反射的方式来获取对应的早餐实例化对象*  使用Class的static方法forName(name)获取Class的实例化对象*  再调用newInstance()方法来实例化BreakfastService*  最后再进行类型转化*/breakfastService = (BreakfastService)Class.forName(breakfastName).newInstance();} catch (Exception e) {//如果出现任何异常直接返回nullreturn null;}return breakfastService;}
}

Main

package javabase;
import javabase.factory.Myfactory;
import javabase.service.BreakfastService;
public class Main {public static void main(String[] args) {//生产美味的早餐,这次需要传递的就是完整的类名了【包.类】,就不能简单地写类名了BreakfastService breakfastService = Myfactory.getBreakFast("javabase.entity.Breakfast");breakfastService.cookIt();//生产美味的西式早餐BreakfastService eastBreakfastService = Myfactory.getBreakFast("javabase.entity.EastBreakfast");eastBreakfastService.cookIt();}
}

运行结果

====我正在做一份美味的早餐呢!====>
====我正在做一份美味的西式早餐呢!====>

这时,店主再加入中式早餐服务,则不需要再修改对应的工厂类。

ChineseBreakfast

package javabase.entity;import javabase.service.BreakfastService;public class ChineseBreakfast implements BreakfastService {@Overridepublic void cookIt() {System.out.println("====我正在做一份美味的中式早餐呢!====>");}
}

Main

package javabase;
import javabase.factory.Myfactory;
import javabase.service.BreakfastService;
public class Main {public static void main(String[] args) {//生产美味的早餐,这次需要传递的就是完整的类名了【包.类】,就不能简单地串类名了BreakfastService breakfastService = Myfactory.getBreakFast("javabase.entity.Breakfast");breakfastService.cookIt();//生产美味的西式早餐BreakfastService eastBreakfastService = Myfactory.getBreakFast("javabase.entity.EastBreakfast");eastBreakfastService.cookIt();//生产中式早餐BreakfastService chineseBreakfastService = Myfactory.getBreakFast("javabase.entity.ChineseBreakfast");chineseBreakfastService.cookIt();}
}

运行结果

====我正在做一份美味的早餐呢!====>
====我正在做一份美味的西式早餐呢!====>
====我正在做一份美味的中式早餐呢!====>

拓展业务

通过反射的机制,店长有了更多的时间来进行思考其他的事,时间也更加充裕了。店长又突发奇想,如果我们的店再兼做午餐和晚餐会怎样呢?加多几个工厂如何?可是如果未来要发展更多的餐饮业务,就要加更多个工厂,那每个工厂维护起来,岂不是要麻烦死,店长可不想因为此事而秃顶。店长经过上次经历后,决定,用泛型加反射来搞事情。

所以店长又再次决定修改工厂代码,加入泛型。

MyFactory

package javabase.factory;
import javabase.service.BreakfastService;
public class Myfactory {private Myfactory(){}public static <T> T getService(String serviceName){T service = null;try {/***  使用反射的方式来获取对应的早餐实例化对象*  使用Class的static方法forName(name)获取Class的实例化对象*  再调用newInstance()方法来实例化BreakfastService*  最后再进行类型转化,这里用泛型的转化*/service = (T) Class.forName(serviceName).newInstance();} catch (Exception e) {//如果出现任何异常直接返回nullreturn null;}return service;}
}

此时,店长再加入午餐业务

LunchService

package javabase.service;
public interface LunchService {void cookLunch();
}

加入中式午餐服务

package javabase.entity;
import javabase.service.LunchService;
public class ChineseLunch implements LunchService {@Overridepublic void cookLunch() {System.out.println("====我正在做一份不一样的中式午餐呢!====>");}
}

两种业务进行,同个工厂进行生产两种不同的业务

Main

package javabase;
import javabase.factory.Myfactory;
import javabase.service.BreakfastService;
import javabase.service.LunchService;
import java.util.List;public class Main {public static void main(String[] args) {//生产中式早餐 --->早餐业务BreakfastService breakfastService = Myfactory.getService("javabase.entity.ChineseBreakfast");breakfastService.cookIt();//生产中式午餐 --->午餐业务LunchService lunchService = Myfactory.getService("javabase.entity.ChineseLunch");lunchService.cookLunch();}
}

运行结果

====我正在做一份美味的中式早餐呢!====>
====我正在做一份不一样的中式午餐呢!====>

最后,店主总算是可以拓展不同的餐饮领域了,不用再操心工厂生产的事咯!

总结

1.使用反射可以获取实例化对象的内容,与工厂模式结合能大大的减少代码中实例化对象的耦合。

2.最后使用泛型,而不直接使用Object呢?实际上最后的代码用Object也是可行的,但是在使用的时候要强制转化类型,而泛型则不用,相对来说,编译也会相对于Object安全。讲得通俗点就是,人家java底层开发人员开发出来个比原来还差的东西岂不是要被喷死。

3.代码的实用性以及扩展性,实用反射和泛型之后,能够很好的遵守开闭原则,就尽量减少对原来代码的修改。

4.减少代码的冗余,是检验代码质量的最基本要求,最好就做到高复用,低耦合啦。

5.代码的复制粘贴可能会有错误,参考的游客可以自行尝试敲下代码增加下印象,如果这篇博客能帮助你理解反射与工厂模式之间的关系就更好了。

反射与工厂模式:早餐店的发展之路相关推荐

  1. 设计模式之工厂类模式总结对比、简单工厂模式、工厂方法模式、抽象工厂模式、带反射的工厂模式、例子代码分析、最详细

    1. 题目 假设某公司同时用SqlServer.MySql数据库,即会切换两数据库(不同数据库的sql语句有些许差异),同时,两数据库里均有对Users.Departments表的操作(sql代码不一 ...

  2. Java的反射机制 工厂模式综合讲解【转载自51CTO】

    2019独角兽企业重金招聘Python工程师标准>>> Java的反射机制 工厂模式综合讲解 1.什么叫反射 Java.lang.reflect包下 正常情况下我们可以通过类实例化一 ...

  3. C#三层架构第九课之反射和工厂模式实现多数据库访问

    反射和工厂模式实现不同数据库访问 在之前上课的基础上,使用反射和模唱模式,实现针对不同数据库的动态访问. 在之前的三层架构代码基础上进行修改. 使用三层架构+工厂模式,来实现一个程序访问多个数据库. ...

  4. java 反射实现 工厂模式_java – 用反射实现工厂模式

    我正在实施工厂模式这是我的工厂类: class ProductFactory { private HashMap m_RegisteredProducts = new HashMap(); publi ...

  5. 设计模式(5)--三种工厂模式(披萨店)

    工厂方法 工厂方法 Intent 定义了一个创建对象的接口,但是由子类决定要实例化的类是哪一个.工厂方法让类把是实例化推迟到子类. 抽象工厂 Intent 提供一个接口,用于创建相关或依赖对象的家族, ...

  6. 设计模式-创建型模式-工厂模式(工厂三兄弟)

    设计模式-创建型模式-工厂模式(工厂三兄弟) 工厂模式分为简单工厂,工厂方法,抽象工厂. 简单工厂模式 一个接口,三个具体类,一个工厂,通过选择,生产出对应的对象. package demo2;pub ...

  7. C#之三十九 抽象工厂模式

    在软件系统中,经常面临着"一系列相互依赖的对象"的创建工作:同时由于需求的变化,往往存在着更多系列对象的创建工作.如何应对这种变化?如何绕过常规的对象的创建方法(new),提供一种 ...

  8. 设计模式之工厂方法模式、抽象工厂模式的概念和实现及使用“反射技术+读取配置文件”的方法对工厂模式进行改进(软件工程综合实践课程第三周个人作业)

    文章目录 一.实验目的 二.知识总结 1.工厂方法模式简介 2.抽象工厂模式简介 3.工厂模式小结 4.利用"反射技术+读取配置文件"的方法改进程序 三.实验内容 1. 工厂模式实 ...

  9. 三十八,反射的应用:工厂模式

    2019独角兽企业重金招聘Python工程师标准>>> 1.通过反射调用类中的方法 示例: Person类: package com.ares.demo;interface Info ...

最新文章

  1. JavaScript的编译模式
  2. 文本文件 java,java 写文本文件
  3. 光复用技术中三种重要技术_传感器在机器人技术研究发展历程中扮演着重要角色...
  4. hive与hbase的以及mongodb和cassandra区别整理
  5. java switch case怎么判断范围_java小白从入门到精通(基础二)
  6. ruby 批量下载王者荣耀皮肤
  7. 爬虫 - scrapy框架设置代理
  8. 手挽手带你学VUE:四档 Vue-cli3 Vuex Vue-router
  9. 红米3s进不了recovery_红米手机3S/3X刷recovery教程及第三方recovery下载
  10. UE4 UE5学习和资源网站整理
  11. 怎么做视频伪原创 快手视频修改md5
  12. 关于修复Office图标白色的问题
  13. 2021-2027全球及中国结构光源三维扫描仪行业研究及十四五规划分析报告
  14. Pta题目集:汽车加油问题 (20 分)
  15. Confluence 查看文档乱码问题
  16. 基于ArcGIS JS API实现的两种距离和面积测量方式
  17. MongoDB——聚合管道之$project操作
  18. C++程序闪退原因定位
  19. 网络编程培训之六 使用原始套接字实现Ping
  20. Scale-Equalizing Pyramid Convolution for Object Detection论文阅读

热门文章

  1. PS占用CPU太高,导致电脑异常卡顿
  2. 棒材轧机轧制力矩matlab数学模型,轧钢厂棒材轧制工艺及装备.ppt
  3. xp桌面上的计算机管理,xp系统纯净版使用“计算器管理”导致桌面崩溃如何解决...
  4. 建木入选开源GitOps产业联盟生态图第一版
  5. 分享:nuxt个性化特定页面的 Meta 标签
  6. linux 基础 基础命令及解压
  7. docker-compose实现php环境安装
  8. Ruby for SketchUp之Entities对象
  9. 线性动力学变分原理基础 Part1
  10. speedtest-cli网络测速