@Tyhj
        
        2019-01-30T08:17:12.000000Z
        字数 3737
        阅读 1624
    设计模式
感觉工厂方法模式,是有点难理解的;所以先讲讲使用方法,再谈谈理解
定义一个用于创建对象的接口,让子类决定实例化哪个类
在任何需要生成复杂对象的地方,都可以使用工厂方法模式
比如数据存储,APP一般可以将数据保存在内存、数据库、服务器这三个地方;对数据的操作,一般就是增删改查,所以我们抽象出产品类;
public interface IoHandler {/*** 保存*/void save();/*** 删除*/void delete();/*** 更新*/void update();}
然后具体产品类,就是实现接口保存数据到数据库
public class SqlLiteHandler implements IoHandler {@Overridepublic void save() {//保存数据到数据库}@Overridepublic void delete() {}@Overridepublic void update() {}}
就是实现接口保存数据到后台
public class ServerHandler implements IoHandler {@Overridepublic void save() {//保存数据到后台}@Overridepublic void delete() {}@Overridepublic void update() {}}
创建一个简单的工厂
public class IoFactory {public static IoHandler getIoHandler(String type) {IoHandler ioHandler = null;if (type.equals("server")) {ioHandler = new ServerHandler();} else if (type.equals("sqllite")) {ioHandler = new SqlLiteHandler();}return ioHandler;}}
调用也很简单
ServerHandler handler = IoFactory.getIoHandler("server");
上面的工厂有一个问题,不符合开闭原则,新增数据保存方式的时候需要修改IoFactory,容易出错;解决方法,很简单,抽象出创建产品的接口
public interface IoFactory {/*** 创建IoHandler* @return*/IoHandler createIoHandler();}
实现接口,实现创建ServerHandler的工厂,创建SqlLiteHandler工厂方法也是一样
public class ServerFactory implements IoFactory {@Overridepublic IoHandler createIoHandler() {return new ServerHandler();}}
具体调用
ServerHandler handler = new ServerFactory().createIoHandler();
符合了开闭原则,新增一种保存方法不会影响之前的代码;每一个保存方法需要新建一个工厂,稍微有些麻烦,还有一种简洁的写法,利用反射来生产具体的对象
public interface IoFactory {/*** 创建IoHandler** @param tClass* @param <T>* @return*/<T extends IoHandler> T createIoHandler(Class<T> tClass);}
具体的工厂类通过反射就可以获取
public class IoHandlerFactory implements IoFactory {@Overridepublic <T extends IoHandler> T createIoHandler(Class<T> tClass) {IoHandler ioHandler = null;try {ioHandler = (IoHandler) Class.forName(tClass.getName()).newInstance();} catch (Exception e) {e.printStackTrace();}return (T) ioHandler;}}
具体调用
ServerHandler serverHandler=new IoHandlerFactory().createIoHandler(ServerHandler.class);SqlLiteHandler sqlLiteHandler=new IoHandlerFactory().createIoHandler(SqlLiteHandler.class);
其实抽象工厂模式和工厂方法模式差不多,区别就是工厂方法模式一个工厂只能做一件事,比如创建一个IoHandler对象;抽象工厂模式不只是创建一个IoHandler,还得创建其他相关的对象出来;就是一个创建一组相关产品的工厂吧;实现方法和工厂方法模式一样,只是多了几种产品,抽象出来的工厂类多几个抽象方法,用来创建多的几个抽象产品,当然因为产品多了,实现的工厂类可以对产品进行组合,也更多了;
买电脑,网上买电脑,CPU主板一起买会便宜不少,店铺一般也会给出几种搭配,我们选择其中一种就行了
抽象出CPU来
public interface Cpu {/*** CPU型号* @return*/void cpuName();}
AMD的1500X,ACpu
public class ACpu implements Cpu {@Overridepublic void cpuName() {System.out.println("Ryzen 5 1500X");}}
Intel的i7 9700k,ICpu
public class ICpu implements Cpu{@Overridepublic void cpuName() {System.out.println("i7 9700k");}}
抽象出主板来
public interface MotherBoard {/*** 主板型号** @return*/void boardName();}
Z390主板
public class BoardZ390 implements MotherBoard{@Overridepublic void boardName() {System.out.println("Z390-PLUS GAMING");}}
B250主板
public class BoardB250 implements MotherBoard{@Overridepublic void boardName() {System.out.println("MSI B250");}}
抽象出电脑工厂
public interface ComputerFactory {/*** 组装CPU** @return*/Cpu buildCpu();/*** 组装主板** @return*/MotherBoard buildBoard();}
Z390主板加i7CPU的高配套装
public class HighwithFactory implements ComputerFactory {@Overridepublic Cpu buildCpu() {return new ICpu();}@Overridepublic MotherBoard buildBoard() {return new BoardZ390();}}
B250主板加上1500X的中配套餐
public class MediumFactory implements ComputerFactory {@Overridepublic Cpu buildCpu() {return new ACpu();}@Overridepublic MotherBoard buildBoard() {return new BoardB250();}}
现在要选择高配的套餐
ComputerFactory computerFactory=new HighwithFactory();computerFactory.buildBoard().boardName();computerFactory.buildCpu().cpuName();
输出
Z390-PLUS GAMING
i7 9700k
看下图我们可以知道,我们是需要抽象出产品,抽象出工厂,实现不同的工厂去创建不同的产品;

抽象这种东西,在六大基本原则就知道了,抽象是要抽象的,问题是为什么还需要一个工厂呢,直接new一个产品不行吗?感觉像是构造者模式的Director部分一样,没什么用呀
有这个疑问也很正常,我在看了这篇文章(工厂设计模式有什么用?)后,好像有了一点点理解;本质上是封装了new一个具体的classA的细节,将变化控制在工厂之中;如果classA的构造改变了,或者需要改为使用classB了,可以在工厂方法里面修改而不需要修改调用者,这样实现解耦,遵循开闭原则
我感觉好像和依赖注入差不多一个意思,我们为了不耦合,所以不自己去创建对象,使用注入进来的对象,现在我们为了不耦合也可以使用工厂注入对象,可能差不多吧
感觉大概多使用就理解了吧