本文共 4858 字,大约阅读时间需要 16 分钟。
先来看一段程序代码实现:
public class FactoryGOF { public static void main(String[] args) { Car car = new Benz(); car.drive(); }}interface Car{ //定义一个车的接口,有一个drive()方法 public void drive();}class Benz implements Car{ @Override public void drive() { System.out.println("driving the benz"); } }class Audi implements Car{ @Override public void drive() { System.out.println("driving the audi"); }}
在面向对象编程中, 最通常的方法是使用new
关键字产生一个对象实例,new
关键字就是用来构造对象实例的。但是在一些情况下, new
关键字直接生成对象会带来一些问题。比如上面的代码实现, 一个接口和一个子类直接耦合,调用子类方法需要实现向上转型实现,如果要实现的子类功能增加,耦合程度就会进一步增加,重复代码也会增加,此时需要有一个过渡方式来解决这一问题。就像Java的可移植性一样,在不同的平台,都是用JVM。此时的工厂模式就相当于这样一个中间过渡。
组成
1)工厂类角色:这是该模式的核心,含有一定的商业逻辑和判断逻辑。在Java中它往往由一个具体的类实现。
2)抽象产品角色:它一般是具体产品继承的父类或者实现的接口,在Java中由接口或者抽象类来实现。
3)具体产品角色:工厂所创建的对象就是此角色的实例,在Java中由一个具体类实现。
具体实现:public class FactoryGOF { public static void main(String[] args) { Car car = Factory.driveCar("Benz"); car.drive(); //Car car = new Benz(); //car.drive(); }}//抽象产品角色interface Car{ //定义一个车的接口,有一个drive()方法 public void drive();}//具体产品角色class Benz implements Car{ @Override public void drive() { System.out.println("driving the benz"); } }//具体产品角色class Audi implements Car{ @Override public void drive() { System.out.println("driving the audi"); }}//工厂类角色class Factory{ public static Car driveCar(String str){ if ("Benz".equals(str)) { return new Benz(); }else if ("Audi".equals(str)) { return new Audi(); }else { return null; } }}
但是一旦类达到一定数量,这种模式的弊端就很明显了,每次都需要使用关键new实例化对象,为了避免使用new,最好的做法就是使用反射来完成处理,因为Class
类,可以使用newInstance
实例化对象,同时Class.forName()可以接受String类型的类名称。
代码如下:
package com.shmily.gof;interface IFuits{ //定义一个水果类的接口 public void eat();}//两种不同类型的接口interface IMessage{ //定义消息的接口 public void print();}class Apple implements IFuits{ @Override public void eat() { System.out.println("eat apple"); }}class MessageImpl implements IMessage{ @Override public void print() { System.out.println("www.baidu.com"); }}class Factory{ private Factory(){}//私有化 //使用泛型获取实例化对象 @SuppressWarnings("unchecked") public staticT getInstance(String className){ T obj = null; //取得实例化对象 try { obj = (T) Class.forName(className).newInstance(); } catch (Exception e) { e.printStackTrace(); } return obj; }}public class FactoryReflect { public static void main(String[] args) { IFuits fruit = Factory.getInstance("com.shmily.gof.Apple"); fruit.eat(); IMessage msg = Factory.getInstance("com.shmily.gof.MessageImpl"); msg.print(); }}
以上是简单工厂模式的实现代码示例,但是在实现功能的同时,如果此时需要增加多个子类,这时候工厂类就要做相应的修改操作。对于简单工厂模式来说,工厂类就是上帝,但是此时上帝会很累。从开闭原则(对扩展开放,对修改封闭)来说,工厂类很被动。这时为了完善,工厂方法模式就出场了。
工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。
代码示例:
public class FactoryGOF { public static void main(String[] args) { Ifactory ifactory = new BenzDrive(); ifactory.diveCar().drive();; }}//抽象产品角色interface Car{ //定义一个车的接口,有一个drive()方法 public void drive();}//具体产品角色class Benz implements Car{ @Override public void drive() { System.out.println("driving the benz"); } }//具体产品角色class Audi implements Car{ @Override public void drive() { System.out.println("driving the audi"); }}//工厂接口interface Ifactory{ public Car diveCar();}class BenzDrive implements Ifactory{ @Override public Car diveCar() { return new Benz(); } }class AudiDrive implements Ifactory{ @Override public Car diveCar() { return new Audi(); } }
从以上代码可以看出,工厂方法的加入,是的对象的数量成倍增加,当产品种类非常多时,会出现大量与之对应的工厂对象,这并不是我们所希望的。为了避免此类情况,可以使用简单工厂和工厂方法模式相结合的方式来减少工厂类。对产品树上类似的种类采用简单工厂方式来实现。
抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象而且使用抽象工厂模式还要满足一下条件:
来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):
可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品。
对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
降低耦合度。产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所依赖的类都是透明的。
转载地址:http://cdrji.baihongyu.com/