— 设计模式 — 1 min read
Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)
Product:抽象产品类
ConcreteProduct:具体产品类
Creator:抽象工厂类
ConcreteCreator:具体工厂类
工厂方法模式可以说是替代了我们传统的再代码中 new 一个对象的方式,所以再任何需要创建对象的地方都可以使用工厂方法模式,不过要考虑这样做是否值得,会增加代码的复杂度。
在遇到需要灵活且方便拓展的项目中,可以考虑使用工厂方法,当有新的功能出现,那么可以考虑增加一个 product 类就可以了。例如系统中一个拦截模块,可能最开始要实现的是根据 ip 拦截,在后期又要根据方法进行拦截,又或者根据接口进行拦截,这时使用工厂方法今可以做到灵活拓展。
1public abstract class Product{2 //公共方法3 public void common(){4 System.out.println("this is common method!")5 }6 //抽象方法 交给子类实现7 public abstract void make();8}
1public class ConcreteProduct extends Product{2 public void make(){3 System.out.println("this is ConcreteProduct")4 }5}
1public abstract class Factory{2 public abstract <T extends Product> create(Class<T> class);3}
1public class ConcreteFactory extends Factory{2 public <T extends Product> create(Class<T> class){3 Product product=null;4 try {5 product =(Product)Class.forName(c.getName()).newInstance();6 } catch (Exception e) {7 //异常处理8 }9 return (T)product; 10 }11}
1public class Client {2 public static void main(String[] args) {3 Creator creator = new ConcreteCreator();4 Product product = creator.createProduct(ConcreteProduct1.class);5 product.make();6 product.common();7 }8}
工厂方法有对拓展极为开放,也就是说他可以轻松实现多中拓展,而且可以与其他模式结合使用。
若在项目中仅需要一个工厂类,并且能够进行对象的创建,那么其实只需要一个简单工厂模式就可以了,将上边的例子改造一下。
1public class Factory{2 public static <T extends Product> create(Class<T> class){3 Product product=null;4 try {5 product =(Product)Class.forName(c.getName()).newInstance();6 } catch (Exception e) {7 //异常处理8 }9 return (T)product; 10 }11}
1public class Client {2 public static void main(String[] args) {3 //删除4 //Creator creator = new ConcreteCreator();5 //对 static 直接调用6 Product product = Creator.createProduct(ConcreteProduct1.class);7 product.make();8 product.common();9 }10}
运行结果没有发生变化,但是我们的类图变简单了,而且调用者也比较简单,该模式是工厂方法模式的弱化,因为简单,所以称为简单工厂模式(Simple Factory Pattern),也叫做静态工厂模式。在实际项目中,采用该方法的案例还是比较多的,其缺点是工厂类的扩展比较困难,不符合开闭原则,但它仍然是一个非常实用的设计模式。
当我们在做一个比较复杂的项目时,经常会遇到初始化一个对象很耗费精力的情况,所有的产品类都放到一个工厂方法中进行初始化会使代码结构不清晰。例如,一个产品类有5个具体实现,每个实现类的初始化(不仅仅是new,初始化包括new一个对象,并对对象设置一定的初始值)方法都不相同,此时就可以考虑使用多个具体工厂类实现,也就是说每个工厂做自己特定的业务。
1public class NewConcreteFactory extends Factory{2 public Product create(){3 return new NewProduct();4 }5}
其实create
方法中已经不再需要参数了,因为针对每一种产品都有自己的独立的工厂。
每一个产品都对赢了一个创建类,使得他们之间每个工厂的任务简单,代码结构清晰,单对于拓展性和维护性这是带来了一定的负面影响,若一味地在增加产品的时候就增加工厂,可能会导致类的成倍增长。
在复杂的应用中一般采用多工厂的方法,然后再增加一个协调类,避免调用者与各个子工厂交流,协调类的作用是封装子工厂类,对高层模块提供统一的访问接口。
工厂方法模式在项目中使用得非常频繁,以至于很多代码中都包含工厂方法模式。该模式几乎尽人皆知,但不是每个人都能用得好。熟能生巧,熟练掌握该模式,多思考工厂方法如何应用,而且工厂方法模式还可以与其他模式混合使用(例如模板方法模式、单例模式、原型模式等),变化出无穷的优秀设计,这也正是软件设计和开发的乐趣所在。
设计模式 设计模式之禅