工厂模式我理解为 将一个对象的产生过程封装在工厂类里,而工厂对外提供一个公共的方法供外界调用。
下面是工厂模式的一些写法,方法名字看不懂不重要。
1、简单工厂
接口实例化时,需要用不同的子类来返回不同的对象;需要多个对象就需要new出多个来。
例如需要柠檬就需要 IFruits lemmon =new Lemmon();
用工厂方法可以完成统一的调用,而且工厂方法本身是单例模式,省去new的操作。
缺点也比较明显,我需要新产生水果-->苹果时,需要修改工厂中的生产方法,将苹果的判断加进去。
这不符合软件的开闭原则:对扩展开放、对修改关闭。
简单工厂在Log4j中有很多应用。
package com.ldy.designpattern.simpleFactory;
public class IFruitsFactory {
public IFruits make(String name){
if(name.equals("waterlemmon"))
return new WaterLemmon();
else if(name.equals("lemmon")){
return new Lemmon();
}else{
return null;
}
}
public static void main(String[] args) {
// IFruits iFruits= new WaterLemmon();
//一个工厂对象可以生成多个需要的对象
IFruitsFactory factory=new IFruitsFactory();
IFruits lemmon= factory.make("lemmon");
IFruits waterlemmon = factory.make("waterlemmon");
lemmon.make();
waterlemmon.make();
}
}
2、工厂方法
简单工厂使用时需要传入参数容易输错,又不符合开闭原则。工厂方法则解决了这些问题。它是通过为每一个接口和实现类都建造一个工厂,实现类的工厂同样实现接口的工厂。
package com.ldy.designpattern.simpleFactory.factory;
import com.ldy.designpattern.simpleFactory.IFruits;
public interface IFruitsFactory {
public IFruits ifruits();
}
package com.ldy.designpattern.simpleFactory.factory;
import com.ldy.designpattern.simpleFactory.IFruits;
import com.ldy.designpattern.simpleFactory.Lemmon;
public class LemmonFactory implements IFruitsFactory{
@Override
public IFruits ifruits() {
return new Lemmon();
}
}
package com.ldy.designpattern.simpleFactory.factory;
import com.ldy.designpattern.simpleFactory.IFruits;
import com.ldy.designpattern.simpleFactory.WaterLemmon;
import com.ldy.designpattern.simpleFactory.factory.IFruitsFactory;
public class WaterLemmonFactory implements IFruitsFactory {
@Override
public IFruits ifruits() {
return new WaterLemmon();
}
}
如果需要生产新的产品比如苹果。则建立Apple.java并实现IFruits接口,对用建立Apple.java与AppleFactory。
而不需要修改原有的接口,符合开闭原则。并且在调用的时候,只用调用工厂接口,用不同的工厂实现。
工厂方法的缺陷也比较明显,每一个产品都需要对应两个类。类的数量将会越来愈多,代码结构也更复杂。但是简单工厂和工厂方法都容易理解,用起来很方便。
3、抽象工厂
抽象工厂则将所有产品的制造过程方法都提前定义好,作为生产的标准。WaterLemmonFactory同样实现此接口,只用实现制造西瓜的方法即可。其他接口的放都不进行实现。
package com.ldy.designpattern.simpleFactory.factory;
import com.ldy.designpattern.simpleFactory.IFruits;
/**
* 定义好所有的产品生产路线,
* 实现类实现不同的方法来完成不同产品的生产
*/
public interface IFruitsFactory {
public IFruits createLemmon();
public IFruits createWaterLemmonLemmon();
public IFruits createApple();
public IFruits createElse();
}
package com.ldy.designpattern.simpleFactory.factory;
import com.ldy.designpattern.simpleFactory.IFruits;
import com.ldy.designpattern.simpleFactory.Lemmon;
public class LemmonFactory implements IFruitsFactory{
@Override
public IFruits createLemmon() {
return new Lemmon();
}
@Override
public IFruits createWaterLemmonLemmon() {
return null;
}
@Override
public IFruits createApple() {
return null;
}
@Override
public IFruits createElse() {
return null;
}
}
抽象工厂其实依然不符合开闭原则。公共接口一但修改,他所有的实现类都需要更新。所以他不太适合经常升级代码的场景。