23种设计模式之——工厂方法模式

时间:2022-10-02 14:48:03

上一次了解了一个模式,为简单工厂模式,

了解了其特点运用场景和用比不用的好处。

那么这个简单工厂模式有没有缺点呢?当然是有的:

1.在Factory类中如果创造实例的方法是

public Fruit get(String type){
Class clazz = Class.forName(type);
return (Fruit)clazz.newInstance();
}
那么在主程序中用户调用这个Factory类时必须这么调用
     Fruit apple = Factory.get("Apple");
    这个参数Apple写成apple都是错误的!也就是说用户在传入参数的时候一点都不*,

    如果有一点小问题就会抛出异常,这明显是不*的。


因此我们需要修改这个Factory中的方法,可以把Factory中的get方法变为:

public Fruit get(String type){
if(type.equalsIgnoreCase("apple")){
//返回苹果实例
}else if(type.equalsIgnoreCase("pear")){
//返回莉的实例
}else{
return null;}<span style="font-size:18px;">//上述中if中的判断可以自己加,这样用户在传值的时候就会更舒服,更*。类似于在买水果时说买苹果可以得到苹果,买apple也是可以得到苹果的。</span>

不过这样是解决了*度的问题,但是又衍生出了另一个问题,程序封装性和扩展性问题。

假设我们又有了新的水果Banana.java,

那么为了得到它的实例我们必须又要改动Factory.java中的代码,加上banana的判断,

这样显示是不合适的
因为程序设计的原则是弱耦合强引用,

不能因为新出现的类而去大浮动的改变原有的类

而是可以做到在原有的类上进行更好的扩展。
于是就出现了下一种设计模式:

FactoryMethod(工厂方法模式)

我们还是根据三重思维来分析这个设计模式:
1.FactoryMethod的特点:
工厂方法模式同样属于类的创建型模式又被称为多态工厂模式。
工厂方法模式的意义是定义一个创建产品对象的工厂接口
         将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,
       这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口。


根据定义我们可以知道这个模式当中具有的一些特质:
1)有一个工厂接口:(抽象工厂--creater)
在simpleFactory中没有这个接口,而是直接一个工厂类,创造所有的水果都在这个类中。
但是在FactoryMethod中不直接创造一个具体的大工厂,而是有一个工厂接口,

这个接口提供了抽象的创造水果的方法。但是它不具体实现


2)有一些具体的工厂子类:(具体工厂--concrete creater)
这一些具体的工厂子类实现核心工厂接口并且复写这个工厂中提供的方法

用于创造不同的实例对象。


3)产品父类接口:(productor)
4)具体子类产品:(concrete productor)
3),4)在simpleFactory中是有的。


2.如何运用这种模式:
直接上代码:

  1)抽象工厂接口:Factory.java

/**
* 工厂基类,所有工厂类的子类
* 对外暴露一个生产fruit的方法,由具体的子类来实现
* @author sgg
*
*/
public interface Factory {
/**
* 得到fruit实例的方法
* @return fruit的实例
*/
public Fruit getFruit();
}
       2)具体工厂子类:AppleFactory.java

/**
* factory的直接子类,用来创造apple的工厂
* @author sgg
*
*/
public class AppleFactory implements Factory{

@Override
public Fruit getFruit() {
// TODO Auto-generated method stub
return new Apple();
}

}

 2)具体工厂子类:PearFactory.java

/**
* Factory的直接子类,用来生产pear的factory
* @author sgg
*
*/
public class PearFactory implements Factory{

@Override
public Fruit getFruit() {
// TODO Auto-generated method stub
return new Pear();
}

}
3)产品父类接口:Fruit.java

import javax.sound.midi.VoiceStatus;

/**
* 所有水果的基类,暴露一个方法供其子类具体实现
* @author sgg
*
*/
public interface Fruit {
/**
* 卖水果的方法
*/
public void sell();
}

4)具体子类产品:Apple.java

/**
* fruit类的直接子类
* @author sgg
*
*/
public class Apple implements Fruit{

@Override
public void sell() {
//卖苹果的方法
}

}

4)具体子类产品:Pear.java

/**
* Fruit类的直接子类pear类
* @author sgg
*
*/
public class Pear implements Fruit{

@Override
public void sell() {
//卖梨的方法
}

}
5)程序入口以及调用:FactoryMethod.java

public class FactoryMethod {
public static void main(String[] args) {
//生成applefactory
Factory appleFactory = new AppleFactory();
//由appleFactory得到apple实例
Fruit apple = appleFactory.getFruit();

//生成pearfactory
Factory pearFactory = new PearFactory();
//由pearFactory得到pear实例
Fruit pear = pearFactory.getFruit();

//分别调用两个水果的两种方法
apple.sell();
pear.sell();
}
}

3.这种模式运用说明
这个明显是简单工厂模式的升级,解决了简单工厂模式中的一些问题:

*度与封装性扩展之间的矛盾
解决的方法就是将核心工厂类抽象化,

根据产品的类型来生成对应的子类工厂并具体实现产生实例的方法。
相当于在工厂和水果之间搭了座桥。


下为两种模式的区别图解:

SimpleFactory(简单工厂模式)

23种设计模式之——工厂方法模式


FactoryMethod(工厂方法模式)

23种设计模式之——工厂方法模式


这里有一个疑问,既然工厂方法模式中是
一类水果对应一个工厂,那么为什么还要运用工厂模式呢?
直接水果方法生成水果实例不就行了么?
其实关于这点我也理解的不是很透彻,

现在就是先了解其特点,至于为什么要有这种设计模式得慢慢研究。

抽空说说抽象工厂模式