简单工厂模式

简单工厂模式

0.前言

  • 设计模式篇主要是阅读《大话设计模式》的记录,同时也有阅读五月的仓颉中设计模式相关部分。

1.定义

  • 简单工厂模式又叫做静态工厂方法模式简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。

2.为什么使用

  • 用来解决如何去实例化对象的问题。
    • 到底要实例化谁,将来会不会增加实例化的对象,这是很容易变化的地方,应该考虑用一个单独的类来做这个创造实例的过程,这就是工厂。
  • 缺点
    • 工厂类的职责相对过重,增加新的产品时需要修改工厂类的判断逻辑,违背开闭原则。每次有新的实例类产生时,需要在工厂方法中增加判断逻辑。

3.如何实现

  • 以一个简单的计算器程序来说明
package cn.sun.code.one.ouhe;

/**
 * Created by rider on 2018/11/21.
 * 1.9 紧耦合 vs 松耦合
 */
public class Operation {

	private double numberA;

	private double numberB;

	public double getNumberA() {
		return numberA;
	}

	public void setNumberA(double numberA) {
		this.numberA = numberA;
	}

	public double getNumberB() {
		return numberB;
	}

	public void setNumberB(double numberB) {
		this.numberB = numberB;
	}

	public double getResult() {
		double result = 0d;
		return result;
	}
}

class OperationAdd extends Operation {

	public double getResult() {
		double result = 0d;
		result = this.getNumberA() + this.getNumberB();
		return result;
	}

}

class OperationSub extends Operation {

	public double getResult() {
		double result = 0d;
		result = this.getNumberA() - this.getNumberB();
		return result;
	}

}

class OperationMul extends Operation {

	public double getResult() {
		double result = 0d;
		result = this.getNumberA() * this.getNumberB();
		return result;
	}

}

class OperationDiv extends Operation {

	public double getResult() {
		double result = 0d;
		if(getNumberB()==0)
			throw new RuntimeException("除数不能为0");
		result = this.getNumberA() / this.getNumberB();
		return result;
	}

}

package cn.sun.code.one.ouhe;

/**
 * Created by rider on 2018/11/21.
 * 简单工厂模式
 */
public class OperationFactory {

	public static Operation createOperate(String operate) {
		Operation operation = null;
		switch (operate) {
			case "+":
				operation = new OperationAdd();
				break;
			case "-":
				operation = new OperationSub();
				break;
			case "*":
				operation = new OperationMul();
				break;
			case "/":
				operation = new OperationDiv();
				break;
		}
		return operation;
	}

	/**
	 * 客户端代码
	 *
	 * @param args
	 */
	public static void main(String[] args) {
		Operation operation = null;
		operation = OperationFactory.createOperate("+");
		operation.setNumberA(1);
		operation.setNumberB(2);
		double result = operation.getResult();
		System.out.println(result);
	}
	
}

  • 通过多态,返回父类的方式实现了计算器的结果
  • 如果有一天需要修改加法运算,只需要修改OperationAdd就可以了;如果要增加其它运算种类,比如平方根等,只需要增加运算种类,同时修改工厂类中的逻辑判断即可。

  • 简单工厂模式的优点:
    • 简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。

4.简单工厂模式在Java中的应用

  • 客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不要关心 。
  • Calendar的相关应用
    public static Calendar getInstance(Locale aLocale)
    {
        return createCalendar(TimeZone.getDefault(), aLocale);
    }
    private static Calendar createCalendar(TimeZone zone,
                                           Locale aLocale)
    {
        CalendarProvider provider =
            LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                 .getCalendarProvider();
        if (provider != null) {
            try {
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException iae) {
                // fall back to the default instantiation
            }
        }

        Calendar cal = null;

        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype != null) {
                switch (caltype) {
                case "buddhist":
                cal = new BuddhistCalendar(zone, aLocale);
                    break;
                case "japanese":
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                case "gregory":
                    cal = new GregorianCalendar(zone, aLocale);
                    break;
                }
            }
        }
        if (cal == null) {
            // If no known calendar type is explicitly specified,
            // perform the traditional way to create a Calendar:
            // create a BuddhistCalendar for th_TH locale,
            // a JapaneseImperialCalendar for ja_JP_JP locale, or
            // a GregorianCalendar for any other locales.
            // NOTE: The language, country and variant strings are interned.
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        return cal;
    }
  • 日志系统中相关应用
  public static Logger getLogger(String name) {
    ILoggerFactory iLoggerFactory = getILoggerFactory();
    return iLoggerFactory.getLogger(name);
  }
{
    Logger slf4jLogger = (Logger)this.loggerMap.get(name);
    if (slf4jLogger != null) {
      return slf4jLogger;
    } else {
      org.apache.log4j.Logger log4jLogger;
      if (name.equalsIgnoreCase("ROOT")) {
        log4jLogger = LogManager.getRootLogger();
      } else {
        log4jLogger = LogManager.getLogger(name);
      }

      Logger newInstance = new Log4jLoggerAdapter(log4jLogger);
      Logger oldInstance = (Logger)this.loggerMap.putIfAbsent(name, newInstance);
      return (Logger)(oldInstance == null ? newInstance : oldInstance);
    }
  }
原文地址:https://www.cnblogs.com/riders/p/12191235.html