设计模式之简单工厂模式
以下所有仅供记录和参考,如有问题,请留言提出,感谢!转载注明出处。
在23种设计模式之中,和工厂相关的有三种:1.简单工厂模式;2.工厂方法模式;3.抽象工厂模式。其中,简单工厂模式是工厂方法模式的特殊情况。
下面记录一下简单工厂模式,先给出一个例子来说明为什么要使用简单工厂模式。
例子:假如一位农民伯伯(Farmer)需要购买化肥,现在有磷肥(P),氮肥(N),钾肥(K)三种肥料。那么在面向对象中,就会有四个类,分别是Farmer,P,N,K。下面用Java代码来展示这四个类,其中Farmer类是主类,在主类中进行化肥的获取:
Farmer类:
public class Farmer {
public static void main(String[] args) {
K k = new K(); //购买K肥
k.get();
//P p = new P(); //购买P肥
//p.get();
//N n = new N(); //购买N肥
//n.get();
}
}
三个化肥P,K,N类:
public class K {
public void get(){
System.out.println("got K");
}
}
public class N {
public void get(){
System.out.println("got N");
}
}
public class P {
public void get(){
System.out.println("got P");
}
}
现在,假如农民伯伯开始想买K肥,那么就直接new一个K肥就可以了,但是之后又想买P肥呢。那就把购买K肥的两行代码删除,重新new一个P肥出来。又但是,还想买点N肥呢,那就把K肥的两行代码删除,再new一个N肥出来。可以看出来,所有的化肥都是农民伯伯自己创造出来的。
好了,问题来了,如果涉及到的代码很多的话,是不是每次修改都要删除很多代码,然后重新写很多代码。这就显得很麻烦,而且这很不面向对象。
面向对象是对现实生活进行了抽象,那么在现实生活中,是怎么购买化肥的。在上面的例子中,所有的化肥都是农民伯伯自己生产(new)出来的,然而,事实上,农民伯伯是不会自己去生产化肥的,而是通过化肥工厂购买化肥。所以现在需要一个化肥工厂类(Factory)。有了Factory类之后,农民伯伯只需要告诉工厂:“我需要x肥”,就可以了。
除了有一个Factory类之外。还需要对三种化肥类进行处理。因为现在所有的化肥都交给一个工厂处理了,工厂要对于所有的化肥会进行统一的管理,不再将K,N,P分开处理,把它们都称为“化肥(Fertilizer)”。所以这里就需要用到面向对象的继承特性,将三个化肥类K,N,P都继承到化肥类(Fertilizer)。这样,工厂只需要管理化肥类就行,以后无论增加什么新品种的肥料,都归到化肥类下面就行了。
下面是化肥类和工厂类的java实现:化肥类:
public abstract class Fertilizer { //这里可以是抽象类,接口,普通类,根据实际需求写
public abstract void get();
}
工厂类:
public class Factory {
public static Fertilizer creatFertilizer(String name){ //静态方法,通过类名直接可以调用
Fertilizer fertilizer = null; //统一管理的化肥
switch(name){
case "K":
fertilizer = new K(); //根据需要生成K肥
break;
case "P":
fertilizer = new P(); //根据需要生成P肥
break;
case "N":
fertilizer = new N(); //根据需要生成N肥
break;
}
return fertilizer; //返回已经实例化后的化肥
}
}
有了工厂类(Factory)和化肥类(Fertilizer)之后,需要对以前的K,N,P肥进行修改,让它们都继承化肥类,修改如下:
修改后的各种化肥K,P,N类:
public class K extends Fertilizer { //主要修改了这里,继承了化肥类(Fertilizer)
public void get(){
System.out.println("got K");
}
}
public class N extends Fertilizer { //主要修改了这里,继承了化肥类(Fertilizer)
public void get(){
System.out.println("got N");
}
}
public class P extends Fertilizer { //主要修改了这里,继承了化肥类(Fertilizer)
public void get(){
System.out.println("got P");
}
}
工厂已经建造结束,也实行了统一管理。那么农民伯伯这次需要化肥的话,会怎么弄呢,下面是对主类(Farmer)的修改:
修改后的主类:
public class Farmer {
public static void main(String[] args) {
//下面是没有工厂之前,农民伯伯自己生产化肥
/*
K k = new K(); //购买K肥
k.get();
P p = new P(); //购买P肥
p.get();
N n = new N(); //购买N肥
n.get();
*/
//有了工厂后,只要告诉工厂要买什么肥
Fertilizer fertilizer = Factory.creatFertilizer("K");
fertilizer.get();
}
}
可以看到的是,这一次,只需要告诉工厂类需要什么肥料就可以了(通过给creatFertilizer方法传递参数)。假如这次,农民伯伯又想要P肥的话,只需要修改传递的参数就行了,不需要像以前那样自己创造了。如果又需要其他肥料的话,也都只是修改传递给工厂的那个参数就行了。这就是简单工厂模式带来的好处。
总结:
看完简单工厂模式后,上面是自己想的一个例子,通过思考,也算是明白了简单工厂模式的构造和好处。
好处:假如把农民伯伯称为前端,把所有的化肥称为后端。那么以前就是在前端直接进行后端对象的生成,这样的话,前后端耦合太紧。而再前后端之间添加一个工厂。通过工厂来进行后端对象的生成。前端只需要告诉工厂需要什么对象就行了。这样就达到了松耦合的效果。同时,在这一个简单工厂模式中,还可以看到面向对象的三个特性,封装,继承和多态。
构造:从例子中可以看到,1、首先我们需要把所有用户需要的类进行一个统一管理,这里就是继承关系(当然,这些类之间需要有共性),这是添加的第一个类。2、之后,需要添加一个工厂类来对用户需要的这些类进行统一生产(生产对象),这是添加的第二个类,在工厂中,需要根据用户所传递的信息,来选择到底生产哪一种类对象。3、除了添加这两个类之外,就是用户端需要对工厂传递必要的信息,来告诉工厂自己需要什么对象。
通过以上三个步骤,就设计出来一个简单工厂模式了。
缺点:从例子中可以看出,所有的化肥都需要工厂来生产,那么当化肥的种类越来越多时,工厂类的责任就越来越大(因为需要添加其他化肥的生产)。以后每添加一种化肥,就得修改工厂中的选择语句,这样违反了“高内聚责任分配原则”(我也不知道这是什么原则)。这个缺点在工厂方法模式中得到了一定的缓解。