设计模式之简单工厂

简单工厂(静态工厂)

定义:由一个工厂对象决定创建出哪一种产品类的实例

类型:创建型,不属于GOF23种设计模式

适用场景

  • 工厂类负责创建的对象比较少
  • 客户端(应用层)只知道传入工厂类的参数,对于如何创建对象(逻辑)并不关心

优点

  • 只需要传入一个正确的参数,就可以获取你所需要的对象而不需要知道其创建的细节

缺点

  • 工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背了开闭原则

UML类图:

IProduct:抽象产品接口,具体产品都需要遵循的规范

Product:具体产品实现类

Creator:工厂类,提供工厂方法创建产品实例

示例

我们知道不同品牌的打印机都需要安装相应品牌的驱动程序才能正常使用,这里以惠普和佳能打印机为例

  • 直接在使用时候由客户端创建产品对象
//使用佳能打印机,需要在客户端主动new对象
CanonPrinter canonPrinter = new CanonPrinter();
canonPrinter.print();
//使用惠普打印机
HpPrinter hpPrinter = new HpPrinter();
hpPrinter.print();
  • 使用简单工厂模式,产品对象的创建全部交给工厂对象(或工厂类),只需要传递关于产品的参数即可
/**
 * 各个打印机需要实现的打印机接口(产品接口)
 */
public interface IPrinter {
    void print();
}
/**
 * 佳能打印机(具体产品)
 */
public class CanonPrinter implements IPrinter {

    @Override
    public void print(){
        System.out.println("佳能打印机开始打印...");
    }

}
/**
 * 惠普打印机(具体产品)
 */
public class HpPrinter implements IPrinter{

    @Override
    public void print(){
        System.out.println("惠普打印机开始打印...");
    }

}
/**
 * 打印机工厂(负责根据参数创建产品实例)
 */
public class PrinterFactory {
    /**
     * 如果该工厂仍然需要提供给子类扩展,则去掉工厂的静态方法,修改为实例方法,去掉私有构造,这里是当 成是静态工厂使用
     */
    private PrinterFactory(){

    }

    public static IPrinter createPrinter(String printerName){
        if("canon".equals(printerName)){
            return new CanonPrinter();
        }else if("hp".equals(printerName)){
            return new HpPrinter();
        }
        return null;
    }
}
public static void main(String[] args) {
    IPrinter canonPriner = PrinterFactory.createPrinter("canon");
    canonPriner.print();
    IPrinter hpPrinter = PrinterFactory.createPrinter("hp");
    hpPrinter.print();
}
  • 在简单工厂的基础上加上反射技术,修改PrinterFactory中的createPrinter方法和参数,让输入参数可控
public static IPrinter createPrinter(Class<? extends IPrinter> clazz) throws IllegalAccessException, InstantiationException {
    return clazz.newInstance();
}

上面中的的打印机实例都是由一个打印机工厂类进行创建,如果增加了不同的打印机,则仍然需要修改该工厂类,违反了开闭原则。在后面的工厂方法模式就可以解决这个问题,工厂方法模式中,就是将产品对象的创建延迟到工厂子类去实现,每当需要生产一种产品,就需要引入一个新的工厂类,这样对于客户端说来,创建不同产品,只需要更改其抽象产品工厂的实现类即可,对开闭原则友好

使用典范

  • java.util.Calendar
/**
 * Gets a calendar using the default time zone and specified locale.
 * The <code>Calendar</code> returned is based on the current time
 * in the default time zone with the given locale.
 *
 * @param aLocale the locale for the week data
 * @return a Calendar.
 */
public static Calendar getInstance(Locale aLocale)
{
    return createCalendar(TimeZone.getDefault(), aLocale);
}
原文地址:https://www.cnblogs.com/DiDi516/p/12732613.html