【工厂方法模式】
定义一个用于创建对象的接口(或抽象类),让子类决定去实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
【具体案例:小米手机工厂】
package com.Higgin.FactoryMethod; /** * 小米手机接口 * 其有三个实现类,分别对应小米1,小米2,小米3 */ interface MiPhone{ public void getPrice(); public void call(); } /** * 小米1 */ class Mi1 implements MiPhone{ public void getPrice() { System.out.println("小米1价格:999元!"); } public void call() { System.out.println("小米1打电话..."); } } /** * 小米2 */ class Mi2 implements MiPhone{ public void getPrice() { System.out.println("小米2价格:1999元!"); } public void call() { System.out.println("小米2打电话..."); } } /** * 小米3 */ class Mi3 implements MiPhone{ public void getPrice() { System.out.println("小米3价格:2999元!"); } public void call() { System.out.println("小米3打电话..."); } } /** * 抽象工厂类 * 定义一个工厂的基本功能 */ abstract class AbstractMiPhoneFactory{ /* * 泛型使得参数c必须是MiPbone的实现类,且必须是Class类型(这里的Class的C大写!) * 其中T表示,只要是实现了MiPhone接口的类都可以作为参数 */ public abstract <T extends MiPhone> T createMiPhone(Class<T> c); } /** * 具体工厂类 */ class MiPhoneFactory extends AbstractMiPhoneFactory{ public <T extends MiPhone> T createMiPhone(Class<T> c) { MiPhone miPhone=null; try { miPhone=(MiPhone) Class.forName(c.getName()).newInstance(); } catch (Exception e) { e.printStackTrace(); } return (T) miPhone; } } /** * 客户端类 */ public class TestMiPhoneFactory { public static void main(String[] args) { AbstractMiPhoneFactory miPhoneFactory=new MiPhoneFactory(); MiPhone mi1=miPhoneFactory.createMiPhone(Mi1.class); //泛型的传入参数:类名.class 这里的class小写 mi1.getPrice(); mi1.call(); MiPhone mi3=miPhoneFactory.createMiPhone(Mi3.class); mi3.getPrice(); mi3.call(); } }
【运行结果】
【优点】
* 良好的封装性,代码接口清晰。一个对象的创建是有条件约束的,如一个调用者需要一个具体的产品对象(new Mi3()),只要知道这个产品的类名即可(Mi3.class),不需要知道其具体的创建过程,降低模块之间的耦合。
* 扩展性较为优秀,在增加产品类的,只要适当修改其具体工厂类或扩展一个工厂类即可,如需要增加一个小米4手机,只要增加一个class Mi4 implements MiPhone{...}类即可。
* 屏蔽产品类,调用者无需关心产品类如何变化,只需要关心产品的接口,只要接口不变,系统中的上层模块就不需要发生变化。
* 典型的解耦框架,高层模块只需知道产品的接口(或抽象类),其它实现类都不需要关心,符合迪米特法则;又因为只依赖于产品类的抽象,符合依赖倒置原则;还因为使用产品子类替换产品父类,符合里氏替换原则。