简单工厂,工厂方法,抽象工厂,三种工厂模式

264 阅读6分钟

简单工厂

简单工厂是真的简单,如果我们有N个类需要被工厂管理,那我们给N个类分配一个唯一标识,调用工厂方法需要传递标识,工厂根据传入的标识创建对象。这种做法的缺点很明显,扩展性太差!严重违反开闭原则。如果要是又新增M个类需要被工厂管理,那么还要去改工厂类代码。

package simplefactory_k;/*
* @auther 顶风少年 
* @mail dfsn19970313@foxmail.com
* @date 2020-01-15 10:45
* @notify 
* @version 1.0
*/
public class Airplane {

}

View Code

package simplefactory_k;/*
* @auther 顶风少年 
* @mail dfsn19970313@foxmail.com
* @date 2020-01-15 10:46
* @notify 
* @version 1.0
*/
public class Rocket {
}

View Code

package simplefactory_k;/*
* @auther 顶风少年 
* @mail dfsn19970313@foxmail.com
* @date 2020-01-15 10:46
* @notify 
* @version 1.0
*/
public class Screw {
}

View Code

package simplefactory_k;
/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2020-01-15 10:46
 * @notify
 * @version 1.0
 */

public class SimpleFactoryK {
    public static Object getObject(String obj) {
        if (obj.equals("飞机")) {
            return new Airplane();
        } else if (obj.equals("火箭")) {
            return new Rocket();
        } else if (obj.equals("螺丝")) {
            return new Screw();
        } else {
            return null;
        }
    }
}

View Code

package simplefactory_k;
/*
* @auther 顶风少年 
* @mail dfsn19970313@foxmail.com
* @date 2020-01-15 10:53
* @notify 
* @version 1.0
*/
public class Main {
    public static void main(String[] args) {
        Object airplane = SimpleFactoryK.getObject("飞机");
        System.out.println(airplane instanceof Airplane);

        Object rocket = SimpleFactoryK.getObject("火箭");
        System.out.println(rocket instanceof Rocket);

        Object screw = SimpleFactoryK.getObject("螺丝");
        System.out.println(screw instanceof Screw);
    }
}

View Code

工厂方法

工厂方法弥补了简单工厂不易于扩展的缺点,给一个产品族定义一个接口,产品族下边定义具体的产品实现。(产品族的纵向的,接口和实现类,或者抽象类和子类)创建产品族工厂接口,不同的产品工厂创建不同的产品。苹果和香蕉都是都是水果族,苹果工厂生产苹果,香蕉工厂生产香蕉,而他们属于水果工厂。当我们需要增加另外一种水果,例如橘子,需要我们创建一个橘子类,和一个橘子类的工厂,这听起来好像又麻烦了许多。但是我们假设,创建一个类需要很多的参数,整体的创建需要写很多的代码。那创建一个工厂类是完全有必要的。

package factorymethod_k;/*
* @auther 顶风少年 
* @mail dfsn19970313@foxmail.com
* @date 2020-01-15 14:22
* @notify 
* @version 1.0
*/
public interface Fruiter {
    void product();
}

View Code

package factorymethod_k;/*
* @auther 顶风少年 
* @mail dfsn19970313@foxmail.com
* @date 2020-01-15 14:24
* @notify 
* @version 1.0
*/
public class Apple implements Fruiter {
    @Override
    public void product() {
        System.out.println("种出苹果");
    }
}

View Code

package factorymethod_k;/*
* @auther 顶风少年 
* @mail dfsn19970313@foxmail.com
* @date 2020-01-15 14:24
* @notify 
* @version 1.0
*/
public class Banana implements Fruiter {
    @Override
    public void product() {
        System.out.println("种出香蕉");
    }
}

View Code

package factorymethod_k;/*
* @auther 顶风少年 
* @mail dfsn19970313@foxmail.com
* @date 2020-01-15 14:25
* @notify 
* @version 1.0
*/
public interface Farm {
    Fruiter getBean();
}

View Code

package factorymethod_k;/*
* @auther 顶风少年 
* @mail dfsn19970313@foxmail.com
* @date 2020-01-15 14:26
* @notify 
* @version 1.0
*/

import factoryMethod.Fruit;

public class AppleFarm  implements Farm{
    @Override
    public Fruiter getBean() {
        return new Apple();
    }
}

View Code

package factorymethod_k;/*
* @auther 顶风少年 
* @mail dfsn19970313@foxmail.com
* @date 2020-01-15 14:26
* @notify 
* @version 1.0
*/
public class BananaFarm implements Farm{
    @Override
    public Fruiter getBean() {
        return new Banana();
    }
}

View Code

package factorymethod_k;/*
* @auther 顶风少年 
* @mail dfsn19970313@foxmail.com
* @date 2020-01-15 14:29
* @notify 
* @version 1.0
*/


public class Client {
    public static void main(String[] args) {

        Farm farm = new AppleFarm();
        Fruiter fruiter = farm.getBean();

        Farm farm2 = new BananaFarm();
        Fruiter fruiter2 = farm2.getBean();

        System.out.println(fruiter instanceof Apple);
        System.out.println(fruiter2 instanceof Banana);
    }
}

View Code

抽象工厂

工厂方法对于单一产品族是够用了,但是如果是多产品族就不行了。思考一个场景,有一个水果族,和一个蔬菜族。水果和蔬菜都分热带种植环境,和常温种植环境。如果使用工厂方法,我们要怎么做呢?创建一个水果族接口,创建一个水果族工厂接口,创建一个蔬菜族的接口,一个蔬菜族工厂接口。但这显然是不符合实际逻辑的,热带水果和常温水果肯定不能在一个工厂被创建出来。热带蔬菜和常温蔬菜也是。于是我们需要横向抽取。热带水果,常温水果都是水果,热带蔬菜,常温蔬菜都是蔬菜。我们在园丁接口做抽取,有管理常温农作物的园丁和管理热带农作物的园丁。现在一个农场就可以创建两个族群的产品了。

package abstractFactory;
/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2019-07-24 10:55
 * @notify 蔬菜接口
 * @version 1.0
 */

public interface Veggie {
}

View Code

package abstractFactory;
/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2019-07-24 10:58
 * @notify 热带的蔬菜
 * @version 1.0
 */

import com.sun.org.apache.regexp.internal.RE;

public class TropicalVeggie implements Veggie {
    private String name;

    public TropicalVeggie(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

View Code

package abstractFactory;
/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2019-07-24 10:56
 * @notify 北方的蔬菜
 * @version 1.0
 */

public class NorthernVeggie implements Veggie {
    private String name;

    public NorthernVeggie(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

View Code

package abstractFactory;
/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2019-07-24 11:00
 * @notify 水果接口
 * @version 1.0
 */

public interface Fruit {
}

View Code

package abstractFactory;
/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2019-07-24 11:00
 * @notify 北方的水果
 * @version 1.0
 */

public class NorthernFruit implements Fruit {
    private String name;

    public NorthernFruit(String name) {
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }

}

View Code

package abstractFactory;
/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2019-07-24 11:02
 * @notify 热带的水果
 * @version 1.0
 */

public class TropicalFruit implements Fruit {
    private String name;

    public TropicalFruit(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

View Code

package abstractFactory;
/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2019-07-24 10:50
 * @notify 园丁抽象类
 * @version 1.0
 */

public interface Gardener {
}

View Code

package abstractFactory;/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2019-07-24 10:50
 * @notify 管理北方农场的园丁
 * @version 1.0
 */

public class NorthernGardener implements Gardener {

    //    北方的水果
    public Fruit createFruit(String name) {
        return new NorthernFruit(name);
    }

    //北方的蔬菜
    public Veggie createVeggie(String name) {
        return new NorthernVeggie(name);
    }
}

View Code

package abstractFactory;
/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2019-07-24 10:53
 * @notify 管理热带农场的园丁
 * @version 1.0
 */


public class TropicalGardener implements Gardener{

    //热带水果
    public Fruit createFruit(String name){
        return new TropicalFruit(name);
    }

    //热带蔬菜
    public Veggie createVeggie(String name){
        return new TropicalVeggie(name);
    }
}

View Code

package abstractFactory;/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2019-07-24 12:28
 * @notify
 * @version 1.0
 */

import junit.framework.TestCase;

public class AbstractFactoryTest extends TestCase {
    public void testCreate(){
        TropicalGardener tropicalGardener = new TropicalGardener();
        Fruit fruit1 = tropicalGardener.createFruit("热带水果");
        Veggie veggie1 = tropicalGardener.createVeggie("热带蔬菜");
        assertTrue(fruit1 instanceof TropicalFruit);
        assertTrue(veggie1 instanceof  TropicalVeggie);

        NorthernGardener northernGardener = new NorthernGardener();
        Fruit fruit2 = northernGardener.createFruit("北方水果");
        Veggie veggie2 = northernGardener.createVeggie("北方蔬菜");
        assertTrue(fruit2 instanceof NorthernFruit);
        assertTrue(veggie2 instanceof  NorthernVeggie);

    }
}

View Code