设计模式之三——工厂方法模式(Factory Method)&抽象工厂模式(AbstractFacotry)

模式名称

工厂方法模式(Factory Method)、抽象工厂模式(AbstractFacotry)

问题

  • 客户类不关心使用哪个具体类,只关心该接口所提供的功能。
  • 创建过程比较复杂,例如需要初始化其他关联资源,读取配置文件等。
  • 接口有很多具体实现或者抽象类有很多具体子类,避免客户端写一大堆if-else逻辑来决定运行时使用哪个具体实现或者具体子类。
  • 不希望给客户程序暴露过多此类的内部结果或创建过程,降低耦合度。
  • 优化性能,比如缓存大对象或者初始化比较耗时的对象。

GOF为工厂方法模式给出的定义:

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
为创建对象定义一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟至子类。

用法分类

实例一、简单工厂:
    //--------------参数化简单工厂创建示例--------------------------
    public class ProductCreator {
        Product createProduct(String type){
            if(type.equals("tv")){
                return new TVProduct();
            }else if(type.equals("watch")){
                return new WatchProduct(); 
            }
        }
    } 

    public interface Product{}
    public class TVProduct implements Product{}
    public class WatchProduct implements Product{}
    //---------------工厂的客户类示例----------------------------
    public class Client{
        private ProductCreator creator;
        public Client(ProductCreator creator){
            this.creator=creator;
        }
        public void doSomething(String type){
            Product product=creator.createPorduct(type); 
            //to do something...
        }
    }
    //--------------测试工厂方法---------------------------------
    public class TestFacotry{
        public static void main(String[] args){
            Client client=new Client(new ProductCreator());  
            client.doSomething("car");
        }
    }

简单工厂并不是一个模式,只是一种习惯用法。它看起来像是把问题从一个类转移到了另一类,也就是把创建对象的行为从一个类转移到另一个类当中。但它也有其好处,例如,如果有其他客户也需要创建对象,那么就可以直接调用简单工厂,避免代码重复。

实例二、静态工厂方法

静态工厂方法同样不是一种模式,但它可以避免简单工厂类的泛滥,不需要额外的工厂类了。例如,在Java5版本里,为创建基本类型Integer、Long、Boolean对象都提供了静态工厂方法,以Integer为例:

    public static Integer valueof(int i){  //注意static关键字
        if(i>=-128 && i<=IntegerCache.high)
            return IntegerCache.cache[i+128];
        else
            return new Integer(i);
    }

静态工厂方法的优缺点:
优点:

  • 可以为静态工厂选择合适的命名,提高程序的可读性。
  • 静态工厂和简单工厂一样,可以封装复杂的初始化过程。
  • 避免了简单工厂类泛滥

缺点:

  • 一般为了强迫使用工厂方法,我们会让类只含有私有构造方法,这样,会导致此类不能被子类化。
  • 如果添加了一个新的该类的子类,此静态工厂方法可能需要重写,以加入该子类的实例化过程,导致扩展性不强。
  • 静态方法没有面向对象的特征,比如继承、动态多态等,不能被重写。

实例三、真正的模式之一:工厂方法模式

所有的工厂模式都用来封装对象的创建。工厂方法模式(Facotry Method Pattern)通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。

    /**
 * 工厂方法模式.
 * 工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。
 * 工厂方法将类的实例化推迟到子类,
 *
 */
public abstract class PizzaStore {
    public Pizza orderPizza(){
        Pizza pizza;

        pizza=createPizza(); //不变的部分调用变化的部分

        pizza.prepare();
        pizza.cut();
        pizza.box();
        return pizza;
    }

    protected abstract Pizza createPizza();//变化的部分,工厂方法,由子类实现
}
//-------------------------------------------------------------------------
/**
 * 实现了工厂方法。
 */
public class NewYorkPizzaStore extends PizzaStore{
        @Override
        protected Pizza createPizza() { //工厂方法的实现,创建类的对象。
            return new NewYorkPizza();
        }
}

实例四、真正的模式之二:抽象工厂模式

定义

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类

/**
 * 抽象工厂,使用组合创建了一些列产品的集合。
 */
public interface PizzaIngredientFacotry { //接口中,每一种原料都有一个方法创建该原料。
    public Sauce createSauce();
    public Cheese createChesse();
}
//----------------------------------------------------------
/**
 * 抽象工厂PizzaIngredientFactory的一种实现
 * @see PizzaIngredientFacotry
 */
public class NYPizzaIngredientFacotry {
    public Sauce createSauce(){ //返回具体的酱汁
        return new NYSauce();
    }
    public Cheese createChesse(){
        return new NYChesse();
    }
}

实际上,抽象工厂的每个方法实际上看起来都像是工厂方法。每个方法都被声明成抽象的,而子类的方法覆盖这些方法来创建某些对象。没错,工厂方法潜伏在抽象工厂里面。抽象工厂的方法经常以工厂方法的方式实现。
抽象工厂的任务是创建一组产品的接口。这个接口内的每个方法都负责创建一个具体产品。所以,在抽象工厂中利用工厂方法实现生产方法是相当自然的做法。

与工厂方法的区别
  • 两者都是负责创建对象,但工厂方法使用的是继承,而抽象工厂使用的是对象的组合。
  • 工厂方法适合创建一类对象,即这类对象有共同的抽象。而抽象工厂适合把一组相关的产品集合起来,因为它用的是组合。
  • 对工厂方法来说,抽象创建者中所实现的代码通常会用到子类所创建的具体类型。
  • 当我们需要创建产品家族和想让制造的相关产品集合起来时,就可以使用抽象工厂。
  • 工厂方法的使用方式很简单,只要继承父类,在子类中实现其抽象方法即可。

效果

工厂模式让我们把对象实例化的过程进行了封装,屏蔽了复杂的构建过程。同时,工厂模式让客户类和具体类型解耦,增强了程序的可扩展性和可维护性。只有在需要考虑扩展性的时候才使用工厂方法模式,否则会增加代码的复杂程度。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值