Java中的GOF23(23中设计模式)--------- 工厂模式(Factory)

    在给大家介绍工厂模式之前,我想和大家聊聊面向对象的那点事,在这里,引入三个概念。

      开闭原则(Open Closed Principle)是Java世界里最基础的设计原则,它指导我们如何建立一个稳定的、灵活的系统:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。说白了就是在这里我的项目写完了,你到改某些功能,就只能添加新的类,不能修改其他的类,在这里也许会有很多的人会说,为什么呀,我举个例子,你做的版本是2.5的然后你要做2.6的如果你全部都修改了,那就意味着所有的测试用例要改,并且你的工期也得大大的延长,预算也会大大的提高 ·········

      注意:开闭原则对扩展开放,对修改关闭,并不意味着不做任何修改,底层模块的变更,必然要有高层模块进行耦合,否则就是一个孤立无意义的代码片段了。

      

      迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle,LKP),一个对象应该对其他对象有最少的了解。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的public方法,我就调用这么多,其他的一概不关心。说白了就是只和朋友类交流,而朋友类的定义是这样的:出现在成员变量、方法的输入输出参数中的类称为成员朋友类,而出现在方法体内部的类不属于朋友类。

      依赖倒置原则(DIP--Dependency Inversion Principle):高层模块不应该依赖于低层模块,二者都应该依赖于抽象,抽象不应该依赖于细节,细节应该依赖于抽象。高层模块包含了一个应该程序中的重要的策略选择和业务模型,正是这些高层模块才使得其所有的应用程序区别于其他,如果高层依赖于低层,那么对低层模块的改动就会直接影响到高层模块,从而迫使它们依次做出改动。说白了就是应该面向接口编程,而不应该面向实体类编程。

  

   其实这种编程的原则还有几个,当然我也只是为了更好的引出上述的工厂模式,其他的会在其他的设计模式当中 一 一 提出的,

   下面我就给大家说说工厂模式吧,工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。工厂模式主要分为三个,在某些书中分为两类主要是将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。

      1)简单工厂模式(Simple Factory) 又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据自变量的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

          (1)工厂类(Creator)角色:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体Java 类实现。

         (2)抽象产品(Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。抽象产品角色可以用一个Java 接口或者Java 抽象类实现。

         (3)具体产品(Concrete Product)角色:工厂方法模式所创建的任何对象都是这个角色的实例,具体产品角色由一个具体Java 类实现。

          

 /**
*
* @author 刘酸酸,
* 这是我们的产品类的总接口,就是说我们的每一辆汽车都会有驾驶的功能
*
*/
public interface Car {
void driver();
}
/**
* 大货车
* @author 刘酸酸
*
*/
public class BigTruck implements Car { public BigTruck() {
driver();
} @Override
public void driver() {
System.out.println("大货车出发了····");
} }
/**
*
* @author 刘酸酸,
*
*
*/
public class Bus implements Car { public Bus() {
driver();
} @Override
public void driver() {
System.out.println("大客车出发了");
}
}
/**
* 创建产品的工厂类
* @author 刘酸酸
*
*/
public class Factory {
public static Car createCar(int flag){
switch (flag) {
case 1:
return new BigTruck();
case 2:
return new Bus();
case 3:
return new Sedan();
}
return null;
}
}
/**
* 相当于我们的客户类
* @author 刘酸酸
*
*/
public class Main {
public static void main(String[] args) {
Factory.createCar(1);
Factory.createCar(2);
Factory.createCar(3);
}
}

    简单工厂模式的优缺点

      简单工厂模式的优点如下:

        (1)工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。

        (2)客户端无需知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。

        (3)通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

      简单工厂模式的缺点如下:

        (1)由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。

        (2)使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。

        (3)系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

        (4)简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。

      简单工厂模式的适用环境

        (1)工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂;

        (2)客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。

2)工厂方法模式(Factory Method) :工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method是一个类的实例化延迟到其子类。在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。这个核心类则摇身一变,成为了一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。

  工厂方法模式角色

   (1) 抽象工厂(Creator)角色:担任这个角色的是工厂方法模式的核心,它是与应用程序无关的。任何在模式中创建对象的工厂类必须实现这个接口。在上面的 系统中这个角色由Java 接口Creator 扮演;在实际的系统中,这个角色也常常使用抽象Java 类实现。

   (2) 具体工厂(Concrete Creator)角色:担任这个角色的是实现了抽象工厂接口的具体Java 类。具体工厂角色含有与应用密切相关的逻辑,并 且受到应用程序的调用以创建产品对象。在本系统中给出了两个这样的角色,也就是具体Java 类ConcreteCreator1 和 ConcreteCreator2。

   (3)抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。在本系统中,这个角色由Java 接口Product 扮演;在实际的系统中,这个角色也常常使用抽象Java 类实现。

   (4)具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所声明的接口。工厂方法模式所创建的每一个对象都是某个具体产品角色的实例。

    产品类介绍

 /**
*
* @author 刘酸酸,
* 这是我们的产品类的总接口,就是说我们的每一辆汽车都会有驾驶的功能
*
*/
public abstract class Car {
public abstract void driver();
} /**
* 大货车
* @author 刘酸酸
*
*/
public class BigTruck extends Car { @Override
public void driver() {
System.out.println("的大货车出发了····");
} }
/**
*
* @author 刘酸酸,
*
*
*/
public class Bus extends Car { @Override
public void driver() {
System.out.println("客车开动了 ");
} }/**
* 小轿车
* @author 刘酸酸
*
*/
public class Sedan extends Car { @Override
public void driver() {
System.out.println("小轿车出发了");
} }

    

    工厂类的介绍

 /**
* 创建产品的总工厂,大家可以理解为里面有多个小车间
* @author 刘酸酸
*
*/
public abstract class Factory { public abstract Car getCar();
} /**
* 我们的生产大货车的小车间
* @author 刘酸酸
*
*/
public class BigTruckFactory extends Factory{ @Override
public Car getCar() {
return new BigTruck();
} }
/**
* 生产大客车的小车间
* @author 刘酸酸
*
*/
public class BusFactory extends Factory{ @Override
public Car getCar() {
return new Bus();
} }
/**
* 生产小轿车的小车间
* @author 刘酸酸
*
*/
public class SedanFactory extends Factory{ @Override
public Car getCar() {
return new Sedan();
} }

    客户类

 /**
* 相当于我们的客户类
* @author 刘酸酸
*
*/
public class Main {
public static void main(String[] args) {
new BigTruckFactory().getCar().driver();
new BusFactory().getCar().driver();
new SedanFactory().getCar().driver();
}
}

工厂方法模式的优缺点

  工厂方法模式的优点如下:

    (1)在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无需关心创建细节,甚至无需知道具体产品类的类名。

    (2)基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,正是因为所有的具体工厂类都具有同一抽象父类。

    (3)使用工厂方法模式的另一个优点是在系统中加入新产品时,无需修改抽象工厂和抽象产品提供的接口,无需修改客户端,也无需修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

  工厂方法模式的缺点如下:

    (1)在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。

    (2)由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

  工厂方法模式的适用环境

    (1)一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。

    (2)一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。

    (3)将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无需关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

3)抽象工厂模式(Abstract Factory): 抽象工厂模式提供一个创建一系列或相互依赖的对象的接口,而无需指定它们具体的类。 

  抽象工厂模式角色

    (1)抽象工厂(AbstractFactory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统的商业逻辑无关的。通常使用Java 接口或者抽象Java 类实现,而所有的具体工厂类必须实现这个Java 接口或继承这个抽象Java 类。

    (2)具体工厂类(Conrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。通常使用具体Java 类实现这个角色。

    (3)抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。通常使用Java 接口或者抽象Java 类实现这一角色。

    (4)具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。通常使用具体Java 类实现这个角色。

  产品类

  

 /**
*
* @author 刘酸酸,
* 这是我们的产品类的总接口,就是说我们的每一辆汽车都会有驾驶的功能
*
*/
public abstract class Car {
public abstract void driver();
}
/**
*
* @author 刘酸酸,
*
*
*/
public class Bus extends Car { @Override
public void driver() {
System.out.println("客车开动了 ");
} }/**
* 大货车
* @author 刘酸酸
*
*/
public class BigTruck extends Car { @Override
public void driver() {
System.out.println("大货车出发了····");
} }
/**
*
* @author 刘酸酸,
* 这是我们的产品类的总接口,就是说我们的每一辆汽车都会有驾驶的功能
*
*/
public abstract class Train {
public abstract void driver();
} /**
* 拉货的火车
* @author 刘酸酸
*
*/
public class GoodsTrain extends Train { @Override
public void driver() {
System.out.println("拉货的火车出发了····");
} } /**
* 动车
* @author 刘酸酸
*
*/
public class DTrain extends Train { @Override
public void driver() {
System.out.println("动车出发了");
} }

  工厂类

 /**
* 创建产品的总工厂,
* @author 刘酸酸
*
*/
public abstract class Factory { public abstract Car getCar();
public abstract Train getTrain(); }
/**
* 生产拉货的交通工具
* @author 刘酸酸
*
*/
public class GoodsFactory extends Factory{ @Override
public Car getCar() {
return new BigTruck();
} @Override
public Train getTrain() {
return new GoodsTrain();
} }
/**
* 我们的生产可以坐人的车
* @author 刘酸酸
*
*/
public class peopleFactory extends Factory{ @Override
public Car getCar() {
return new Bus();
} @Override
public Train getTrain() {
return new DTrain();
} }

  客户类

 

 /**
* 相当于我们的客户类
* @author 刘酸酸
*
*/
public class Main {
public static void main(String[] args) { //生产拉货的车
GoodsFactory goodsFactory = new GoodsFactory();
goodsFactory.getCar().driver();
goodsFactory.getTrain().driver(); //生产拉人的车
peopleFactory peopleFactory = new peopleFactory();
peopleFactory.getCar().driver();
peopleFactory.getTrain().driver();
}
}

抽象工厂模式的优缺点

  优点:

    (1) 隔离了具体类的生成,使得用户不需要知道什么被创建了。

    (2) 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。

  缺点:

    (1)添加新的产品对像时,难以扩展抽象工厂以便生产新种类的产品。

  抽象工厂模式的适用环境

    (1)一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节。这对于所有形态的工厂模式都是重要的;

    (2)一个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品;

    (3)同属于同一个产品族的产品是在一起使用的,这一约束必须要在系统的设计中体现出来;

    (4)系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

  参考文档 http://www.360doc.com/content/14/0306/21/1332348_358346183.shtml

      http://blog.csdn.net/jason0539/article/details/44976775

      

Java中的GOF23(23中设计模式)--------- 工厂模式(Factory)的更多相关文章

  1. Java中的GOF23(23中设计模式)--------- 单例模式(Singleton)

    Java中的GOF23(23中设计模式)--------- 单例模式(Singleton) 在Java这这门语言里面,它的优点在于它本身的可移植性上面,而要做到可移植的话,本身就需要一个中介作为翻译工 ...

  2. JAVA常用设计模式(一、单例模式、工厂模式)

    JAVA设计模式之单例模式 import java.util.HashMap; import java.util.Map; /** * 设计模式之单例模式 * 单例模式(Singleton Patte ...

  3. SpringBoot使用策略模式+工厂模式

    为了防止大量的if...else...或switch case代码的出现,可以使用策略模式+工厂模式进行优化. 在我的项目当中,报表繁多,所以尝试了这种方式进行优化报表的架构.代码很简单,如下: Fa ...

  4. Spring中常用的23中设计模式

    1.spring 中常用的设计模式有23中  分类  设计模式  创建型 工厂方法模式(FactoryMethod).抽象工厂模式(AbstractFactory).建造者模式(Builder).原型 ...

  5. Java EE设计模式(主要简单介绍工厂模式,适配器模式和模板方法模式)

    Java EE设计模式分为三种类型,共23种: 创建型模式:单例模式.抽象工厂模式.建造者模式.工厂模式.原型模式. 结构型模式:适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式 ...

  6. Java设计模式02:常用设计模式之工厂模式(创建型模式)

    一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的.  工厂模式在<Java与模式>中分为三类: 1)简单工厂模式(Simple Fact ...

  7. Springboot中实现策略模式+工厂模式

    策略模式和工厂模式相信大家都比较熟悉,但是大家有没有在springboot中实现策略和工厂模式? 具体策略模式和工厂模式的UML我就不给出来了,使用这个这两个模式主要是防止程序中出现大量的IF ELS ...

  8. Java 设计模式系列(二)简单工厂模式和工厂方法模式

    Java 设计模式系列(二)简单工厂模式和工厂方法模式 实现了创建者和调用者的分离.分为:简单工厂模式.工厂方法模式.抽象工厂模式 简单工厂模式.工厂方法模式都很简单,就不详细介绍了. 一.简单工厂 ...

  9. 23种设计模式--工厂模式-Factory Pattern

    一.工厂模式的介绍       工厂模式让我们相到的就是工厂,那么生活中的工厂是生产产品的,在代码中的工厂是生产实例的,在直白一点就是生产实例的类,代码中我们常用new关键字,那么这个new出来的实例 ...

随机推荐

  1. WIN8 下Cisco VPN连接 出现vpn 422 failed to enable virtual adapter错误

    今天在家用VPN软件连接,出现了“vpn 422 failed to enable virtual adapter”的错误,系统安装的是Win8专业版32位,百度了半天又很多方法解决不了,后来发现了一 ...

  2. 写给已有编程经验的 Python 初学者的总结

    当我开始学习Python的时候,有些事我希望我一早就知道.我花费了很多时间才学会这些东西.我想要把这些重点都编纂到一篇文章当中.这篇文章的目标读者,是刚刚开始学习Python语言的有经验的程序员,想要 ...

  3. 【转】 SVM算法入门

    课程文本分类project SVM算法入门 转自:http://www.blogjava.net/zhenandaci/category/31868.html (一)SVM的简介 支持向量机(Supp ...

  4. [LeetCode] Longest Valid Parentheses 动态规划

    Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...

  5. 2014-09-19.xml

    <wordbook><item>    <word>basel</word>     <trans><![CDATA[ n. 巴塞尔( ...

  6. Golang控制goroutine的启动与关闭

    最近在用golang做项目的时候,使用到了goroutine.在golang中启动协程非常方便,只需要加一个go关键字: go myfunc(){ //do something }() 但是对于一些长 ...

  7. Windows Storage Server 2008 R2 Standard(64位)之ASM(Automated Storage Manager)管理

    一.服务器管理器之LUN管理 服务器管理器的LUN管理,右键可删除(注意别删了系统分区在的LUN) 二.ASM(Automated Storage Manager) view 高级信息,请不要修改相关 ...

  8. Rpath handling on Linux

    The solution in the article below seems promising: http://www.blaenkdenum.com/notes/cmake/#rpath set ...

  9. Linux高级编程--04.GDB调试程序(查看数据)

    查看栈信息 当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的.当你的程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入"栈"(Stack)中.你可以用 ...

  10. 深入HTML5 Web Worker应用实践:多线程编程

    HTML5 中工作线程(Web Worker)简介 至 2008 年 W3C 制定出第一个 HTML5 草案开始,HTML5 承载了越来越多崭新的特性和功能.它不但强化了 Web 系统或网页的表现性能 ...