工厂模式(创建型)

  创建一个对象常常需要复杂的过程,不适合包含在一个复合对象中。创建对象可能导致大量的重复代码,可能会需要复合对象访问不到的信息,也可能提供不了足够级别的抽象,还可能并不是复合对象概念的一部分。工厂方法模式通过定义一个单独的创建对象的方法来解决这些问题。由子类实现这个方法来创建具体类型的对象。
  上面这一段是从维基百科上抄下来的,看完后是不是并没有看出什么名堂。
  首先来看一个问题:如何能轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程呢?这个问题的答案自然便是:建立一个工厂来创建对象。工厂模式主要就是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
  工厂模式主要分为三类:
  1)简单工厂模式(Simple Factory)
  2)工厂方法模式(Factory Method)
  3)抽象工厂模式(Abstract Factory)
  简单工厂模式可以看作是工厂方法模式的一个特例,这一句先可以不用,往下看完后就自然理解了。
  下面我们来看一个例子,先让大家对于这三个模式有一个具象的认识:
  1)还没有工厂时代:还没有工业革命,一个客户要一款宝马车,一般的做法是客户去创建一款宝马车。
  2)简单工厂模式:工业革命出现了,有工厂来帮客户创建宝马车,想要车子,这个工厂就可以创建车子这个产品了,用户不用自己去创建。
  3)工厂方法模式:不同客户的需求不一样,那么为了满足不同客户的需求,车系列越来越多,出现了i系列的320i,523i等,x系列的X5,X7等等,现在就出现了一个问题,一个工厂无法创建所有系列的车。于是单独分出来多个具体的工厂,每个具体的工厂创建一种系列。即具体工厂类只能创建一个具体产品。但宝马工厂还是个抽象。需要指定某个具体的工厂才能生产出车来。
  4)抽象工厂模式:市场规模扩大,客户变多,要求也多样化了,假定我们之前的宝马车都是三厢车,现在客户需求两厢车,那么为了适应市场需求,工厂在原来的基础上增加生产对应型号的两厢车。由于型号是相同,因此有许多类似的生产过程,所以就放在同一个工厂生产。于是这个工厂开始生产相同型号的两厢车和三厢车的空调。这里就引申出一个产品族的概念:位于不同产品等级结构中功能相关联的产品组成的家族。
  最后客户只要对宝马的销售员说:我要X7空调车,销售员就直接给他X7空调车了。这就是工厂模式。
  下面我们再来看一看抽象的语言描述:
  工厂方法模式:一个抽象产品类,可以派生出多个具体产品类。
         一个抽象工厂类,可以派生出多个具体工厂类。
  每个具体工厂类只能创建一个具体产品类的实例。
  抽象工厂模式:多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
         一个抽象工厂类可以派生出多个具体工厂类。
         每个具体工厂类可以创建多个具体产品类的实例
  工厂方法模式只有一个抽象产品类,而抽象工厂模式有多。
  工厂方法模式的具体工厂类中能创建一个具体的产品类的实例,而抽象工厂模式可以创建多个。

下面就用代码来实现模式

  1. 简单工厂模式
    这里写图片描述
    产品类:
public interface BMW {
    //每辆车子的车身都要涂漆
    void paint();
}

public class BMW320 implements BMW{
    public BMW320(){
        paint();
        System.out.println("宝马320");
    }
    @Override
    public void paint() {
        // TODO Auto-generated method stub
        System.out.println("涂320车身油漆");
    }
}

public class BMW523i implements BMW{
    public BMW523i(){
        paint();
        System.out.println("宝马523i");
    }
    @Override
    public void paint() {
        // TODO Auto-generated method stub
        System.out.println("涂523i车身油漆");
    }
}

public class BMWX7 implements BMW{
    public BMWX7(){
        paint();
        System.out.println("宝马X7");
    }
    @Override
    public void paint() {
        // TODO Auto-generated method stub
        System.out.println("涂X7车身油漆");
    }
}

工厂类:

public class Factory {
    //type客户要的宝马车的型号
    public static BMW createBMW(int type){
        switch (type) {
        case 1:
            return new BMW320();
        case 2:
            return new BMW523i();
        case 3:
            return new BMWX7();
        default:
            return null;
        }
    }
}

客户:

public class Client {
    public static void main(String[] args){
        BMW myBMW = Factory.createBMW(2);
    }
}

  这样一看这个模式其实很简单,我们来看一下它的组成:
  1)工厂类角色(Factory):该模式的核心,含有一定的商业逻辑和判断逻辑,比如说根据你传入的类型返回给你对应型号的车。
  2)抽象产品角色(BMW):一般是具体产品继承的父类或者实现的接口,本例中以接口的形式呈现。
  3)具体产品角色(BMW320,BMW523i,BMWX7—这三个都属于具体产品角色):工厂类所创建的对象就是次角色的实例。
  下面我们在开闭原则(对扩展开放,对修改关闭)上分析一下简单工厂模式。当客户不再满足现有的车型号的时候,想要一种速度快的新型车,只要这种车符合抽象产品定制的合同,那么只要通知到工厂类就可以被客户使用了。所以对产品部分来说,它是符合开闭原则的;但是工厂部分并不是,因为每增加一种新车型,都要在工厂类中增加相应的业务逻辑,这显然违背了开闭原则。当然这只是一个简单的例子,实际应用中,很可能产品是一个多层次的树状结构,而简单工厂中只有一个工厂类来对应这些产品,所以就不适用了。
  针对上述问题,换成工厂方法模式就可以了。此时工厂类被定义成了接口,每新增的车型,就增加该车型对应的工厂类的实现,这样的话,工厂的设计就可以扩展了,而不必去修改原来的代码。
2. 工厂方法模式
这里写图片描述

产品类:同上,没有变化,这里再贴一次

public interface BMW {
    //每辆车子的车身都要涂漆
    void paint();
}

public class BMW320 implements BMW{
    public BMW320(){
        paint();
        System.out.println("宝马320");
    }
    @Override
    public void paint() {
        // TODO Auto-generated method stub
        System.out.println("涂320车身油漆");
    }
}

public class BMW523i implements BMW{
    public BMW523i(){
        paint();
        System.out.println("宝马523i");
    }
    @Override
    public void paint() {
        // TODO Auto-generated method stub
        System.out.println("涂523i车身油漆");
    }
}

public class BMWX7 implements BMW{
    public BMWX7(){
        paint();
        System.out.println("宝马X7");
    }
    @Override
    public void paint() {
        // TODO Auto-generated method stub
        System.out.println("涂X7车身油漆");
    }
}

工厂类:

public interface Factory {
    BMW createBMW();
}

public class FactoryBMW320 implements Factory{
    @Override
    public BMW createBMW() {
        // TODO Auto-generated method stub
        return new BMW320();
    }
}

public class FactoryBMW523i implements Factory{
    @Override
    public BMW createBMW() {
        // TODO Auto-generated method stub
        return new BMW523i();
    }
}

public class FactoryBMWX7 implements Factory{
    @Override
    public BMW createBMW() {
        // TODO Auto-generated method stub
        return new BMWX7();
    }
}

客户:

public class Client {
    Factory f;
    public static void main(String[] args){
        Client c = new Client();
        c.getBMW(2);
    }
    public BMW getBMW(int type){
        switch (type) {
        case 1:
            f = new FactoryBMW320();
            return f.createBMW();
        case 2:
            f = new FactoryBMW523i();
            return f.createBMW();
        case 3:
            f = new FactoryBMWX7();
            return f.createBMW();
        default:
            return null;
        }
    }
}

工厂方法模式的组成:
  1)抽象工厂角色:这是核心,与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。java由接口或者抽象类实现。
  2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品对象。
  3)抽象产品角色:具体产品继承的父类或者是实现的接口。
  4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。
  现在来讲工厂方法和简单工厂做一个对比就一目了然了:去掉工厂方法的静态属性,并将工厂类变成接口(也可以用抽象类),再另外写具体的工厂实现该接口。
  简单工厂里集中在工程方法上的压力就可以由工厂模式里的不同工厂子类来分担,这就是工厂方法模式的核心所在。这样让结构变的灵活,当有新产品时,只要按照抽象产品角色和抽象工厂角色提供的合同来生产,就可以被客户使用,而不必去修改任何已有的代码。这样就符合开闭原则了。
  但是,工厂方法的加入,使对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这样就不优雅了。如果无法避免这种情况,可以考虑使用简单工厂模式模式与工程方法模式相结合的方式来减少工厂类,即对产品树上类似的种类使用简单工厂模式来实现。
  工厂方法模式适用情况:
  1)当客户程序不需要知道要使用对象的创建过程。
  2)客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。
3. 抽象工厂模式
这里写图片描述

产品类:

public interface BMW2 {
    //每辆车子的车身都要涂漆
    void paint();
}

public interface BMW3 {
    //每辆车子的车身都要涂漆
    void paint();
}

public class BMW320Three implements BMW3{
    public BMW320Three(){
        paint();
        System.out.println("3厢宝马320");
    }
    @Override
    public void paint() {
        // TODO Auto-generated method stub
        System.out.println("涂320车身油漆");
    }
}

public class BMW320Two implements BMW2{

    public BMW320Two(){
        paint();
        System.out.println("2厢宝马320");

    }

    @Override
    public void paint() {
        // TODO Auto-generated method stub
        System.out.println("涂320车身油漆");
    }
}

public class BMW523iThree implements BMW3{
    public BMW523iThree(){
        paint();
        System.out.println("3厢宝马523i");
    }
    @Override
    public void paint() {
        // TODO Auto-generated method stub
        System.out.println("涂523i车身油漆");
    }
}

public class BMW523iTwo implements BMW2{
    public BMW523iTwo(){
        paint();
        System.out.println("2厢宝马523i");
    }
    @Override
    public void paint() {
        // TODO Auto-generated method stub
        System.out.println("涂523i车身油漆");
    }
}

工厂类:

public interface Factory {
    BMW3 createBMW3();
    BMW2 createBMW2();
}

public class FactoryBMW320 implements Factory{
    @Override
    public BMW3 createBMW3() {
        // TODO Auto-generated method stub
        return new BMW320Three();
    }
    @Override
    public BMW2 createBMW2() {
        // TODO Auto-generated method stub
        return new BMW320Two();
    }
}

public class FactoryBMW523i implements Factory{
    @Override
    public BMW3 createBMW3() {
        // TODO Auto-generated method stub
        return new BMW523iThree();
    }
    @Override
    public BMW2 createBMW2() {
        // TODO Auto-generated method stub
        return new BMW523iTwo();
    }
}

客户:

public static void main(String[] args){
        Factory f = new FactoryBMW320();
        f.createBMW2();
    }

  抽象工厂模式的用意就是给客户端提供一个接口,可以创建多个产品族中的产品对象。这个模式还是存在缺点:产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用该模式,对产品等级结构的划分是非常重要的。
  适用场景:当需要创建的对象是一系列相互关联或相互依赖的产品族时。
  假如各个等级结构中的实现类之间不存在关联或者约束,则使用多个独立的工厂来对产品进行创建,也就是上面说的工厂方法模式。

总结
这三种模式在形式和特点上其实极为相似,最终目的也都是为了解耦。在使用时,不必在意这个模式是工厂方法还是抽象工厂,两者之间的演变其实很微妙。经常会发现,在使用工厂方法模式时,当新需求来临,稍加修改,添加一个新方法后,由于类中的产品构成了不同等级结构中的产品组,就变成抽象工厂了;对于抽象工厂,当减少一个方法使得提供的产品不再构成一个产品族之后,就变成工厂方法了。所有,在使用工厂模式时,只关心降低耦合的目的是否达到了。


参考:http://blog.csdn.net/hguisu/article/details/7505909
   http://wiki.jikexueyuan.com/project/java-design-pattern/abstract-factory-pattern.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值