工厂模式
在我们平常编程过程中,声明一个对象最常用的方法就是new一个对象实例,但是在一些情况下只用New来构造一个实例对象是不太理想的,这样会将创建对象的代码和逻辑功能的代码混在一起,不太美观。我们希望将对象的创建封装到一个接口中,当我们需要实例化一个对象时,只需要调用这个接口即可,更加简洁方便,而且使得代码更加有逻辑,更具有可读性。这种封装的方法也就是这里要介绍的工工厂模式。
工厂模式一般有三种:简单工厂模式、工厂方法模式、抽象工厂模式。
简单工厂模式
模拟一个手机的生产过程。
简单工厂模式中需要包含三个内容:抽象产品、具体产品、工厂, 定义如下:
抽象产品:
//抽象产品类,以手机为例
public interface Phone {
public void call();
}
具体产品:
//具体手机类,以OPPO手机为例
public class OPphone implements Phone{
public void call()
{
System.out.println("This is OPphone");
}
}
//具体手机类,以华为手机为例
public class HWphone implements Phone {
public void call()
{
System.out.println("This is HWphone");
}
}
工厂:
//手机工厂类
public class PhoneFactory {
//返回类型为抽象的产品类的对象
public static Phone ProducePhone(String name) throws Exception{
//判断需要生产哪种手机
if(name.equals("HWphone")){
return new HWphone();
}
else if(name.equals("OPphone")){
return new OPphone();
}else{
throw new Exception();
}
}
}
在上述代码中我们可以看到,我们将所有new手机对象的方法都封装在了一个ProducePhone方法中,在后续的使用过程中,客户只需要传入相应的手机名称即可返回一个实例对象。
客户:
//客户类
public class Client {
public static void main(String[] args) throws Exception {
//客户告诉工厂需要哪种手机
Phone phone=PhoneFactory.ProducePhone("HWphone");
//拨打电话
phone.call();
}
}
这样通过使创建对象的代码和客户的代码分割开,便可以使客户不直接地创建对象,而是“使用”这个对象,更加简洁。但是也存在一些问题,当手机的种类增加时,便要修改大量的代码,也就是不同的工厂生产不同的手机,即有不同的ProducePhone的方法。于是就出现了工厂方法模式:
工厂方法模式
为了让我们的工厂更加灵活,每个工厂有每个工厂特定的方法,这样便可以使得在简单工厂里的工厂方法分给了子类的工厂来实现。
工厂方法模式的组成有:抽象工厂、具体工厂、抽象产品和具体产品。
抽象产品类:
//抽象产品类,以手机为例
abstract class Phone {
abstract void call();
}
具体产品:
//具体手机类,以华为手机为例
public class HWphone extends Phone {
public void call()
{
System.out.println("This is HWphone");
}
}
//具体手机类,以OPPO手机为例
public class OPphone extends Phone{
public void call()
{
System.out.println("This is OPphone");
}
}
抽象工厂类:
用于生产手机。
//抽象手机工厂类
public interface PhoneFactory {
public Phone ProducePhone();
}
具体工厂:
public class HWFactory implements PhoneFactory {
public Phone ProducePhone()
{
return new HWphone();
}
}
public class OPFactory implements PhoneFactory {
public Phone ProducePhone()
{
return new OPphone();
}
}
客户:
//客户类
public class Client {
private static Phone HWphone,OPphone;
private static PhoneFactory hwfactory,opfactory;
public static void main(String[] args) throws Exception {
//客户告诉工厂需要华为手机
hwfactory=new HWFactory();
HWphone=hwfactory.ProducePhone();
HWphone.call();
//客户告诉工厂需要OPPO手机
opfactory=new OPFactory();
OPphone=opfactory.ProducePhone();
OPphone.call();
}
}
优缺点:
工厂方法模式通过继承自抽象工厂的多个子工厂来代替简单工厂中的多个方法,这样使得结构变得更加灵活,当我们需要添加一个产品时,只需要根据抽象的产品和工厂继承一个新的子类,便可以被用户所使用,而不需要去修改结构上的代码。但是如果产品的数量不断增加时,会出现大量的工厂对象,这样也会导致结构上的开销是我们不希望的,所以在实际应用时需要考虑使用简单工厂和工厂方法两种模式相结合的方式。
抽象工厂
对于手机而言,存在位于不同产品等级结构,功能相关联的产品组成的家族,称为产品族。比如各个品牌的商务系列、游戏手机系列等等。
抽象工厂模式和工厂方法模式的区别在于需要创建的对象的复杂程度上,抽象工厂模式是工厂模式中最为抽象最具有一般性的一种模式。抽象工厂给用户提供一个接口,能够让用户创建多个产品族中的对象。
抽象工厂模式的组成与工厂方法模式类似:抽象工厂类、具体工厂类、抽象产品类、具体产品类。
抽象工厂类是具体工厂必须实现的一个接口或者一个继承的父类:
//抽象手机工厂类,商务手机
public abstract class AbstractFactoryA {
abstract PhoneA ProduceHWBusiness();
abstract PhoneA produceOPBusiness();
}
//抽象工厂类,游戏手机
public abstract class AbstractFactoryB {
abstract PhoneB ProduceHWGame();
abstract PhoneB produceOPGame();
}
抽象产品类:是具体产品的接口或者父类
//抽象产品类,商务手机
abstract interface PhoneA {
public void call();
}
//抽象产品类,游戏手机
public interface PhoneB {
public void call();
}
具体工厂类:含有具体逻辑实现的代码,由用户进行调用来创建相应的工厂对象:
/具体工厂,商务手机
public class AFactory extends AbstractFactoryA {
@Override
PhoneA ProduceHWBusiness() {
// TODO Auto-generated method stub
return new HWBusiness();
}
@Override
PhoneA produceOPBusiness() {
// TODO Auto-generated method stub
return new OPBusiness();
}
}
//具体工厂,游戏手机
public class BFactory extends AbstractFactoryB {
@Override
PhoneB ProduceHWGame() {
// TODO Auto-generated method stub
return new HWGame();
}
@Override
PhoneB produceOPGame() {
// TODO Auto-generated method stub
return new OPGame();
}
}
具体产品类:具体工厂类所创建的对象为具体产品类的实例
//具体手机类,
//华为商务手机
public class HWBusiness implements PhoneA {
public void call()
{
System.out.println("This is HWphone Business");
}
}
//华为游戏手机
public class HWGame implements PhoneB {
public void call()
{
System.out.println("This is HWPhone Game");
}
}
//OPPO商务手机
public class OPBusiness implements PhoneA{
public void call()
{
System.out.println("This is OPphone Business");
}
}
//OPPO游戏手机
public class OPGame implements PhoneB {
public void call()
{
System.out.println("This is OPPhone Game");
}
}
客户测试类:模拟手机生产过程:
以商务手机为例,先实例化一个商务手机工厂,之后调用工厂内的生成方法来制作出相应品牌的商务手机。
public class Client {
public static void main(String[] args)
{
//购买商务手机
AbstractFactoryA afactory=new AFactory();
PhoneA HWBusiness=afactory.ProduceHWBusiness();
PhoneA OPBusiness=afactory.produceOPBusiness();
HWBusiness.call();
OPBusiness.call();
//购买游戏手机
AbstractFactoryB bfactory=new BFactory();
PhoneB HWGame=bfactory.ProduceHWGame();
PhoneB OPGame=bfactory.produceOPGame();
HWGame.call();
OPGame.call();
}
}
优缺点:
抽象工厂模式中所有的具体实现类都依赖于接口,代码更加灵活。工厂内的对应方法可以随着需求而改变。
和工厂方法模式的区别
工厂方法模式中:
一个抽象产品类可以派生出多个具体产品类;一个抽象工厂类可以派生出多个具体工厂类。但是每个具体工厂类只能创建一个具体的产品类的实例。
抽象工厂模式中:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类;一个抽象工厂类可以派生出多个具体工厂类,每个具体工厂类可以创建多个具体产品类的实例。
二者主要区别在于:
工厂方法模式中只有一个抽象产品类,而抽象工厂模式有多个(因为有多个产品族)。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例(一对一),而抽象工厂模式可以创建多个具体产品类的对象(一对多)。
总结
各种工厂模式都各有优缺点,在具体使用中要根据具体情况具体分析采用哪种模式,亦可以结合多种模式来解决一个问题。