一、应用场景
工厂模式应用非常广泛,意在抽象出一层专职管理对象产生以及对象间的关系,让我们能够专注于业务开发:
1. 不用去写许许多多的new方法,替换实现类还得挨个修改。
2. 类中不涉及实现类,对象间只存在接口级别的耦合,客户端调用注入实现类即可。
由于工厂模式变种非常多,这里只讲一下常用的简单工厂和抽象工厂。
二、源码分析
1. 简单工厂
public interface IProduct { void doSomething(); }
public class ConcreteProductA implements IProduct{ @Override public void doSomething() { System.out.println("this is productA"); } }
public class ProductFactory { private ProductFactory() { } public static <T extends IProduct> T getInstance(Class<T> cls) { T product = null; try { product = cls.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return product; } }
简单工厂单以工厂类来区别不同类别的实例,也就是一个工厂中的一个方法只能生产一类实例:这里就只能创建IProduct接口的实现类,如果要创建IKeyBoard接口实现就得新创建一个工厂,或者是在该工厂中添加专门创建该类别实例的方法。当然,添加方法逻辑不够清晰。此外,客户端需要提供实现类的class对象或者全路径。
2. 抽象工厂
这里以A、B公司各有A、B两类产品举例,产品实现类就有2*2=4种,这里就写出一种产品其余大家自行脑补。
产品:
public interface IProduct { void doSomething(); void tagName(); }
public abstract class AbstractProductA implements IProduct { @Override public void doSomething() { System.out.println("this is productA"); } }
public abstract class AbstractProductB implements IProduct { @Override public void doSomething() { System.out.println("this is productB"); } }
工厂:public class PAOfCompanyA extends AbstractProductA{ @Override public void tagName() { System.out.println("this is companyA"); } }
public interface IFactory { IProduct createProductA(); IProduct createProductB(); }
public class CompanyAFactory implements IFactory { @Override public IProduct createProductA() { return new PAOfCompanyA(); } @Override public IProduct createProductB() { return new PBOfCompanyA(); } }
public class CompanyBFactory implements IFactory { @Override public IProduct createProductA() { return new PAOfCompanyB(); } @Override public IProduct createProductB() { return new PBOfCompanyB(); } }
抽象工厂以工厂和方法各为一个维度来区分不同的类别,通过指定工厂和创建方法来产生对应实现类的实例,无需提供实现类信息。
可以看出,抽象工厂与简单工厂的区别在于:
1.抽象工厂一个方法创建一个实现类对象,而非一类对象。
2.抽象工厂处理维度更高的对象关系,扩展要么增加工厂类别,要么增加创建方法。
3.抽象工厂可以用简单工厂实现,比如上面的例子用简单工厂创建IProduct类别即可。