java设计模式--三种工厂模式详解
简单工厂
简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)。当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式。
由于创建实例的方法通常为静态(static)方法,因此简单工厂模式又被成为静态工厂方法模式(Static Factory Method)。
- Product表示产品接口,也可用抽象类实现,封装产品间共有的属性。
- ConcreteProduct*表示具体的实际产品。
- Factory表示工厂,工厂根据需要来创建相应的产品。
这样一来,当添加新的产品C时,只需要修改工厂部分代码即可,而传统方法需要在每一个创建产品的地方都进行修改。可以理解为把具体的产品创建封装成一个工厂类。
举个例子,大富翁的地图创建:
- AbstractBlock是接口,表示抽象的地块,包括方法printBlock()打印地块。
- Empty、Prison、Park实现上述接口,表示空地(*)、监狱(&)和公园(#)。
- SimpleFactory是创建地块的简单工厂。
类图:
代码:
1.产品接口
public interface AbstractBlock { public void printBlock(); }
2.产品接口实现子类
public class Empty implements AbstractBlock{ @Override public void printBlock() { System.out.print("* "); } }
public class Park implements AbstractBlock{ @Override public void printBlock() { System.out.print("# "); } }
public class Prison implements AbstractBlock{ @Override public void printBlock() { System.out.print("& "); } }
3.简单工厂类
public class SimpleFactory { public AbstractBlock getBlock(String type){ //根据传参创建不同的地块 if(type.equalsIgnoreCase("Empty")){ return new Empty(); } else if(type.equalsIgnoreCase("Park")){ return new Park(); } else if(type.equalsIgnoreCase("Prison")){ return new Prison(); } return null; } }
4.调用工厂
public class Map { public void getMap(){ SimpleFactory simpleFactory=new SimpleFactory(); //实例化工厂 ArrayList<AbstractBlock> map=new ArrayList<AbstractBlock>(); //地块集合 String []types=new String[3]; types[0]="Empty"; types[1]="park"; types[2]="Prison"; Random rd = new Random(); for(int i=1;i<=12;i++){ //随机用工厂创建地块并放入集合 int tt = rd.nextInt(types.length); map.add(simpleFactory.getBlock(types[tt])); } //地图大小写死了,不是重点 for(int i=0;i<12;i++){ map.get(i).printBlock(); if(i==3||i==5||i==7) System.out.println(); if(i==4||i==6) System.out.print(" "); } } }
5.测试
public class MonoPoly { public static void main(String[] args) { Map map=new Map(); map.getMap(); } }
运行结果
工厂方法
不难发现,当增加新的产品时需要对简单工厂类修改,或创建多个简单工厂。(比如增加一个法院地块)工厂方法进一步解耦合,把工厂类抽象,不再负责所有实例的创建,而是把具体的创建工作交给了子类去完成,实例化延迟到子类加载,由子类来决定要实例化的类。
抽象化工厂类,把具体实例化工作交给其子类实现。
代码:
1.工厂接口
public interface AbstractFactory { public AbstractBlock createBlock(); }
2.工厂实现子类
public class EmptyFactory implements AbstractFactory { @Override public AbstractBlock createBlock() { return new Empty(); } }
public class ParkFactory implements AbstractFactory { @Override public AbstractBlock createBlock() { return new Park(); } }
public class PrisonFactory implements AbstractFactory { @Override public AbstractBlock createBlock() { return new Prison(); } }
3.产品接口
public interface AbstractBlock { public void printBlock(); }
4.产品实现子类
public class Empty implements AbstractBlock { @Override public void printBlock() { System.out.print("* "); } }
public class Park implements AbstractBlock { @Override public void printBlock() { System.out.print("# "); } }
public class Prison implements AbstractBlock { @Override public void printBlock() { System.out.print("& "); } }
5.调用
public class Map { public void getMap() { ArrayList<AbstractBlock> map=new ArrayList<AbstractBlock>(); //地块集合 AbstractFactory abstractFactory; Random rd = new Random(); for(int i=1;i<=12;i++){ //随机用工厂创建地块并放入集合 int tt = rd.nextInt(3); if(tt==0)abstractFactory=new EmptyFactory(); else if(tt==1)abstractFactory=new ParkFactory(); else abstractFactory=new PrisonFactory(); map.add(abstractFactory.createBlock()); } //地图大小写死了,不是重点 for(int i=0;i<12;i++){ map.get(i).printBlock(); if(i==3||i==5||i==7) System.out.println(); if(i==4||i==6) System.out.print(" "); } } }
6.测试
public class MonoPoly { public static void main(String[] args) { Map map=new Map(); map.getMap(); } }
运行结果:
抽象工厂
不难发现当创建新的产品接口时,也需要对工厂方法修改,或创建多个工厂方法。(比如增加魔法地块簇,对应组产品魔法公园、魔法空地、魔法监狱等)
抽象工厂将工厂方法进一步抽象。定义了一个接口用于创建相关或有依赖关系的对象簇,而无需指明具体的类。可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。
把工厂类抽象后,对应不同子类工厂(普通/魔法),生产对应的一组产品。最后调用时统一调用抽象接口即可,不必知道具体对象,面向接口编程。
1.产品接口
public interface AbstractBlock { void printBlock(); }
2.产品抽象子类-普通产品
public abstract class NormalAbstractBlock implements AbstractBlock { public abstract void printBlock(); }
2.2普通空地
public class NormalEmpty extends NormalAbstractBlock { public void printBlock() { System.out.print("* "); } }
2.3普通公园
public class NormalPark extends NormalAbstractBlock { public void printBlock() { System.out.print("# "); } }
2.4普通监狱
public class NormalPrison extends NormalAbstractBlock { public void printBlock() { System.out.print("& "); } }
3.1产品抽象子类-魔法产品
public abstract class MagicAbstractBlock implements AbstractBlock { public abstract void printBlock(); }
3.2魔法空地
public class MagicEmpty extends MagicAbstractBlock { public void printBlock() { System.out.print("e "); } }
3.3魔法公园
public class MagicPark extends MagicAbstractBlock { public void printBlock() { System.out.print("g "); } }
3.4魔法监狱
public class MagicPrison extends MagicAbstractBlock { public void printBlock() { System.out.print("p "); } }
4.工厂接口
public interface AbstractFactory { AbstractBlock getEmpty(); AbstractBlock getPrison(); AbstractBlock getPark(); }
5.工厂实现子类-普通工厂
public class NormalFactory implements AbstractFactory { public AbstractBlock getEmpty() { return new NormalEmpty(); } public AbstractBlock getPrison() { return new NormalPrison(); } public AbstractBlock getPark() { return new NormalPark(); } }
6.工厂实现子类-魔法工厂
public class MagicFactory implements AbstractFactory { public AbstractBlock getEmpty() { return new MagicEmpty(); } public AbstractBlock getPrison() {return new MagicPrison(); } public AbstractBlock getPark() { return new MagicPark(); } }
7.调用
public class Map { public void getMap(AbstractFactory af){ ArrayList<AbstractBlock> map=new ArrayList<AbstractBlock>(); map.add(af.getEmpty()); map.add(af.getPrison()); map.add(af.getPark()); Random rd = new Random(3); int col=12; for(int i=1;i<=col;i++){ int tt = rd.nextInt(3); map.get(tt).printBlock(); if(i==4||i==6||i==8) System.out.println(); if(i==5||i==7) System.out.print(" "); } } }
8.测试
public class Monopoly { public void play(){ Map map=new Map(); Scanner scan = new Scanner(System.in); System.out.println("请输入指令(1输出普通地图,2输出魔法地图)"); int order; order = scan.nextInt(); if(order == 1){ map.getMap(new NormalFactory()); }else{ map.getMap(new MagicFactory()); } } }
运行结果:
总结
本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注猪先飞的更多内容!
相关文章
- 这篇文章主要介绍了如何利用java语言实现经典《复杂迷宫》游戏,文中采用了swing技术进行了界面化处理,感兴趣的小伙伴可以动手试一试...2022-02-01
java 运行报错has been compiled by a more recent version of the Java Runtime
java 运行报错has been compiled by a more recent version of the Java Runtime (class file version 54.0)...2021-04-01- 这篇文章主要介绍了在java中获取List集合中最大的日期时间操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
- 这篇文章主要介绍了教你怎么用Java获取国家法定节假日,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下...2021-04-23
- 这篇文章主要介绍了Java如何发起http请求的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-31
- 说起C#和Java这两门语言(语法,数据类型 等),个人以为,大概有90%以上的相似,甚至可以认为几乎一样。但是在工作中,我也发现了一些细微的差别...2020-06-25
- 神马是“解释器模式”?先翻开《GOF》看看Definition:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。在开篇之前还是要科普几个概念: 抽象语法树: 解释器模式并未解释如...2014-06-07
- 这篇文章主要介绍了解决Java处理HTTP请求超时的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-29
- 这篇文章主要为大家介绍了JavaScript设计模式中的装饰者模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
- 这篇文章主要介绍了java 判断两个时间段是否重叠的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
- 这篇文章主要介绍了超简洁java实现双色球若干注随机号码生成(实例代码),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-04-02
- 这篇文章主要介绍了Java生成随机姓名、性别和年龄的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-10-01
java 画pdf用itext调整表格宽度、自定义各个列宽的方法
这篇文章主要介绍了java 画pdf用itext调整表格宽度、自定义各个列宽的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-31- 这篇文章主要介绍了java正则表达式判断前端参数修改表中另一个字段的值,需要的朋友可以参考下...2021-05-07
Java使用ScriptEngine动态执行代码(附Java几种动态执行代码比较)
这篇文章主要介绍了Java使用ScriptEngine动态执行代码,并且分享Java几种动态执行代码比较,需要的朋友可以参考下...2021-04-15- 这篇文章主要介绍了Java开发实现人机猜拳游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-03
Java 8 Stream 的终极技巧——Collectors 功能与操作方法详解
这篇文章主要介绍了Java 8 Stream Collectors 功能与操作方法,结合实例形式详细分析了Java 8 Stream Collectors 功能、操作方法及相关注意事项,需要的朋友可以参考下...2020-05-20- 这篇文章主要介绍了Java List集合返回值去掉中括号('[ ]')的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-29
Java中lombok的@Builder注解的解析与简单使用详解
这篇文章主要介绍了Java中lombok的@Builder注解的解析与简单使用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-01-06- 下面小编就为大家带来一篇java中String类型变量的赋值问题介绍。小编觉得挺不错的。现在分享给大家,给大家一个参考。...2016-03-28