概念以及背景
简单工厂模式(Simple Factory Pattern):定义一个工厂类,它能够根据参数的不一样返回不一样类的实例,被建立的实例一般都具备共同的父类。
由于在简单工厂模式中用于建立实例的方法是静态(static)方法,所以简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类建立型模式。
工厂模式是最经常使用的一类建立型设计模式,一般咱们所说的工厂模式是指工厂方法模式而简单工厂模式并不属于GoF 23个经典设计模式,但一般将它做为学习其余工厂模式的基础。
简单地说就是须要什么对象,传入给定格式的参数,就能够获取所需对象,而调用方无需知道其中建立对象的细节,在建立对象那一方也有本身的实现细节,代码结构清晰、解耦。
源码地址:https://github.com/fiuty/stud...
里面用三种不一样的方式应用了简单工厂模式,有用到Java8 Lambda 方式重构简单工厂模式,也有一个我实际开发中应用到的方式。git
UML类图以下,有一个抽象金融产品类AbstractFinanceProduct,有三个子类,贷款(LoanFinanceProduct)、股票(StockFinanceProduct)和债券(BondFinanceProduct)都是抽象金融产品类(AbstractFinanceProduct)的子类。
工厂类是SimpleFactory,负责建对象,根据传入的参数,返回须要的对象。github
/** * 抽象金融产品类 */ public abstract class AbstractFinanceProduct { /** * 全部产品类的公共业务方法 */ public void methodSame() { String className = this.getClass().getName(); //公共方法的实现 System.out.println("抽象类公共方法,该类是:" + className); } /** * 声明抽象业务方法 */ public abstract void disPlayProduct(); }
产品名称枚举,用于工厂类建立对象方法的参数,用枚举的话比用常量好,常量的话方法参数调用方可能会给超出产品范围的常量,而用枚举的话产品枚举类范围都是明确的,也不用担忧写错,如把股票Stock写成Stick等错误写法。设计模式
/** * 产品名称枚举 */ public enum ProductEnum { /** * 产品类别 */ Bond("Bond"), Loan("Loan"), Stock("Stock"); String name; ProductEnum(String name) { this.name = name; } }
/** * 简单工厂类 */ class SimpleFactory { static AbstractFinanceProduct creatProduct(ProductEnum productEnum) { switch (productEnum) { case Bond : return new BondFinanceProduct(); case Loan : return new LoanFinanceProduct(); case Stock : return new StockFinanceProduct(); default: throw new RuntimeException("No such product" + productEnum.name()); } } }
工厂类的调用方,只需传入某个产品的类别,便可返回该产品对象。ide
public class SimpleFactoryPattern { public static void main(String[] args) { AbstractFinanceProduct stockProduct = SimpleFactory.creatProduct(ProductEnum.Stock); AbstractFinanceProduct bondProduct = SimpleFactory.creatProduct(ProductEnum.Bond); stockProduct.methodSame(); stockProduct.disPlayProduct(); bondProduct.disPlayProduct(); } }
跟步骤一的UML类图同样,以下:函数
用lambda的方式实现简单工厂模式,lambda给咱们提供了一些经常使用的函数式接口能够用,简单工厂模式须要建对象和返回对象,故可用Supplier<T>函数式接口,至于建立所需对象的入参,接着下面看。学习
@FunctionalInterface public interface Supplier<T> { /** * Gets a result. * * @return a result */ T get(); }
这里把所需建立对象的入参作成一个Map的key键,而Map的value是一个函数式接口,在设值的时候用lambda实现该value的函数式接口,这里巧妙地用了lambda的方法引用ClassName::new,实现函数式接口Supplier<T>的get()接口方法。this
/** * 用lambda的方式实现简单工厂模式 */ class SimpleFactoryLambda { /** * Map的value是一个函数式接口,里面的接口待实现 */ private final static Map<ProductEnum, Supplier<AbstractFinanceProduct>> PRODEUC_MAP = new HashMap<>(); static { //这里put进去的value就是函数式接口的一个实现,lambda表达式的方法引用 PRODEUC_MAP.put(ProductEnum.Bond, BondFinanceProduct::new); PRODEUC_MAP.put(ProductEnum.Stock, StockFinanceProduct::new); PRODEUC_MAP.put(ProductEnum.Loan, LoanFinanceProduct::new); } static AbstractFinanceProduct creatProduct(ProductEnum productEnum) { Supplier<AbstractFinanceProduct> productSupplier = PRODEUC_MAP.get(productEnum); if (productSupplier != null) { //这里每次调用都生成新的对象,map的value获得的是一个函数式接口的lambda实现,每次都new新对象出来。 return productSupplier.get(); } throw new IllegalArgumentException("No such product" + productEnum.name()); } }
若是不想所建立的对象都是子类继承父类,高度耦合的(实际也不多这样),但在实际开发中又须要常常用到建立对象,能够试试下面这种方式。
这个是我在开发中所运用到的,项目须要大量调用淘宝的接口,淘宝请求参数的对象又有不一样的属性,即调用淘宝线上不一样的接口,都须要有不一样的入参对象DTO,因此这些对象都不是继承的关系,这里用简单工厂模式来建请求淘宝接口的对象。
UML类图:spa
/** * 请求报文,T 携带简单工厂所建立的不一样对象 * @author Fiuty */ public class RequestDTO <T>{ private T payload;
public class Animal { private String name; public Animal(String name) { this.name = name; }
public class People { private String name; public People(String name) { this.name = name; } }
工厂接口类,建对象的方法,统一返回RequestDTO<T>,在泛型中返回所需的对象,而这些对象都不是子类继承父类,高度耦合。.net
public interface SimpleFactoryAdvanceService { RequestDTO<People> createPeople(String name); RequestDTO<Animal> createAnimal(String name); }
工厂实现类设计
public class SimpleFactoryAdvanceServiceImpl implements SimpleFactoryAdvanceService { @Override public RequestDTO<People> createPeople(String name) { return new RequestDTO<>(new People(name)); } @Override public RequestDTO<Animal> createAnimal(String name) { return new RequestDTO<>(new Animal(name)); } }
最后调用工厂实现类来生产咱们所需的对象:
public class SimpleFactoryPatternAdvance { public static void main(String[] agrs) { SimpleFactoryAdvanceServiceImpl factory = new SimpleFactoryAdvanceServiceImpl(); RequestDTO<Animal> animalRequest = factory.createAnimal("特朗普"); RequestDTO<People> peopleRequest = factory.createPeople("上帝"); System.out.println("动物的名字是:"+animalRequest.getPayload().getName()); System.out.println("人类的名字是:"+peopleRequest.getPayload().getName()); } }
参考资料:
http://www.javashuo.com/article/p-mswxlyip-nq.html《Java8 实战》