java设计模式(工厂模式)
来源:互联网 发布:数控编程招聘的视频 编辑:程序博客网 时间:2024/06/16 21:38
代码说明(版本 1)
比如苹果、橙子都是水果,那么可以定义一个水果工厂,工厂中有个方法叫做榨果汁,如果传入的水果为苹果,那么就榨出来苹果汁,如果是橙子那就榨出来橙汁。
按照之前我的写法是这样的
public abstract class Fruit { abstract void makeJuice();}
这个没什么好说的,我们假设水果可以榨自己成为果汁,所以给它弄一个 makeJuice 榨果汁
方法。
然后对应的两个实现类,分别榨出属于自己的果汁。
public class Apple extends Fruit { @Override void makeJuice() { System.out.println("榨苹果汁了,快来喝"); }}
public class Orange extends Fruit { @Override void makeJuice() { System.out.println("榨橙汁了,快来喝"); }}
当然,水果不是凭空得来的,得有对应的工厂去生产它,所以我们再写一个工厂类。
public abstract class AbstractFactory { abstract Fruit create(String className);}
这里定义了一个抽象工厂,主要是因为,可能会有多个苹果工厂来生产苹果。
public class FruitFactory extends AbstractFactory { @Override public Fruit create(String className) { if ("apple".equals(className)) return new Apple(); if ("orange".equals(className)) return new Orange(); return null; }}
水果工厂也定义好了,现在只需要客户端去调用就可以生产水果了。
public class FruitClient { public static void main(String[] args) { FruitFactory fruitFactory = new FruitFactory(); Fruit apple = fruitFactory.create("apple"); Fruit orange = fruitFactory.create("orange"); apple.makeJuice(); orange.makeJuice(); }}
执行我们的 main
方法,客户端依次打印出
以上其实就是一个工厂模式。
问题:如果这时候新来了西瓜,需求说现在要榨西瓜汁了,该怎么办?
想都不用想,二话不说,我们新增一个西瓜类
public class Watermelon extends Fruit { @Override void makeJuice() { System.out.println("榨西瓜汁了,要来喝吗?"); }}
然后修改我们的工厂类,改后的代码如下:
public class FruitFactory extends AbstractFactory { @Override public Fruit create(String className) { if ("apple".equals(className)) return new Apple(); if ("orange".equals(className)) return new Orange(); if ("watermelon".equals(className)) return new Watermelon(); return null; }}
最后修改我们的客户端,增加一个
这样我们就创建了一个西瓜,然后调用 watermelon.makeJuice()
就能榨西瓜汁了。
一切看起来都是那么完美,直到……
直到项目经理告诉你说,现在又新来了几种水果。
这时候就有问题了,我们发现每次一新来水果,我们的工厂类就要改变,这不正是违反了开闭原则吗?
开闭原则(对扩展开放,对修改关闭),简单来说,就是对于新的需求,尽量在原有的类上拓展,比如继承,然后重写原来的方法等,尽量不要在原有的类上进行修改,因为 bug 不仅是写出来的,也是改出来的。
并且既然都是工厂类了,我们肯定希望它能稳定点,总是变来变去,说不准哪天就倒闭了呢?
代码说明(版本 2)
版本 1 的代码既然违反了开闭原则,那么我们就来修复它。
可以看到,造成我们反复修改工厂类的主要原因是,每新来一种水果,我们就要将水果的名称传入,然后 new
对应的实例。
那么可不可以,不需要我们主动判断实例类型,不用显式地去 new
对应的实例呢?可不可以在程序运行的时候,能够自动获取到对应的实例呢?
答案是肯定的。这个时候就要有请开着上帝模式的反射登场了。
利用反射机制,我们可以获取到类的各种信息,比如类型,方法,参数,属性,还能修改访问权限等。
总之,反射好像做啥都行,我们这里要创造一个实例,很简单啊,反射给你做!
修改我们的代码:
public abstract class AbstractFactory { abstract <T extends Fruit> T create(Class<T> c);}
注意,这里我们的参数由之前的 String
改成了 Class<T>
,主要就是实现反射时候需要用到类名。然后修改我们的具体实现类。
public class FruitFactory extends AbstractFactory { @Override <T extends Fruit> T create(Class<T> c) { try { return (T) Class.forName(c.getName()).newInstance(); } catch (Exception e) { e.printStackTrace(); } return null; }}
这样,在程序运行时,就会利用反射机制自动为我们创建对应的实例。
获取实例的几种方式
Object.class
直接调用对象的.class
Class.forName(c.getName())
- 通过实例来获取
- 通过类加载器获取
我们这里采用第二种方式获取实例。
最后修改我们的客户端:
public class FruitClient { public static void main(String[] args) { FruitFactory fruitFactory = new FruitFactory(); Fruit apple = fruitFactory.create(Apple.class); apple.makeJuice(); }}
这样的话,如果新增一个水果,那么我们只需要传入对应的类型就可以了,也就不用频繁修改工厂类了。
好了,到此我们就实现了一个简单工厂。
- Java设计模式--工厂模式(简单工厂+工厂方法)
- Java设计模式-工厂模式(简单工厂+工厂方法)
- Java设计模式:工厂模式(一)简单工厂模式
- Java设计模式-工厂模式(1)简单工厂模式
- 设计模式-java工厂模式2(抽象工厂模式)
- Java(工厂设计模式)
- Java设计模式:Factory(工厂模式)
- Java设计模式 - Factory(工厂模式)
- java设计模式(简例)-工厂模式
- java设计模式(2)--工厂模式
- 工厂模式(JAVA设计模式)
- 设计模式(JAVA)------抽象工厂模式
- Java设计模式(五) 工厂模式
- java设计模式(一)---工厂模式
- Java设计模式----工厂模式(一)
- Java设计模式----工厂模式(二)
- Java设计模式----工厂模式(三)
- Java—设计模式(工厂模式)
- bootstrap table当前行 上移 下移
- python爬虫由浅入深9---定向爬取股票数据信息并保存至本地文件
- FastDFS上传文件二 : 多文件上传
- java 缓存架构剖析--本地缓存(LoadingCache)
- 111. Minimum Depth of Binary Tree(DFS)
- java设计模式(工厂模式)
- ubuntu16.04+cuda8.0安装
- Kubernetes之健康检查与服务依赖处理
- windows强制关闭Tomcat
- 关于正常启动虚拟机的环境下,本机通过无线上外网
- 《并发编程》--22.死锁产生的条件和动静态避免死锁
- chap2 变量和基本类型
- MapReduce1的工作原理
- 安装并开启MongoDB数据库服务