Java设计模式(三—四)----工厂模式

Java设计模式

工厂模式 一、引言 二、分类 三、简单工厂模式 四、工厂方法模式 五、抽象工厂模式 六、和工厂方法模式区别 七、总结

工厂模式 在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象。在这些情况,新对象的建立就是一个“过程”,不仅是一个操作,像一部大机器中的一个齿轮传动。 模式的问题:你如何能轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程呢? 解决方案:建立一个工厂来创建对象

一、引言 1)还没有工厂时代:假如还没有工业革命,如果一个客户要一款宝马车,一般的做法是客户去创建一款宝马车,然后拿来用。 2)简单工厂模式:后来出现工业革命。用户不用去创建宝马车。因为客户有一个工厂来帮他创建宝马.想要什么车,这个工厂就可以建。比如想要宝马系列车。工厂就创建这个系列的车。即工厂可以创建产品。 3)工厂方法模式时代:为了满足客户,车系列越来越多,奔驰等系列,一个工厂无法创建所有的车系列。于是由单独分出来多个 具体的工厂。每个具体工厂创建一种系列。即具体工厂类只能创建一个具体产品。 4)抽象工厂模式时代:随着客户的要求越来越高,车进行分类,分为商务车和运动车两个族

二、分类 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。 工厂模式在《Java与模式》中分为三类: 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory) 这三种模式从上到下逐步抽象,并且更具一般性。 也可将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。 两者皆可 说明引子:从无到有。客户自己创建宝马车奔驰车,然后拿来用。

public class benzCar {
    public void dirve() {
        System.out.println("驾驶奔驰车");
    }
}

public class bmwCar {
     public void drive(){  
         System.out.println("驾驶宝马车");  
     } 
}






/**
 * 传统创建对象  没有通过工厂模式
 * @author Administrator
 *
 */
public class Client {
    public static void main(String[] args) {
        benzCar benz=new benzCar();
        bmwCar bmw=new bmwCar();
        benz.dirve();
        bmw.drive();
    }
}

客户需要知道怎么去创建一款车,客户和车就紧密耦合在一起了.为了降低耦合,就出现了工厂类,把创建宝马的操作细节都放到了工厂里面去,客户直接使用工厂的创建工厂方法,传入想要的宝马车名就行了,而不必去知道创建的细节.这就是工业革命了:简单工厂模式

三、简单工厂模式 简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。 先来看看它的组成: 1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。 2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。 3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。

/**
 * 抽象产品角色
 * @author Administrator
 *
 */
public interface Car {
    public void drive();
}



/**
 * 具体产品类
 * @author Administrator
 *
 */
public class benzCar implements Car {
    @Override
    public void drive() {
        System.out.println("驾驶奔驰车......");
    }

}

/**
 * 具体产品类
 * @author Administrator
 *
 */
public class bmwCar implements Car {

    @Override
    public void drive() {
        System.out.println("驾驶宝马车......");
    }
}


/**
 * 工厂类角色
 * @author Administrator
 *
 */
public class driverFactory {
    //返回类型必须为抽象产品角色
    public static Car dirveCar(String params) throws          Exception{
        //判断逻辑,返回具体的产品角色给Client
        if(params.equals("benzCar")){
            return new benzCar();
        }else if(params.equals("bmwCar")){
            return new bmwCar();
        }else{
            throw new Exception(); 
        }   
    }
}
//客户
public class Client {
    public static void main(String[] args) throws Exception {
        //告诉司机(工厂) 开奔驰车
        Car car=driverFactory.dirveCar("benzCar");
        //下命令开车
        car.drive();
    }
}

这便是简单工厂模式了。怎么样,使用起来很简单吧?那么它带来了什么好处呢? 首先,使用了简单工厂模式后,客户端免除了直接创建产品对象的责任,而仅仅负责“消费”产品。 下面我们从开闭原则(对扩展开放;对修改封闭)上来分析下简单工厂模式。当客户不再满足现有的车型的时候,想要一种速度快的新型车,只要这种车符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。所以对产品部分来说,它是符合开闭原则的;但是工厂部分好像不太理想,因为每增加一种新型车,都要在工厂类中增加相应的创建业务逻辑,这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类或者上帝类。 我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝累坏了,也累坏了我们这些程序员。 于是工厂方法模式作为救世主出现了。 工厂类定义成了接口,而每新增的车种类型,就增加该车种类型对应工厂类的实现,这样工厂的设计就可以扩展了,而不必去修改原来的代码。

四、工厂方法模式 工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。 你应该大致猜出了工厂方法模式的结构,来看下它的组成: 1) 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。 2) 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。 3) 抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。 4) 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。 用类图来清晰的表示下的它们之间的关系:

/**
 * 抽象产品角色
 * @author Administrator
 *
 */
abstract class Car {
    abstract void drive();
}


/**
 * 具体产品类
 * @author Administrator
 *
 */
public class bmwCar extends Car {

    @Override
    public void drive() {
        System.out.println("驾驶宝马车......");
    }
}
/**
 * 具体产品类
 * @author Administrator
 *
 */
public class benzCar extends Car {
    @Override
    public void drive() {
        System.out.println("驾驶奔驰车......");
    }
}


/**
 * 抽象工厂角色 用來生产车
 * @author Administrator
 *
 */
public interface abstractFactory {
    public Car driveFactory();

}


/**
 * 具体工厂角色
 * 创建奔驰车对象
 */
public class benzCarFactory implements abstractFactory {
    @Override
    public  Car driveFactory() {
        return new benzCar();
    }
}


/**
 * 具体工厂角色
 * 创建宝马车对象
 */
public class bmwCarFactory implements abstractFactory {
    @Override
    public Car driveFactory() {
        return new bmwCar();
    }
}


//客户
public class Client {
    private static Car benzcar,bmwcar;
    private static abstractFactory benzcarfactory,bmwcarfactory;
    public static void main(String[] args) throws Exception {
        //告诉(工厂) 要奔驰车
        benzcarfactory=new benzCarFactory();
        benzcar=benzcarfactory.driveFactory();
        //可以开车了
        benzcar.drive();
        System.out.println("-------------------");
        bmwcarfactory=new bmwCarFactory();
        bmwcar=bmwcarfactory.driveFactory();
        bmwcar.drive();
    }
}

工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使 得结构变得灵活起来——当有新的产品产生时,只要按照抽象产品角色、生成具体的实现类,那么就可以被客户使用,而不必去修 改任何已有的代码。可以看出工厂角色的结构也是符合开闭原则的! 可以看出工厂方法的加入,使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。因为如果不能避免这 种情况,可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来 实现。

五、抽象工厂模式 先来认识下什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。还是让我们用一个例子来形象地说明一下吧。

BenzSportsCar和BmwSportsCar 就是一个产品族。他们都可以放到跑车家族中,因此功能有所关联。同理BmwBussinessCar和BenzSportsCar也是一个产品族。商业族里面 回到抽象工厂模式的话题上。 可以说,抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。 抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象 而且使用抽象工厂模式还要满足以下条件: 1) 系统中有多个产品族,而系统一次只可能消费其中一族产品。 2) 同属于同一个产品族的产品以其使用。 来看看抽象工厂模式的各个角色(和工厂方法的如出一辙): 1) 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。 2) 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。 3) 抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。 4) 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。

// 抽象工厂类  定义不同的产品之间的标准,商务车
public interface ICarA {
    public void drive();
}


// 抽象工厂类  定义不同的产品之间的标准 跑车族
public interface ICarB {
    public void drive();
}

//具体产品类
public class productAHongqi implements ICarA {
    @Override
    public void drive() {
        System.out.println("开商务族--红旗车");
    }
}

//具体工厂类
public class productABmw implements ICarA {
    @Override
    public void drive() {
         System.out.println("开商务族--宝马车 ..."); 
    }
}

//具体产品类
public class producSporttBAudi implements ICarB {
    @Override
    public void drive() {
        System.out.println("开跑车族--奥迪车...");
    }
}


//具体工厂类
public class productSportBBenz implements ICarB {
    @Override
    public void drive() {
         System.out.println("开跑车族--奔驰车 ..."); 
    }
}


/**
 * 抽象工厂类 创建跑车族跑车
 * @author Administrator
 *
 */
public abstract class abstractoryFactory1 {
    abstract ICarB getProductBBenz();
    abstract ICarB getProductBAudi();
}


/**
 * 抽象工厂类  创建商务族跑车
 * @author Administrator
 *
 */
public abstract class abstractoryFactory2 {
    abstract ICarA getProductABmw();
    abstract ICarA getProductBHongqi();
}


/**
 * 具体工厂类 跑车族
 * @author Administrator
 *
 */
public class Factory1 extends abstractoryFactory1 {

    @Override
    ICarB getProductBBenz() {
        return new productSportBBenz();
    }

    @Override
    ICarB getProductBAudi() {
        return new producSporttBAudi();
    }
}


/**
 * 具体工厂类
 * 商务族
 * @author Administrator
 *
 */
public class Factory2 extends abstractoryFactory2 {
    @Override
    ICarA getProductABmw() {
        return new productABmw();
    }

    @Override
    ICarA getProductBHongqi() {
        return new productAHongqi();
    }
}


public class Client {
    public static void main(String[] args) {
        //工厂一制造的产品族车
        abstractoryFactory1 factory1 = new Factory1(); 
        ICarB productsportAbenz = factory1.getProductBBenz(); 
        ICarB productsportBaudi = factory1.getProductBAudi(); 

        productsportAbenz.drive(); 
        productsportBaudi.drive(); 
        //工厂二制造的产品族车
        abstractoryFactory2 factory2 = new Factory2(); 
        ICarA productAbmw = factory2.getProductABmw(); 
        ICarA productBhongqi = factory2.getProductBHongqi(); 
        productAbmw.drive(); 
        productBhongqi.drive(); 
    }
}

六、和工厂方法模式区别 工厂方法模式: 一个抽象产品类,可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类只能创建一个具体产品类的实例。 抽象工厂模式: 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类可以创建多个具体产品类的实例。 区别: 工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个(产品族)。 工厂方法模式的具体工厂类只能创建一个具体产品类的实例(一对一),而抽象工厂模式可以创建多个具体产品类的实例(一对多)。

七、总结 无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们具体问题具体分析

以上内容来自平时所看书籍和网络资源整理测试所得,如有不完善之处,欢迎指正!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏漫漫深度学习路

tensorflow学习笔记(二十八):collection

tensorflow collection tensorflow的collection提供一个全局的存储机制,不会受到变量名生存空间的影响。一处保存,到处可取。...

3489
来自专栏iKcamp

翻译连载 |《你不知道的JS》姊妹篇 |《JavaScript 轻量级函数式编程》- 第 6 章:值的不可变性

原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 第 6 章:值的不可变性 在第 ...

2055
来自专栏老九学堂

零基础学Java第三讲变量

如何掌握了变量这个语法?看看微视频中对应的知识点的讲解。 别走开,下面有干货哦! 1了解什么是变量?变量如何使用? 2会使用常用的数据类型 任何编程语言的语...

2825
来自专栏华章科技

值得收藏的Python小技巧:这17个骚操作你都OK吗?

导读:Python 是一门非常优美的语言,其简洁易用令人不得不感概人生苦短。在本文中,作者 Gautham Santhosh 带我们回顾了 17 个非常有用的 ...

2973
来自专栏微信公众号:Java团长

谈谈我对面向对象以及类与对象的理解

对于刚接触JAVA或者其他面向对象编程语言的朋友们来说,可能一开始都很难理解面向对象的概念以及类和对象的关系。笔者曾经带过一个短期培训班教授java入门基础,在...

1072
来自专栏编程微刊

2018年各大互联网前端面试题二(滴滴打车)

3562
来自专栏编程

C语言最难啃的三块硬骨头,你越过去了吗?

提到C语言很多初学者都觉得,学到中间就进行不下去了,因为碰到了几个硬骨头死活翻不过去,于是很多人给C语言下结论太难了,太靠近底层了,特别是那几块难啃的骨头,直接...

2268
来自专栏WeaponZhi

AI 学习之路——轻松初探 Python 篇(三)

这是「AI 学习之路」的第 3 篇,「Python 学习」的第 2 篇 Python 字符串使用和 C 语言比较类似,但还有一些我们值得注意的地方需要关注,用这...

3446
来自专栏java技术学习之道

java设计模式之工厂模式

1513
来自专栏程序员互动联盟

10个实用的但偏执的Java编程技术

在沉浸于编码一段时间以后(比如说我已经投入近20年左右的时间在程序上了),你会渐渐对这些东西习以为常。因为,你知道的……任何事情有可能出错,没错,的确如此。 这...

35413

扫码关注云+社区