工厂模式结合反射——遵循开闭原则

tech2022-09-28  68

目录

介绍传统工厂模式工厂模式结合反射机制总结

介绍

工厂模式是一种创建型模式,在工厂模式中,创建对象时不会对客户端暴露创建细节(将创建的代码封装到一个工厂类中),而是通过一个接口指向由工厂类创建并返回的对象。 对于设计模式和各个原则来说,无非就是要实现代码的高内聚和低耦合,还有尽量遵循开闭原则。开闭原则简单来说就是:软件中的对象(类,函数,模块)对扩展开放,对修改关闭。

于是,围绕开闭原则展开以下讨论。 传统工厂模式是如何违背了开闭原则的,工厂模式加反射机制是如何遵循开闭原则的。

以披萨为话题,我们要创建各种口味的披萨,例如奶酪披萨,水果披萨。 这个显然可以就通过工厂模式来实现,下面用传统工厂模式。 首先我们要声明一个IPizza接口:

public interface IPizza { void eat(); }

IPizza的实现类:

//奶酪披萨 public class CheesePizza implements IPizza { private String pizzaType="奶酪披萨"; @Override public void eat() { System.out.println(pizzaType+"真香!"); } } //水果披萨 public class FruitPizza implements IPizza { private String pizzaType="水果披萨"; @Override public void eat() { System.out.println(pizzaType+"真好吃!"); } }

下面通过工厂创建各种口味的披萨。

传统工厂模式

写一个工厂类,把创建各种口味披萨的任务交给它。

//披萨工厂类 public class PizzaFactory { private PizzaFactory(){} public static IPizza createPizza(String pizzaType){ IPizza pizza=null; if ("奶酪披萨".equals(pizzaType)) { pizza=new CheesePizza(); } else if ("水果披萨".equals(pizzaType)) { pizza=new FruitPizza(); } return pizza; } }

测试:

public class PizzaTest { public static void main(String[] args) { IPizza pizza=PizzaFactory.createPizza("水果披萨"); pizza.eat(); pizza=PizzaFactory.createPizza("奶酪披萨"); pizza.eat(); } }

控制台结果: OK!就是那么简单,但是问题来了,我现在突然想到还有一种口味的披萨:蛋黄披萨。我想把它添加到系统中,要怎么做呢? 第一步,实现IPizza接口

//蛋黄披萨 public class EggyolkPizza implements IPizza { private String pizzaType="蛋黄披萨"; @Override public void eat() { System.out.println(pizzaType+"贼香!"); } }

第二步,修改工厂类(emmm,思考一下,这是不是违背了开闭原则)

修改过程就是添加一个else if分支。

public class PizzaFactory { private PizzaFactory(){} public static IPizza createPizza(String pizzaType){ IPizza pizza=null; if ("奶酪披萨".equals(pizzaType)) { pizza=new CheesePizza(); } else if ("水果披萨".equals(pizzaType)) { pizza=new FruitPizza(); } else if ("蛋黄披萨".equals(pizzaType)) { pizza=new EggyolkPizza(); } return pizza; } }

代码搞定,测试一下: 添加披萨口味是成功了,但是我们也违背了开闭原则,如果有很多个口味的披萨引进来,那我们岂不是要改工厂类改到吐?

工厂模式结合反射机制

同样也是写一个工厂类,把创建各种口味披萨的任务交给它。

public class PizzaFactory { private PizzaFactory(){} public static IPizza createPizza(String pizzaType){ IPizza pizza=null; try { Class clazz=Class.forName(pizzaType); pizza=(IPizza)clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } return pizza; } }

测试:

public class PizzaTest { public static void main(String[] args) { IPizza pizza=PizzaFactory.createPizza("cn.thg.community.pizza.impl.CheesePizza"); pizza.eat(); pizza=PizzaFactory.createPizza("cn.thg.community.pizza.impl.FruitPizza"); pizza.eat(); } }

控制台结果: OK! 添加一个口味的披萨,还是蛋黄披萨吧。 很简单,只需要扩展多一个类就行了,不需要取修改工厂类。 只需一步,扩展一个蛋黄披萨的类

public class EggyolkPizza implements IPizza { private String pizzaType="蛋黄披萨"; @Override public void eat() { System.out.println(pizzaType+"贼香!"); } }

测试: 搞定。这样无论要加多少种口味,只需要拓展就行了,这不就很好的遵循了开闭原则吗,无论添加多少个披萨类,都不用对工厂类进行任何改变,直接在客户端(main方法)调用即可,相比较与传统工厂模式简直不要方便太多。

总结

很显然,传统工厂模式违背了开闭原则(扩展新口味要修改工厂类),而工厂模式结合反射的方式则没有违背。只不过是后者传参的方式变成了传全限定类名。

最新回复(0)