工厂模式的几种形态:
1、简单工厂模式,又叫做静态工厂方法(Static Factory Method)模式。
2、工厂方法模式,又称为多态性工厂(Polymorphic Factory)模式
3、抽象工厂模式,又称工具(Kit或ToolKit)模式
简单工厂模式(Simple Factory)
1、模式:
简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。
它是由一个工厂对象决定创建出哪一种产品类的实例。
2、举例:
//水果接口
public interface Fruit{
void grow(); //生长
void harvest(); //收获
void plant(); //种植
}
//苹果类
public class Apple implements Fruit{
private int treeAge //树龄
public void grow(){
log("Apple is growing...");
}
public void harvest(){
log("Apple has been harvented.");
}
public void plant(){
log("Apple has been planted.");
}
//辅助方法
public static void log(String msg){
System.out.println(msg);
}
public int getTreeAge(){
return treeAge;
}
public void setTreeAge(int treeAge){
this.treeAge = treeAge;
}
}
//葡萄类
public class Grape implements Fruit{
private boolean seedless;
public void grow(){
log("Grape is growing...");
}
public void harvest(){
log("Grape has been harvested.");
}
public void plant(){
log("Grape has been planted.");
}
public static void log(String msg){
System.out.println(msg);
}
//有无籽方法
public boolean getSeedless(){
return seedless;
}
public void setSeedlees(boolean seedless){
this.seedless = seedless;
}
}
//草莓类
public class Strawberry implements Fruit{
public void grow(){
log("Strawberry is growing...");
}
public void harvest(){
log("Strawberry has been harvested.");
}
public void plant(){
log("Strawberry has been planted.");
}
public static void log(String msg){
System.out.println(msg);
}
}
//农场园丁类,由他决定创建哪种水果类的实例
public class FruitGardener{
//静态工厂方法
public static Fruit factory(String which) throws BadFruitException{
if(which.equalslgnoreCase("apple")){
return new Apple();
}else if(which.equalslgnoreCase("grape")){
return new Grape();
}else if(which.equalslgnoreCase("strawberry")){
return new Strawberry();
}else{
throw new BadFruitException("Bad fruit request");
}
}
}
//异常类
public class BadFruitException extends Exception{
public BadFruitException(String msg){
super(msg);
}
}
//测试类
public class Test{
FruitGardener gardener =new FruitGardener();
try{
gardener.factory("grape");
gardener.factory("apple");
gardener.factory("strawberry");
gardener.factory("banana"); //抛出异常
}catch(BadFruitException e){
System.out.println("dont't has this fruit.");
}
}
3、三个角色:
1、工厂类(Creator)角色:在客户端的直接调用下创建产品对象
2、抽象产品角色:可以用一个接口或者一个抽象类实现
3、具体产品角色:工厂方法模式所创建的任何对象都是这个角色的实例
4、如果工厂方法总是循环使用同一个产品对象,那么这个工厂对象可以使用一个属性来存储这个产品对象。
每一次客户端调用工厂方法时,工厂方法总是提供这同一个对象。
如果工厂方法永远循环使用固定数目的一些产品对象,而且这些产品对象的数目并不大的话,
可以使用一些私有属性存储对这些产品对象的引用。比如:一个永远只提供一个产品对象的工厂对象
可以使用一个静态变量存储对这个产品对象的引用。
如果工厂方法使用数目不确定,或者数目较大的一些产品对象的话,使用属性变量存储对这些产品对象的引用就不方便了,
这时候 就应当使用聚集对象存储对产品对象的引用。
5、其他模式;
1、单例模式:单例模式要求单例类的构造子是私有的,从而客户端不能直接将之实例化,而必须通过这个静态工厂方法将之实例化,
而且单例类自身是自己的工厂角色。单例类自己负责创建自身的实例
单例类使用一个静态属性存储自己的唯一的实例,工厂方法永远仅提供这一个实例
2、多例模式:它是对单例模式的推广,多例模式也禁止外界直接将之实例化,同时通过静态工厂方法想外界提供循环使用的自身的实例,
多例模式可以有多个实例
多例模式具有一个聚集属性,通过向这个聚集属性登记已经创建过的实例达到循环使用实例的目的,
它还拥有一个内部状态,每一个内部状态都只有一个实例存在
根据外界传入的参量,工厂方法可以查询自己的登记聚集,如果具有这个状态的实例已经存在,
就直接将这个实例提供给外界:反之,就首先创建一个新的满足要求的实例,将之登记到聚集中,然后再提供客户端。
3、备忘录模式:单例模式和多例模式使用一个属性或者聚集属性来登记所创建的产品对象,一边可以通过查询这个属性或者聚集属性
找到并共享已经创建了的产品对象,这就是备忘录模式的应用。
4、MVC模式:是更高层次上的架构模式。
包括:合成模式、策略模式、观察者模式、也有可能会包括装饰模式、调停者模式、迭代子模式以及工厂方法模式等。
****:如果系统需要有多个控制器参与这个过程的话,简单工厂模式就不适合了,应当考虑使用工厂方法模式。
6、简单工厂模式的优点己缺点
优点:模式的核心是工厂类,这个类有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例。
而客户端则可以免除直接创建产品对象的责任,而仅仅负责“消费”产品。简单工厂模式通过这种做法实现了对责任的分割
缺点:1)这个工厂类集中了所有的产品创建逻辑,形成一个无所不知的全能类,有人把这种类叫做上帝类(God Class)。
如果这个全能类代表的是农场的一个具体园丁的话,那么这个园丁就需要对所有的产品负责,成了农场的关键人物,
他什么时候不能正常工作了,整个农场都要受到影响;
2)将这么多的逻辑集中放在一个类里面的另外一个缺点是,当产品类有不同的接口种类时,工厂需要判断在什么时候创建某种产品,
这种对时机的判断和对哪一种具体产品的判断逻辑混合在一起,使得系统在将来进行功能扩展时较为困难。
这一缺点在工厂方法模式中得到克服
3)由于简单工厂模式使用静态方法作为工厂反尬,而静态方法无法由子类继承,因此工厂角色无法形成基于继承的等级结构。
这一缺点会在工厂方法模式中得到克服
7、“开——闭”原则要求一个系统的设计能够允许系统在无需修改的情况下,扩展其功能。
要求系统允许当新的产品加入系统中时,而无需对现有代码进行修改,这一点对于产品消费者角色是成立的,而对于工厂角色是不成立的
一般而言:一个系统总是可以划分成为产品的消费者角色(Client)、产品的工厂角色(Factory)以及产品角色(Product)三个子系统
对于产品消费者角色来说,任何时候需要某种产品,只需向工厂角色请求即可,而工厂角色在接到请求后,
会自行判断创建和提供哪一个产品,所以,产品消费者角色无需知道它得到的是哪一个产品,
产品消费者角色无需修改就可以接纳新的产品,而接纳新的产品意味着要修改这个工厂角色的源代码
(简单工厂角色只在有限的程度上支持“开—闭”原则)