设计模式之工厂方法模式

来源:互联网 发布:task host windows 10 编辑:程序博客网 时间:2024/05/29 09:43

工厂,顾名思义在于对相关产品的批量添加,在开发中指将对象创建交给某个类,使得开发者不需要在意对象的创建。举个例子,小青我的面包店即将开业了。

/** *  * @author 小青 * @Time 下午12:30:34 * @Function:小青的面包店 * */public class First {public static void main(String[] args) {System.out.println("小青的面包店开业了");System.out.println("小青制作了一组黑面包");System.out.println("小青制作了一组蜂蜜燕麦面包");System.out.println("小青制作了一组白面包");}}
运行结果:


小青我发现,如果我还要制作其他类型的面包呢?客户端的代码就会越来越庞大,而且改起来很是麻烦,经过一定的思考,我设计了如下操作

/** *  * @author ricardo * @Time 下午12:36:33 * @Function:面包师小青 * */public class BreadMaker {public static void GetBread(int breadType) {switch (breadType) {case 1:System.out.println("小青制作了一组黑面包");break;case 2:System.out.println("小青制作了一组蜂蜜燕麦面包");break;case 3:System.out.println("小青制作了一组白面包");break;default:System.out.println("小青制作了一组新的面包");break;}}}
/** *  * @author ricardo * @Time 下午12:37:02 * @Function:小青的面包店 * */public class Second {public static void main(String[] args) {System.out.println("小青的面包店开业了");System.out.println("顾客想要黑面包");BreadMaker.GetBread(1);System.out.println("顾客想要蜂蜜燕麦面包");BreadMaker.GetBread(2);System.out.println("顾客想要白面包");BreadMaker.GetBread(3);}}
运行截图:


这样的过程看上去就合理多了,但是要修改面包师类也是很麻烦的,所以我决定再次修改拆分

/** *  * @author ricardo * @Time 下午12:42:29 * @Function:面包师 * */public class BreadMaker {public void GetBread() {System.out.println("制作面包");}}
/** *  * @author ricardo * @Time 下午12:45:19 * @Function:制作黑面包 * */public class BlackBread extends BreadMaker {@Overridepublic void GetBread() {System.out.println("制作一组黑面包");}}
public class HoneyBread extends BreadMaker {@Overridepublic void GetBread() {System.out.println("制作一组蜂蜜燕麦面包");}}
public class WhiteBread extends BreadMaker {@Overridepublic void GetBread() {System.out.println("制作一组白面包");}}
将各种面包都包装成了BreadMaker的子类,重写GetBread()方法,这样在修改任何一种面包的代码都与其他面包无关,同时还保证了面包配方的安全性。

/** *  * @author ricardo * @Time 下午12:59:42 * @Function:简单面包工厂类 * */public class BreadFactory {public static BreadMaker MakeBread(int breadType) {BreadMaker breadMaker = null;switch (breadType) {case 1:breadMaker = new BlackBread();break;case 2:breadMaker = new HoneyBread();break;case 3:breadMaker = new WhiteBread();break;default:break;}return breadMaker;}}

public class Second {public static void main(String[] args) {BreadMaker breadMaker;System.out.println("小青的面包店开业了");System.out.println("顾客要黑面包");breadMaker = BreadFactory.MakeBread(1);breadMaker.GetBread();System.out.println("顾客要白面包");breadMaker.GetBread();breadMaker = BreadFactory.MakeBread(2);System.out.println("顾客要蜂蜜燕麦面包");breadMaker = BreadFactory.MakeBread(3);breadMaker.GetBread();}}

运行截图:


以上采用的是简单工厂模式,但是这样做,在添加一种新面包的时候,要修改工厂类,增加Case分支,对扩展开发的同时也对修改开放了,这让小青我这个强迫症怎么忍,于是,根据GOF对工厂方法的定义:定义一个创建对象的接口,让子类决定实例化那一个类,工厂方法使一个类的实例化延迟到子类。再次对代码进行修改

/** *  * @author ricardo * @Time 下午1:44:34 * @Function:工厂接口 * */public interface IFactory {BreadMaker CreateBread();}
public class BlackBreadFactory implements IFactory {@Overridepublic BreadMaker CreateBread() {// TODO Auto-generated method stubreturn new BlackBread();}}
public class HoneyBreadFactory implements IFactory {@Overridepublic BreadMaker CreateBread() {// TODO Auto-generated method stubreturn new HoneyBread();}}
public class WhiteBreadFactory implements IFactory {@Overridepublic BreadMaker CreateBread() {// TODO Auto-generated method stubreturn new WhiteBread();}}

客户端实现对子类的实例化

public class Three {public static void main(String[] args) {BreadMaker breadMaker;System.out.println("小青的面包店开业了!");System.out.println("顾客要买黑面包");IFactory breadFactory = new BlackBreadFactory();breadMaker = breadFactory.CreateBread();breadMaker.GetBread();System.out.println("顾客要蜂蜜燕麦黑面包");breadFactory = new HoneyBreadFactory();breadMaker = breadFactory.CreateBread();breadMaker.GetBread();System.out.println("顾客要买白面包");breadFactory = new WhiteBreadFactory();breadMaker = breadFactory.CreateBread();breadMaker.GetBread();}}

运行截图:



这样一来,新的代码中增加新的面包种类,只需要增加新面包类和新的工厂方法接口实现就好了,具体的实例化哪个类的判断放到了客户端。

简单工厂模式的最大优点是去除了客户端与具体产品的依赖,虽然违背了开放-封闭原则,但是保持了封装对象创建过程的优点。工厂方法模式在保留了简单工厂模式优点的同时,也克服了其缺点,但对应的,每增加一个产品,都要添加一个产品工厂类,额外的增加了开发量。

以上内容,整理自刘径舟,张玉华编著的《设计模式其实很简单》读书笔记,欢迎转载.