设计模式之工厂模式
工厂模式其实很简单,在这里就简单的说一下自己的心得体会,随时补充和修正自己对工厂模式的认知。
question one:工厂是干什么的?当然是生产东西的,在Java的世界或者面向对象编程的世界里,工厂是用来生产对象实例的。
当然一个工厂生产的产品具有共性,比如一个工厂专门用来生产手机,不管是红色的手机、黄色的手机、拍照用的手机,老年人用的手机 等等其共性就是手机这个产品。所以可以抽象出Phone这个接口。如果一个工厂生产的东西不一样,也就是说没有共性,那么在面向对象的世界里工厂模式就没用武之地。在Java世界中具有共性的东西叫什么:Interface或者abstract class。许多implements 一个interface或者extends 一个抽象类的子类因为其接口或者父类而具有了共性。
interface Phone {
void call();//具有共同的行为打电话
}
工厂模式的作用就是从这些共性的产品中,根据某种原则返回一个具体的产品对象出来。
所以简单工厂模式就出炉了:
public class PhoneFactory {
//注意此处是static的
public static Phone create(String pattern) {
switch(pattern){
case a:
return new PhoneA();
case b:
return new PhoneB();
}
}
}
这样我们客户端的代码就很简单了:
void call(String pattern) {
Phone phone = PhoneFactory.create(pattern);
phone.call();
}
客户端没必要知道手机对象创建的具体细节,只要根据匹配规则拿到手机后执行call这个行为就可以了。这也是工厂模式优点的体现:因为Phone接口指定了实现此接口类的行为call,那么子类只需要重写这个方法即可。如果没有工厂模式的话可能就会如下面这个代码了:
void call(String pattern) {
Phone phone;
switch(pattern){
case a:
phone= new PhoneA();
case b:
phone=new PhoneB();
}
if(phone!=null)
phone.call();
}
这段代码不仅对客户端暴露太多的对象创建细节,而且如果有多个页面或者模块需要打电话的话,可能会ctrl+c/v大法,然后需要改动的时候各个模块都需要改动;可能好一点设计的就是抽象一个公共utils方法了。
其实工厂模式之所以能成功,是面向抽象/接口编程的合理应用的必然结果,Phone接口使得其子类具有共同的call行为(算是接口的约束作用)。所以使用客户端工厂模式(如上)代码可以很简洁。如果没有接口约束作用也就是说每个电话对象不实现Phone接口,且每个电话对象打电话的方法都不一样,比如PhoneA的打电话为call(),PhoneB()打电话的方法叫hello()等等吧,上面的call方法就可能更复杂:
void call(String pattern) {
switch(pattern){
case a:
PhoneA phoneA= new PhoneA();
phoneA.call();
break;
case b:
PhoneB phoneB= new PhoneB();
phoneB.hello();
break;
}
}
随着更多不同电话的加入,每个电话都有不同拨打电话的入口方式;你不得不阅读说明书(api)来知道每部电话该拨打电话,想想就头大。
而定义一个Phone接口,打电话的行为就是call(),那么你从工厂里拿道手机直接call就行了。 面向接口或者面向抽象编程的有点体现淋漓尽致。可以说如果没有了接口或者抽象类,就不会存在设计模式这套东西,所以掌握类的设计原则:面向抽象或者接口编程,其实还是很有必要的。
其实仔细想想,与其说工厂模式是个模式,不如说是一个代码编写习惯,把创建对象的具体职责统一起来即可。
工厂模式虽然很简单,但是应用确很广泛,比如大名鼎鼎的Retrofit,Okhttp等等框架都有这该模式的影子。
刚才博主一直强调 面向抽象和接口编程,那么能不能对工厂进行抽象呢?当然能,这就是抽象工厂模式了。下一篇会详细介绍
上一篇: 【JS逆向】无限debugger实战之八仙过海,各显神通。
下一篇: 改用sublime编辑器