java设计模式--三种工厂模式详解
简单工厂
简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)。当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式。
由于创建实例的方法通常为静态(static)方法,因此简单工厂模式又被成为静态工厂方法模式(static factory method)。
- product表示产品接口,也可用抽象类实现,封装产品间共有的属性。
- concreteproduct*表示具体的实际产品。
- factory表示工厂,工厂根据需要来创建相应的产品。
这样一来,当添加新的产品c时,只需要修改工厂部分代码即可,而传统方法需要在每一个创建产品的地方都进行修改。可以理解为把具体的产品创建封装成一个工厂类。
举个例子,大富翁的地图创建:
- abstractblock是接口,表示抽象的地块,包括方法printblock()打印地块。
- empty、*、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 * 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("*")){ return new *(); } 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]="*"; 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 *factory implements abstractfactory { @override public abstractblock createblock() { return new *(); } }
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 * 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 *factory(); 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 normal* 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 magic* extends magicabstractblock { public void printblock() { system.out.print("p "); } }
4.工厂接口
public interface abstractfactory { abstractblock getempty(); abstractblock get*(); abstractblock getpark(); }
5.工厂实现子类-普通工厂
public class normalfactory implements abstractfactory { public abstractblock getempty() { return new normalempty(); } public abstractblock get*() { return new normal*(); } public abstractblock getpark() { return new normalpark(); } }
6.工厂实现子类-魔法工厂
public class magicfactory implements abstractfactory { public abstractblock getempty() { return new magicempty(); } public abstractblock get*() {return new magic*(); } 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.get*()); 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()); } } }
运行结果:
总结
本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注的更多内容!
下一篇: Tree-shaking的使用实例