设计模式—简单工厂模式(静态工厂模式)

时间:2021-07-24 16:38:19

基本概念:

1)Simple Factory模式属于创建型模式,
2)简单工厂模式是由一个工厂(注意是一个!)对象决定创建出哪一种产品类的实例(例如你到肯德基说你要鸡腿,要薯条,要饮料还是,,,这时肯德基是一个工厂,客户端只需要点明自己要什么就行)
3)实现方式的实质:由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

下面来看一个例子:

音乐盒接口IMusicBox:

package SimpleFactory;

public interface IMusicBox {
public void play();
}

两种不同的音乐盒播放方式:ViolinBox(小提琴)和 PianoBox(钢琴):

package SimpleFactory;

public class ViolinBox implements IMusicBox {
public void play() {
System.out.println(
"拨放小提琴音乐^_^");
}
}
package SimpleFactory;

public class PianoBox implements IMusicBox {

public void play() {
System.out.println(
"拨放钢琴音乐:)");
}
}

下面是一个工厂MusicBoxFactory(Simple Factory的核心,在工厂中根据客户端指定的参数动态创建不同的对象):

package SimpleFactory;

public class MusicBoxFactory {

public static IMusicBox createMusicBox(String name)
throws InstantiationException,
IllegalAccessException,
ClassNotFoundException{

// 这边使用的是Java的Reflection机制来产生实例
return (IMusicBox) Class.forName(name).newInstance();

}
}

下面客户端就可以利用工厂模式:(利用工厂模式,客户端只需要对工厂指定你要创建的对象的名字(参数),工厂就可以根据你指定的参数动态创建不同的对象)

package SimpleFactory;

public class MusicBoxDemo {

public static void main(String[] args) throws Exception {//利用工厂模式,客户端只需要对工厂指定你要创建的对象的名字(参数),工厂就可以根据你指定的参数动态
//创建不同的对象。当然,这些不同的对象就有不同的表现(在本例中通过play表示)
playMusicBox(MusicBoxFactory.createMusicBox("SimpleFactory.PianoBox"));
playMusicBox(MusicBoxFactory.createMusicBox(
"SimpleFactory.ViolinBox"));
}

public static void playMusicBox(IMusicBox musicBox) {
musicBox.play();
}
}

结果:
拨放钢琴音乐:)
拨放小提琴音乐^_^

为什么工厂类中的方法必须是静态的?

下面咱们就来探讨一下 ,其实这样不用静态的在语法上并没有错误,但却完全没理解java面向对象设计的精髓。

如果直接new出FriutFactory的对象,客户端就必须自己控制工厂类的构造和生成,客户端必须非常清楚工厂的构造函数(比如构造函数有多少个参数,输入参数时有什么条件等等),也知道工厂的内部细节,一旦工厂扩展或者改变了,客户端在没有得到通知的情况下就不知道怎么调用了。而是用静态方法构造客户端则完全不关心你是如何构造对象的所以客户端不需要了解工厂的构造细节,一旦工厂内部发生变化,客户端也不需要关心。它只需要关心最后的结果就行了,因为所有的细节都在工厂内部被处理完了。

 

优点:

客户端只面对工厂,不用管产品的具体细节,客户只需向工厂要求你需要什么,其他的事情都交给工厂了。

 

缺点:

这个工厂类集中了所以的创建逻辑,当有复杂的多层次等级结构时,所有的业务逻辑都在这个工厂类中实现。什么时候它不能工作了,整个系统都会受到影响。

 

从上面的例子也可以看出来,工厂类往往是用反射机制来产生具体对象的。(因为不同类都继承自同一接口),故其扩展性很有限,产品种类必须是事先就知道的哪几

种,什么时候你想要添加一个不是公共接口下的具体类就不行了。

另外,如果你不用反射机制,也不要公共接口,在工厂中使用其他逻辑(例如判断传入的字符串)来根据用户参数创建对象也行,那样扩展性也是很糟糕的,逻辑和添

加只会越来多。