Spring 与工厂模式
工厂模式优化
先简单回顾一下工厂模式,例如,针对下面 Phone 接口及其实现
1 2 3
| public interface Phone { void powerOn(); }
|
HWPhone 类
1 2 3 4 5 6
| public class HWPhone implements Phone{ @Override public void powerOn() { System.out.println("华为"); } }
|
现在,假设有一个 Shop 类,负责使用 phone 对象
1 2 3 4 5 6
| public class Shop { public static void main(String[] args) { Phone phone = new HWPhone(); phone.powerOn(); } }
|
现在华为销量不好,商店想要改卖小米,应该怎么办呢?
首先,需要创建一个小米手机类,并实现 Phone 接口
1 2 3 4 5 6
| public class XMPhone implements Phone { @Override public void powerOn() { System.out.println("小米"); } }
|
然后在商店主方法中修改生产的手机类型为小米
1 2 3 4 5 6 7
| public class Shop { public static void main(String[] args) { Phone phone = new XMPhone(); phone.powerOn(); } }
|
通过以上修改就实现了销售品牌从华为变更为小米,但是如果商店想改卖 Apple 怎么办呢?是不是又要重复以上动作。这样,每次修改销售品类都要频繁修改程序代码,使得程序难以维护。根据以往经验,我们可以将手机的创建过程封装到一个工厂类中,此后修改销售品类只需要更改工厂代码即可
工厂类如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class PhoneFactory { public static Phone getPhone(String type) { Phone phone = null; switch (type) { case "HW": phone = new HWPhone(); break; case "XM": phone = new XMPhone(); break; } return phone; } }
|
修改一下商店代码,使其根据类型从工厂中获取手机:
1 2 3 4 5 6 7
| public class Shop { public static void main(String[] args) { Phone phone = PhoneFactory.getPhone("HW"); phone.powerOn(); } }
|
经过上述修改后,后续商店只要修改手机类型即可从工厂中获取对应产品了,而不需要考虑产品是如何创造的。但是又出现了另外一个问题:如果后续新增 Oppo 品牌还是需要修改工厂类,该怎么办呢?
之所以出现上面的问题,是因为上面出现的产品都是通过 new
来创建的,这样就不可避免的出现硬编码问题。那除了使用 new
有没有其他方式呢?还真有,那就是反射
1
| Phone phone = (Phone) Class.forName("me.zyp.basic.HWPhone").newInstance();
|
为了使用反射创建对象,我们需要知道对应类的全类名,该怎么获取呢?
很简单,将全类名使用其他持久化方式进行配置(数据库、配置文件等)即可,这样后续即使增加再多的产品,只需要维护一下其全类名即可
下面是以配置文件为例,进行改造后的工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class PhoneFactory { public static Properties env;
static { try { env = new Properties(); InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("application.properties"); env.load(in); in.close(); } catch (Exception e) { e.printStackTrace(); } }
public static Phone getPhone(String type) throws Exception { Phone phone = null; try{ String className = env.getProperty(type); phone = (Phone) Class.forName(className).newInstance(); }catch (Exception e){ e.printStackTrace(); } return phone; } }
|
对应配置文件如下:
1 2
| HW=me.zyp.basic.HWPhone XM=me.zyp.basic.XMPhone
|
商店类如下:
1 2 3 4 5 6
| public class Shop { public static void main(String[] args) { Phone phone = PhoneFactory.getPhone("HW"); phone.powerOn(); } }
|
经过上面改造,产品创建已完成解耦。即使增加产品也不需要更改程序代码了
Spring 中的工厂
Spring 框架就类似于上面的手机工厂,它负责生产和管理应用程序中的各种对象(手机)。我们可以在配置文件中定义 Bean (手机品牌)的属性,例如依赖关系、作用域、生命周期等,然后 Spring 框架(手机工厂 PhoneFactory)会根据这些配置来创建和管理相应的对象