[关闭]
@Tyhj 2019-01-30T16:17:12.000000Z 字数 3737 阅读 1371

工厂方法模式

设计模式


感觉工厂方法模式,是有点难理解的;所以先讲讲使用方法,再谈谈理解

定义

定义一个用于创建对象的接口,让子类决定实例化哪个类

使用场景

在任何需要生成复杂对象的地方,都可以使用工厂方法模式

举个栗子

比如数据存储,APP一般可以将数据保存在内存、数据库、服务器这三个地方;对数据的操作,一般就是增删改查,所以我们抽象出产品类;

  1. public interface IoHandler {
  2. /**
  3. * 保存
  4. */
  5. void save();
  6. /**
  7. * 删除
  8. */
  9. void delete();
  10. /**
  11. * 更新
  12. */
  13. void update();
  14. }

然后具体产品类,就是实现接口保存数据到数据库

  1. public class SqlLiteHandler implements IoHandler {
  2. @Override
  3. public void save() {
  4. //保存数据到数据库
  5. }
  6. @Override
  7. public void delete() {
  8. }
  9. @Override
  10. public void update() {
  11. }
  12. }

就是实现接口保存数据到后台

  1. public class ServerHandler implements IoHandler {
  2. @Override
  3. public void save() {
  4. //保存数据到后台
  5. }
  6. @Override
  7. public void delete() {
  8. }
  9. @Override
  10. public void update() {
  11. }
  12. }

简单工厂模式

创建一个简单的工厂

  1. public class IoFactory {
  2. public static IoHandler getIoHandler(String type) {
  3. IoHandler ioHandler = null;
  4. if (type.equals("server")) {
  5. ioHandler = new ServerHandler();
  6. } else if (type.equals("sqllite")) {
  7. ioHandler = new SqlLiteHandler();
  8. }
  9. return ioHandler;
  10. }
  11. }

调用也很简单

  1. ServerHandler handler = IoFactory.getIoHandler("server");

工厂方法模式

上面的工厂有一个问题,不符合开闭原则,新增数据保存方式的时候需要修改IoFactory,容易出错;解决方法,很简单,抽象出创建产品的接口

  1. public interface IoFactory {
  2. /**
  3. * 创建IoHandler
  4. * @return
  5. */
  6. IoHandler createIoHandler();
  7. }

实现接口,实现创建ServerHandler的工厂,创建SqlLiteHandler工厂方法也是一样

  1. public class ServerFactory implements IoFactory {
  2. @Override
  3. public IoHandler createIoHandler() {
  4. return new ServerHandler();
  5. }
  6. }

具体调用

  1. ServerHandler handler = new ServerFactory().createIoHandler();

符合了开闭原则,新增一种保存方法不会影响之前的代码;每一个保存方法需要新建一个工厂,稍微有些麻烦,还有一种简洁的写法,利用反射来生产具体的对象

  1. public interface IoFactory {
  2. /**
  3. * 创建IoHandler
  4. *
  5. * @param tClass
  6. * @param <T>
  7. * @return
  8. */
  9. <T extends IoHandler> T createIoHandler(Class<T> tClass);
  10. }

具体的工厂类通过反射就可以获取

  1. public class IoHandlerFactory implements IoFactory {
  2. @Override
  3. public <T extends IoHandler> T createIoHandler(Class<T> tClass) {
  4. IoHandler ioHandler = null;
  5. try {
  6. ioHandler = (IoHandler) Class.forName(tClass.getName()).newInstance();
  7. } catch (Exception e) {
  8. e.printStackTrace();
  9. }
  10. return (T) ioHandler;
  11. }
  12. }

具体调用

  1. ServerHandler serverHandler=new IoHandlerFactory().createIoHandler(ServerHandler.class);
  2. SqlLiteHandler sqlLiteHandler=new IoHandlerFactory().createIoHandler(SqlLiteHandler.class);

抽象工厂模式

其实抽象工厂模式工厂方法模式差不多,区别就是工厂方法模式一个工厂只能做一件事,比如创建一个IoHandler对象;抽象工厂模式不只是创建一个IoHandler,还得创建其他相关的对象出来;就是一个创建一组相关产品的工厂吧;实现方法和工厂方法模式一样,只是多了几种产品,抽象出来的工厂类多几个抽象方法,用来创建多的几个抽象产品,当然因为产品多了,实现的工厂类可以对产品进行组合,也更多了;

简单举个小例子

买电脑,网上买电脑,CPU主板一起买会便宜不少,店铺一般也会给出几种搭配,我们选择其中一种就行了

抽象出CPU来

  1. public interface Cpu {
  2. /**
  3. * CPU型号
  4. * @return
  5. */
  6. void cpuName();
  7. }

AMD的1500X,ACpu

  1. public class ACpu implements Cpu {
  2. @Override
  3. public void cpuName() {
  4. System.out.println("Ryzen 5 1500X");
  5. }
  6. }

Intel的i7 9700k,ICpu

  1. public class ICpu implements Cpu{
  2. @Override
  3. public void cpuName() {
  4. System.out.println("i7 9700k");
  5. }
  6. }

抽象出主板来

  1. public interface MotherBoard {
  2. /**
  3. * 主板型号
  4. *
  5. * @return
  6. */
  7. void boardName();
  8. }

Z390主板

  1. public class BoardZ390 implements MotherBoard{
  2. @Override
  3. public void boardName() {
  4. System.out.println("Z390-PLUS GAMING");
  5. }
  6. }

B250主板

  1. public class BoardB250 implements MotherBoard{
  2. @Override
  3. public void boardName() {
  4. System.out.println("MSI B250");
  5. }
  6. }

抽象出电脑工厂

  1. public interface ComputerFactory {
  2. /**
  3. * 组装CPU
  4. *
  5. * @return
  6. */
  7. Cpu buildCpu();
  8. /**
  9. * 组装主板
  10. *
  11. * @return
  12. */
  13. MotherBoard buildBoard();
  14. }

Z390主板加i7CPU的高配套装

  1. public class HighwithFactory implements ComputerFactory {
  2. @Override
  3. public Cpu buildCpu() {
  4. return new ICpu();
  5. }
  6. @Override
  7. public MotherBoard buildBoard() {
  8. return new BoardZ390();
  9. }
  10. }

B250主板加上1500X的中配套餐

  1. public class MediumFactory implements ComputerFactory {
  2. @Override
  3. public Cpu buildCpu() {
  4. return new ACpu();
  5. }
  6. @Override
  7. public MotherBoard buildBoard() {
  8. return new BoardB250();
  9. }
  10. }

现在要选择高配的套餐

  1. ComputerFactory computerFactory=new HighwithFactory();
  2. computerFactory.buildBoard().boardName();
  3. computerFactory.buildCpu().cpuName();

输出

Z390-PLUS GAMING
i7 9700k

工厂方法的理解

看下图我们可以知道,我们是需要抽象出产品,抽象出工厂,实现不同的工厂去创建不同的产品;

抽象这种东西,在六大基本原则就知道了,抽象是要抽象的,问题是为什么还需要一个工厂呢,直接new一个产品不行吗?感觉像是构造者模式的Director部分一样,没什么用呀

有这个疑问也很正常,我在看了这篇文章(工厂设计模式有什么用?)后,好像有了一点点理解;本质上是封装了new一个具体的classA的细节,将变化控制在工厂之中;如果classA的构造改变了,或者需要改为使用classB了,可以在工厂方法里面修改而不需要修改调用者,这样实现解耦,遵循开闭原则

我感觉好像和依赖注入差不多一个意思,我们为了不耦合,所以不自己去创建对象,使用注入进来的对象,现在我们为了不耦合也可以使用工厂注入对象,可能差不多吧

总结

感觉大概多使用就理解了吧

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注