1.解析
简单工厂并不简单,它是整个模式的核心,一旦他出了问题,整个模式都将受影响而不能工作,为了降低风险和为日后的维护、扩展做准备,我们需要对它进行重构,引入工厂方法。
区别说明 :
工厂方法和简单工厂的主要区别如下 :
(1) 简单工厂是把创建产品的职能都放在一个类里面,而工厂方法则把不同的产品放在实现了工厂接口的不同工厂类里面;
(2) 这样就算其中一个工厂类出了问题,其他工厂类也能正常工作,**互相不受影响;
(3) 以后增加新产品,也只需要新增一个实现工厂接口工厂类,就能达到,不用修改已有的代码。
2.实例
实例说明 :
餐馆的例子 : 大厅经理接收点菜单 -> 给后厨主任菜单通知做菜 -> 服务员去端菜.简单的说明下工厂方法模式.
$. 后厨风波
(1) 实现产品接口 : 后厨主任, 告知做饭,说话任务
/**
* 角色:后厨主任
* 任务:告知制作什么食物
* 目的:统一制作什么产品
* @author yuan
*
*/
public abstract class Foods {
/**
* 都要实现的工作,做饭
*/
public abstract void makeFood();
/**
* 非都可实现的工作,说话
*/
public void sayHello(){}
}
(2) 实现单一产品 : 饺子大厨, 制作饺子,还可以说话
public class JiaoziDaChu extends Foods {
/**
* 角色 : 饺子大厨
* 任务 : 制作饺子
* 目的 : 实现Foods接口,知道自己干什么
*/
@Override
public void makeFood() {
System.out.println("热腾腾的饺子出锅了:)");
}
@Override
public void sayHello() {
//饺子大厨说
System.out.println("我是饺子大厨 : 同志们好啊!");
}
}
(3) 实现单一产品 : 面条大厨 , 制作面条
public class MianTiaoDaChu implements Foods {
/**
* 角色 : 面条大厨
* 任务 : 制作面条
* 目的 : 实现Foods接口,知道自己干什么
*/
@Override
public void makeFood() {
System.out.println("热腾腾的面条做好了:)");
}
}
(4) 实现单一产品: 馒头大厨, 制作馒头
public class ManTouDaChu extends Foods {
/**
* 角色 : 馒头大厨
* 任务 : 制作馒头
* 目的 : 实现Foods接口,知道自己干什么
*/
@Override
public void makeFood() {
System.out.println("热腾腾的馒头出炉了:)");
}
}
$. 服务风波 : 服务员听从大厅经理的话
(5) 实现总的任务 : 大厅经理 命令干活
/**
*角色:大厅经理
*任务:通知上菜
*目的:工厂方法为工厂类定义了接口,用多态来削弱了工厂类的职能
* @author yuan
*
*/
public abstract class ServiceFactorys {
//端菜去
public abstract Foods getFood();
//说出是谁
public void sayWho(){}
//说出的年龄
public void sayAge(){}
}
(6) 实现单一职责 : 饺子服务员,上菜,说名字
public class JiaoZiService extends ServiceFactorys {
/**
*角色:饺子专门服务员
*任务:去后厨拿饺子
*目的:单一的生产一种产品
*/
@Override
public Foods getFood() {
return new JiaoziDaChu();
}
@Override
public void sayWho() {
System.out.println("我是 饺子专门服务员 :(");
}
}
(7) 实现单一职责 : 面条服务员,上菜,说名字
public class MianTiaoService extends ServiceFactorys {
/**
*角色:面条专门服务员
*任务:去后厨拿面条
*目的:单一的生产一种产品
*/
@Override
public Foods getFood() {
return new MianTiaoDaChu();
}
@Override
public void sayWho() {
System.out.println("我是 面条专门服务员 :(");
}
}
(8) 实现单一职责 : 馒头服务员 , 上菜,说名字,说年龄
public class ManTouService extends ServiceFactorys {
/**
*角色:馒头专门服务员
*任务:去后厨拿馒头
*目的:单一的生产一种产品
*/
@Override
public Foods getFood() {
return new ManTouDaChu();
}
@Override
public void sayWho() {
System.out.println("我是 馒头专门服务员 :(");
}
@Override
public void sayAge() {
System.out.println("我今年20岁!");
}
}
$. 用户点饭, 大厅经理告知 上饭
(9) 实现测试 : 用户点菜, 服务上菜
/**
* 设计模式之工厂方法模式
*/
public class TestDemo {
/**
* 角色: 用户
* 任务: 点菜
* 目的: 测试
*/
public static void main(String[] args) {
ServiceFactorys factorys=new JiaoZiService();
JiaoziDaChu jiaoziDaChu= (JiaoziDaChu) factorys.getFood();
jiaoziDaChu.makeFood();
jiaoziDaChu.sayHello();
ServiceFactorys mantoufactorys=new ManTouService();
mantoufactorys.sayWho();
mantoufactorys.sayAge();
mantoufactorys.getFood().makeFood();
}
}
$. 关门数钱
(10) 实例小结
后厨主任 : 实现需要做的任务,必须实现的和非必要实现的任务,主要工作时安排大厨任务.
饺子,面条,馒头大厨 : 任务是做不同的产品.除了做产品,还可以去实现其他方法,比如说话.包含有和具体业务逻辑有关的代码实现。
大厅经历 : 安排服务员任务。
饺子,面条,馒头服务员:必须任务端菜.除了端菜,还可以实现其他方法。包含必要的业务逻辑和代码实现。
结果 :
3.优缺点
优点 :
(1)工厂方法模式类允许子类来决定实例化哪一个类.
(2)代码灵活,松耦合和可复用性,将对象创建的代码从客户端移到了工厂类,那就是它的子类。这非常易于维护相关代码,因为对象的创建非常集中。
(3)客户端代码只处理产品的接口,因此可以无需修改客户端的逻辑代码就能添加任何具体的产品。
(4)工厂方法的优势之一就是可以多次返回相同的实例,或者可以返回一个子类而不是一个具体类型的对象。
缺点 :
在可维护性上,可扩展性上是非常差的。
4.用途
使用场景 :
(1)对象的创建如果需要代码复用却没有现成的代码可用时,工厂方法设计模式就派上用场了。
(2)类并不知道需要创建的是什么子类。
(3)子类可以指定应该创建什么样的对象。
(4)父类会委托它的子类创建对象。
模式应用 :
第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。
例如 : Java Collection中的iterator() 方法即属于这种情况。
第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。
5.Demo免积分下载
接口模式demo :
http://download.csdn.net/detail/lablenet/9281223
抽象类模式demo :
http://download.csdn.net/detail/lablenet/9291275