设计模式《工厂方法模式》

2018-07-06  本文已影响0人  天道__

引言

  上一节我们说了单例模式,这一节我们来说说工厂方法模式。

示例地址

  Demo

先看类图

image

工厂方法模式定义

  定义一个用于创建对象的接口,让子类决定实例化哪一个类。

使用场景

  在任何需要生成复制对象的地方,都可以使用工厂方法模式。

工厂方法模式示例

  举个例子,我们吃饭的时候都会点主食,主食的种类分为 米饭、面,南方人喜欢吃米饭,但是北方人喜欢吃面。

简单工厂模式

1. 我们先来设计产品
/**
 * 主食
 * @author 512573717@qq.com
 * @created 2018/7/6  下午2:36.
 *
 */
public interface IZhuShi {
    // 主食吃什么
    void eat();
}
2. 产品一:南方人爱吃米饭
/**
 *  主食米饭
 *
 * @author 512573717@qq.com
 * @created 2018/7/6  下午2:37.
 *
 */
public class Rice implements IZhuShi {
    @Override
    public void eat() {
      System.out.println("主食米饭上来了。");
    }
}
3. 产品二:北方人爱吃面食
/**
 * 主食面
 *
 * @author 512573717@qq.com
 * @created 2018/7/6  下午2:43.
 */
public class Flour implements IZhuShi {
    @Override
    public void eat() {
        System.out.println("主食 面上来了。");
    }
}

简单(静态)工厂

  接下来是我们怎么创建产品了,就是我们在点餐的时候要选择吃什么。

1. 主食工厂
/**
 * 主食工厂
 *
 * @author 512573717@qq.com
 * @created 2018/7/6  下午2:48.
 */
public class FactoryZhuShi {
    //南方人
    public static final int SOUTH = 1;
    //北方人
    public static final int NORTH = 2;

    public  static IZhuShi createZhuShi(int type) {
        switch (type) {
            case SOUTH:
                return new Rice();
            case NORTH:
                return new Flour();
            default:
                return new Rice();
        }
    }
}
2. 调用工厂创建产品
  IZhuShi south = FactoryZhuShi.createZhuShi(FactoryZhuShi.SOUTH);
  south.eat();

  IZhuShi north = FactoryZhuShi.createZhuShi(FactoryZhuShi.NORTH);
  north.eat();
3. 如果我们增加了产品三(水饺),这个时候就需要修改工程类了,违背了设计模式的六大原则(开闭原则)。

简单(反射)工厂

  Java中反射是无所不能的。那我们就反一种思路,我们通过反射实现。

1. 反射实现工厂
/**
 * 通过反射获取主食
 *
 * @author 512573717@qq.com
 * @created 2018/7/6  下午3:11.
 */
public class ReflectFactoryZhuShi {

    public static <T extends IZhuShi> T createZhuShi(Class<T> cls) {
        T object = null;
        try {
            object = (T) (Class.forName(cls.getName())).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return object;
    }
}
2. 调用工厂创建产品
 IZhuShi south = ReflectFactoryZhuShi.createZhuShi(Rice.class);
 south.eat();

 IZhuShi north = ReflectFactoryZhuShi.createZhuShi(Flour.class);
 north.eat();
3. 在增加新产品的时候,我们无需修改工厂类,解决设计模式的开闭原则。但是反射影响性能,我们在来看看方法工厂模式

简单工厂

  反射有效率问题,我们看看最常用的一种写法

1. 日常写法
/**
 * 简单工厂
 *
 * @author 512573717@qq.com
 * @created 2018/7/6  下午3:37.
 */
public class MethodFactoryZhuShi {

    public static Rice getRice() {
        return new Rice();
    }

    public static Flour getFlour() {
        return new Flour();
    }
}
2. 简单调用
   IZhuShi south = MethodFactoryZhuShi.getRice();
   south.eat();

   IZhuShi north = MethodFactoryZhuShi.getFlour();
   north.eat();

工厂方法模式

1. 工厂接口
/**
 * 主食创建工厂
 *
 * @author 512573717@qq.com
 * @created 2018/7/6  下午4:08.
 */
public interface IFactory<T extends IZhuShi> {
    T create();
}
2. 米饭工厂
/**
 *  米饭工厂
 * 
 * @author 512573717@qq.com
 * @created 2018/7/8  下午11:11.
 * 
 */
public class RiceFactory implements IFactory<Rice> {
    @Override
    public Rice create() {
        return new Rice();
    }
}
3. 面食工厂
/**
 *  面食工厂
 *
 * @author 512573717@qq.com
 * @created 2018/7/8  下午11:11.
 *
 */
public class FlourFactory implements IFactory<Flour> {
    @Override
    public Flour create() {
        return new Flour();
    }
}
4. 简单调用
 IFactory northFactory = new FlourFactory();
 IZhuShi north = northFactory.create();
 north.eat();

 IFactory southFactory = new RiceFactory();
 IZhuShi south = southFactory.create();
 south.eat();

总结

   当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。(即当有新产品时,只要创建并基础抽象产品;新建具体工厂继承抽象工厂;而不用修改任何一个类)工厂方法模式是完全符合开闭原则的!

上一篇 下一篇

猜你喜欢

热点阅读