工厂设计模式

引入工厂设计模式的缘由

先来看一段程序代码实现:

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。此时的工厂模式就相当于这样一个中间过渡。

分类(以Java与模式定义为准)

简单工厂方法(Simple Factory)

组成

  • 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 static <T> T 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();
    }
}

以上是简单工厂模式的实现代码示例,但是在实现功能的同时,如果此时需要增加多个子类,这时候工厂类就要做相应的修改操作。对于简单工厂模式来说,工厂类就是上帝,但是此时上帝会很累。从开闭原则(对扩展开放,对修改封闭)来说,工厂类很被动。这时为了完善,工厂方法模式就出场了。

工厂方法模式(Factory Method)*

工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。

  • 1) 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在 java 中它由抽象类或者接口来实现。
  • 2) 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
  • 3) 抽象产品角色:它是具体产品继承的父类或者是实现的接口。在 java 中一般由抽象类或者接口来实现。
  • 4) 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在 java 中由具体的类来实现。

代码示例:

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();
    } 
}

从以上代码可以看出,工厂方法的加入,是的对象的数量成倍增加,当产品种类非常多时,会出现大量与之对应的工厂对象,这并不是我们所希望的。为了避免此类情况,可以使用简单工厂和工厂方法模式相结合的方式来减少工厂类。对产品树上类似的种类采用简单工厂方式来实现。

抽象工厂模式(Abstract Factory)

抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象而且使用抽象工厂模式还要满足一下条件:

  • 系统中有多个产品族,而系统一次只可能消费其中一族产品。
  • 同属于同一个产品族的产品以其使用。

来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):

  • 1) 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在 java 中它由抽象类或者接口来实现。
  • 2) 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在 java 中它由具体的类来实现。
  • 3) 抽象产品角色:它是具体产品继承的父类或者是实现的接口。在 java 中一般有抽象类或者接口来实现。
  • 4) 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在 java 中由具体的类来实现。

工厂模式的特点

  • 可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品。

  • 对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。

  • 降低耦合度。产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所依赖的类都是透明的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值