这个设计模式系列的第一篇
只是把创造对象的代码简单的移到一个专门用来创建对象的类中,叫简单工厂,它更像一种好的编程习惯而不是一种模式。
而静态工厂函数则是类自己提供了一个静态的方法用来产生自己的对象(或者子类对象),它的好处有很多,经典的可以用来创建单例模式,或者创建实例受限制的多例模式。
工厂方法模式就是一种比较好用的模式了,它将创建对象的工作延迟到子类,代码依赖于抽象而不是具体,这种模式我感觉又有点像模板方法模式。
抽象工厂模式则是基于工厂方法模式,它针对一个产品族了。
简单工厂保证代码的可复用,各个子类完全分离,避免了更高代码无意中把原来好的源代码改错,对于开发公司来说,个人自用负责自己对应的子类,就行了,公司也不用把别的子类给你,
比如,如果现在公司要求你为公司的薪资管理系统做维护,原来只有技术人员(月薪) ,市场销售人员(底薪+提成),经理(年薪+股份)三种运算算法,现在要增加兼职工作人员的(时薪)算法,但按照前面的程序写法,公司就必须要把包含有的原三种算法的运算类给你,让你修改,你如果心中小算盘一打,‘TMD,公司给我的工资这么低,我真是郁闷,这会有机会了’,于是你除了增加了兼职算法以外,在技术人员(月薪)算法中写了一句
if (员工是自己)
{
salary = salary * 1.1;
}
那就意味着,你的月薪每月都会增加10%(小心被抓去坐牢),本来是让你加一个功能,却使得原有的运行良好的功能代码产生了变化,这个风险太大了。我们应该把加减乘除等运算分离,修改其中一个不影响另外的几个,增加运算算法也不影响其它代码”
这时候就需要用到 简单工厂模式了
让我们来看看这个例子,“我要发表博客”。
现在我要发表博客,这是我的一个想法,我想发表2篇,一篇是python的,一篇是java的。但他们都是博客,所以都有发表时间和题目俩个属性。但是在我写好具体的博客之前,博客这个概念还存在于我的脑海之中,实体还没有出来。
在这里,博客这个概念就是接口,我的脑子就是工厂,可以生产不同的符合有不同时间不同标题的博客实体出来,这些博客实体,则是实现了博客这个概念的具体实现。
package com.garfield.simplefactory;
/**
* 这是一个接口,就是我脑子里对博客的一个抽象概念
* 他们都有时间和标题俩个共同的特点
* @author Garfield
*
*/
interface Blog{
public void getTime();
public void getTitle();
}
/**
* 这个是具体的实现类,就是我脑海里博客的具体文章
* 关于Python的
* @author Garfield
*
*/
class Python implements Blog{
public void getTime(){
System.out.println("博客>>Python<<发表的时间是:XXXXXX");
}
public void getTitle(){
System.out.println("博客>>Python<<的标题是:XXXXXXX");
}
}
/**
* 这个是具体的实现类,就是我脑海里博客的具体文章
* 关于JAVA的
* @author Garfield
*
*/
class Java implements Blog{
public void getTime(){
System.out.println("博客>>Java<<发表的时间是:XXXXXX");
}
public void getTitle(){
System.out.println("博客>>Java<<的标题是:XXXXXXX");
}
}
/**
* 这个是核心工厂类,他负责根据需求生成具体的产品
* 客户端需要哪个博客,只要把名字传给工厂就好了
* 客户端不关心博客具体是怎么生成的,只要传回客户端需要的东西就好了
* @author Garfield
*
*/
class Factory{
public static Blog getBlogInstance(String name){
Blog blog=null;
try {
//利用反射得到汽车类型
blog=(Blog)Class.forName("com.garfield.simplefactory."+name).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return blog;
}
}
/**
* 客户端测试类
* 从客户端的角度看,客户看到的东西有
* 1.Blog一个借口,是我的概念,里边是一些抽象的共同的方法和属性
* 2.Factory工厂类以及我告诉客户的,现有有Pyhon和JAVA俩种博客,你要哪个就写哪个好了
* @author Garfield
*
*/
public class SimpleFactory {
public static void main(String[] args) {
Blog p=Factory.getBlogInstance("Python");
Blog j=Factory.getBlogInstance("Java");
p.getTitle();
p.getTime();
j.getTitle();
j.getTime();
}
}
输出结果是:
如果我要新加一个博客,那么只需要再加一个类,比如“C#”,继承博客这个借口。
其实,工厂模式细分可以分为3中:简单工厂模式,工厂方法模式和抽象工厂模式。 在简单工厂模式中有一个工厂类,还有一个所有产品的超类(博客接口)和各个具体产品类。为了让客户在系统运行期间动态的决定需要那种产品,所以提供了所有产品的超类(博客接口),这是利用的面向对象的多态机制。 通过提供了一个产品的超类类,在我们的系统需要别的形状的时候只要加入一个实现这个超类的具体产品类(python,java,c#)就可以了。产品中确实自动添加了我们需要的新产品,但工厂没有可以提供新产品的逻辑,必须修改源代码,在if语言中加上创建新产品的逻辑,重新编译系统才可以。这一点违反了“开闭原则”,如何才可以不违反原则呢,工厂方法模式的其他两个模式作出了解决的方法,但不完全。但简单工厂模式也是有优点的,要不然也没有存在的理由了,优点就在于实现起来很简单,对于一些本身就很简单的系统没有必要使用复杂的模式。