三大工厂设计模式对比
简单工厂设计模式(Simple Factory Pattern)
指的是由一个工厂对象来决定创建出哪一类产品种类的实例.
简单工厂示例
创建一个工厂接口:
package com.zwx.service;
public interface IFactory {
public void create();
}
创建一个产品接口:
package com.zwx.service;
public interface IProduct {
public void test();
}
创建产品A:
package com.zwx.service.impl;
import com.zwx.service.IProduct;
public class ProductA implements IProduct {
public void test() {
System.out.println("===test==ProductA===");
}
}
创建产品B:
package com.zwx.service.impl;
import com.zwx.service.IProduct;
public class ProductB implements IProduct {
public void test() {
System.out.println("===test==ProductB===");
}
}
工厂实现类,实现了创建对象具体方法
package com.zwx.service.impl;
import com.zwx.service.IProduct;
public class SimpleFactory{
public IProduct create(String name){
if("A".equals(name)){
return new ProductA();
}else if("B".equals(name)){
return new ProductB();
}
return null;
}
测试类
package com.zwx.controller;
import com.zwx.service.IProduct;
import com.zwx.service.impl.SimpleFactory;
public class TestFactory1 {
public static void main(String[] args) {
SimpleFactory simpleFactory = new SimpleFactory();
IProduct procuct = simpleFactory.create("A");
procuct.test();
}
}
上面就基本上实现了一个简单工厂模式,但是我们发现,假如我们要增加一个产品C,那么我们就需要去修改创建工厂实现了类,这就违背了软件设计的开闭原则,所以,我们可以对CreateFactory类利用反射进行改进。
改进后的工厂实现类
package com.zwx.service.impl;
import com.zwx.service.IProduct;
public class SimpleFactory {
public IProduct create2(Class<? extends IProduct> clazz) throws InstantiationException, IllegalAccessException{
if(null == clazz){
return null;
}
return clazz.newInstance();
}
}
测试类:
package com.zwx.controller;
import com.zwx.service.IFactoryMethod;
import com.zwx.service.IProduct;
import com.zwx.service.impl.ProductCCFactory;
import com.zwx.service.impl.ProductCFactory;
/**
* 工厂方法测试
* @author zwx
*/
public class TestFactory2 {
public static void main(String[] args) {
// IFactoryMethod factory = new ProductCFactory();
// IProduct product = factory.create();
// product.test();
IFactoryMethod factory2 = new ProductCCFactory();
IProduct product2 = factory2.create();
product2.test();
}
}
简单工厂模式适用场景
简单工厂适用于工厂类负责创建的对象较少的场景,且客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心
简单工厂模式缺点
假如每种产品创建不仅仅只是实例化一个对象,还有其他逻辑需要处理,那么我们无法直接使用一句反射,避免不了写很多if(亦或者用switch循环),这样的话每新增一个产品我们都需要修改工厂实现类,随着产品链越来越丰富,工厂的职责会变得越来越多,久而久之会越来越难以维护。
工厂方法设计模式(Fatory Method Pattern)
工厂方法模式是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个对象,工厂方法让类的实例化推迟到子类中进行,在工厂方法模式中用户只需要关心所需产品对应的工厂,无须关心创建细节,而且加入新的产品符合开闭原则。
创建一个工厂接口,注意这里和简单工厂的区别是接口内方法有返回值
package com.zwx.service;
public interface IFactoryMethod {
public IFactoryMethod create();
}
创建一个产品C类
package com.zwx.service.impl;
import com.zwx.service.IProduct;
public class ProductC implements IProduct {
public void test(){
System.out.println("===test==ProductC===");
}
}
创建一个产品C工厂类
package com.zwx.service.impl;
import com.zwx.service.IFactoryMethod;
import com.zwx.service.IProduct;
public class ProductCFactory implements IFactoryMethod {
public IProduct create() {
return new ProductC();
}
}
最后,添加测试类
package com.zwx.controller;
import com.zwx.service.IFactoryMethod;
import com.zwx.service.IProduct;
import com.zwx.service.impl.ProductCFactory;
public class TestFactory2 {
public static void main(String[] args) {
IFactoryMethod factory = new ProductCFactory();
IProduct product = factory.create();
product.test();
}
}
如此就成功创建了对象C,假如要增加对象D,那么我们只需要新增一个对象C类和其对应的一个工厂类即可,不需要去修改原有的工厂类,符合了开闭原则。
工厂方法模式适用场景
1、创建对象需要大量重复的代码。
2、客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
3、一个类通过其子类来指定创建哪个对象。
工厂方法模式缺点
1、类的个数容易过多,增加复杂度。
2、增加了系统的抽象性和理解难度
抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。客户端(应用层)不依赖于产品类实例如何被创建、实现等细节,强调的是一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
抽象工厂示例
创建一个抽象接口:
package com.zwx.service;
public interface IAbstractFactory {
IApple createApple();
IOrange createOrange();
}
创建两个产品接口:
package com.zwx.service;
public interface IApple {
void eatApple();
}
package com.zwx.service;
public interface IOrange {
void eatOrange();
}
假设现在有一个农场要去生产这两种产品,建立如下两个类:
package com.zwx.service.impl;
import com.zwx.service.IApple;
public class Farm1Apple implements IApple {
public void testApple() {
System.out.println("=====farm1==testApple");
}
}
package com.zwx.service.impl;
import com.zwx.service.IOrange;
public class Farm1Orange implements IOrange{
public void testOrange() {
System.out.println("=====farm1==testOrange");
}
}
接下来创建一个农场1的具体工厂类:
package com.zwx.service.impl;
import com.zwx.service.IAbstractFactory;
import com.zwx.service.IApple;
import com.zwx.service.IOrange;
public class Farm1AbstractFactory implements IAbstractFactory{
public IApple createApple() {
return new Farm1Apple();
}
public IOrange createOrange() {
return new Farm1Orange();
}
}
最后再建立一个测试类测试:
package com.zwx.controller;
import com.zwx.service.impl.Farm1AbstractFactory;
public class TestFactory3 {
public static void main(String[] args) {
Farm1AbstractFactory factory = new Farm1AbstractFactory();
factory.createApple().testApple();
factory.createOrange().testOrange();
}
}
此时,如果有一个农场2又要来生产Apple和Orange,那么再新增两个对应的产品类以及一个具体工厂类即可实现。
抽象工厂使用场景
当我们有一系列产品(如上面的Apple,Orange)。而这一系列产品每种产品又需要具有不同的创建方法(如上种植Apple和种植Orange方法肯定是不同的需要不同的方法实现)。
抽象工厂缺点
1、规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂
的接口。
2、增加了系统的抽象性和理解难度。