官方定义:设计模式(Design Pattern)是一套被反复使用、多数人知晓的、通过分类编目的代码设计经验总结。java
使用意义:使用设计模式是为了可重用代码,让代码更容易被他人理解,保证代码的可靠性。可复用的面向对象软件系统主要包含两大类:应用程序工具箱和框架(框架是指构成一类特定软件可复用设计的一组相互协做的类)。设计模式有助于对框架的理解,成熟的框架一般使用了多种设计模式,若是你能熟悉这些设计模式,毫无疑问,将能迅速的掌握框架的结构。数据库
工厂模式将客户类与工厂类分开,消费者在任什么时候候须要某种产品只须要向工厂请求,消费者无须修改就能接纳新产品。缺点:产品修改时,工厂类也要作相应的修改。工厂模式是编程过程当中最经常使用的设计模式,由于工厂模式至关于建立实例对象的new, 例如 A a = new A();工厂类也是用来建立实例对象的,那么,new关键字能够建立对象,为何还要用工厂类建立实例对象呢?因为建立实例时一般伴随有初始化工做,若是只是简单的赋值操做,咱们可使用带参数的构造方法,但若是初始化不只仅是赋值这样简单的操做,还包含一些逻辑判断等大片断的代码,若是都写进构造函数,会使咱们的代码看起来很臃肿,将多个功能放进一个方法,就像将不少鸡蛋放进一个篮子里,这很危险,而且有悖于咱们面向对象的设计原则。这时须要咱们将长片断的代码进行分割,再封装,之后若是须要修改,只须要修改部分片断,而不会出现牵一动百的情形。编程
简单工厂模式的是想源于java中的接口,经过使用接口能够实现不相关类的相同行为,而不须要考虑这些类的层次关系,接口就是实现类对外的外观。主要使用在业务比较简单的状况下,由三种角色构成。设计模式
Client与具体实现Impl之间并没有瓜葛,客户端经过Factory获取须要的接口对象,而后调用接口的方法来实现具体的功能。下面举个例子,经过不一样的通信工具来通讯,QQ和微信分别实现了API接口。微信
/** * 简单工厂模式 * Created by xian.juanjuan on 2017-7-13 14:07. */ public class SimpleFactory { //根据条件建立具体的实现对象 public static MessageApi createMessageApi(int condition){ MessageApi messageApi = null; if (condition == 1){ messageApi = new QQMessageImpl(); } else if (condition == 2){ messageApi = new WeChatMessageImpl(); } return messageApi; } } class Client{ public static void main(String[] args){ //经过简单工厂获取接口对象 MessageApi messageApi = SimpleFactory.createMessageApi(1); messageApi.sendMessage("测试简单工厂模式"); } } /** * 通讯接口能够经过简单工厂来建立 */ interface MessageApi{ //具体的功能方法 void sendMessage(String msg); } /** * 接口的具体实现--QQ通讯 */ class QQMessageImpl implements MessageApi{ @Override public void sendMessage(String msg) { System.out.println("经过QQ聊天工具发送消息:"+msg); } } /** * 接口的具体实现--微信通讯 */ class WeChatMessageImpl implements MessageApi{ @Override public void sendMessage(String msg) { System.out.println("经过微信聊天工具发送消息"+msg); } }问题1:这里若是再增长一种通信方式(Email)时,就须要修改工厂类,显然简单工厂方式不能知足OCP设计原则。
问题2:客户端在调用工厂时,须要传入选择的参数,这就说明客户端必须知道每一个参数的含义,也须要知道每一个参数对应的功能处理,在必定程度上向客户端暴露了内部实现细节。框架
每次增长一个实现类就要就要修改工厂类的实现,一般用配置文件类解决这个问题。less
建立FactoryTest.properties配置文件,内容以下,若是新增实现类,只须要修改下面的配置文件便可。ide
ImplClass=com.xianjj.pattern.QQMessageImpl
工厂类以下函数
public class SimpleFactory { public static MessageApi createMessageApi(){ Properties properties = new Properties(); InputStream inputStream; try { inputStream = SimpleFactory.class.getResourceAsStream("FactoryTest.properties"); properties.load(inputStream); } catch (IOException e) { System.out.println("加载工厂配置文件异常"); e.printStackTrace(); } //用反射建立对象 MessageApi messageApi = null; try { messageApi = (MessageApi)Class.forName(properties.getProperty("ImplClass")).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return messageApi; } }
简单工厂一般不用建立简单工厂类的类实例,所以,能够把简单工厂类看作一个工具类,直接使用静态方法就能够了,因此被称做静态工厂。为了防止客户端无谓的建立简单工厂实例,能够把简单工厂的构造方法私有化。工具
为了解决简单工厂模式最大的缺点—不彻底知足OCP原则,设计师们提出了工厂方法模式,工厂方法模式相对于简单工厂模式来讲最大的不一样在于,对于一个项目或者一个独立的模块来讲,简单工厂模式只有一个工厂类,儿工厂方法模式有一组实现了相同接口的工厂类。
在工厂方法模式中,核心的工厂类再也不负责产品的建立,而是将具体的建立工做交给子类去作。这个核心工厂则变为抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触产品建立的细节。在工厂方法模式中通常都有一个平行的等级结构,也就是说工厂和产品是对应的。
果农起初只有一个小型的苹果园,后来规模扩大,出现了苹果工厂,葡萄工厂,每一个工厂独立生产对应的水果,实现专业化和规模化的生产。
/** * 工厂方法模式示例 * Created by xian.juanjuan on 2017-7-14 09:30. */ public class ClientTest { public static void main(String[] args){ //实例化水果工厂 FruitFactory fruitFactory = new AppleFactoryImpl(); FruitFactory fruitFactory1 = new GrapeFactoryImpl(); //从水果工厂生产水果 Fruit fruit = fruitFactory.factory(); Fruit fruit1 = fruitFactory1.factory(); //不一样水果的生长过程 fruit.plant(); fruit1.harvest(); } } /** * 水果接口 */ interface Fruit{ void plant();//种植 void harvest();//收获 } /** * 水果工厂的产品:苹果 */ class Apple implements Fruit{ private int treeAget;//树龄 @Override public void harvest() { System.out.println("苹果已经收获。。。"); } @Override public void plant() { System.out.println("苹果已经种植。。。"); } public int getTreeAget() { return treeAget; } public void setTreeAget(int treeAget) { this.treeAget = treeAget; } } /** * 水果工厂的产品:葡萄 */ class Grape implements Fruit{ private boolean seedless;//是否有籽 @Override public void harvest() { System.out.println("葡萄已经收获。。。"); } @Override public void plant() { System.out.println("葡萄已经种植。。。"); } public boolean isSeedless() { return seedless; } public void setSeedless(boolean seedless) { this.seedless = seedless; } } /** * 水果工厂接口 */ interface FruitFactory{ Fruit factory(); } /** * 苹果工厂实现 */ class AppleFactoryImpl implements FruitFactory{ @Override public Fruit factory() { Fruit fruit = new Apple(); System.out.println("水工工厂成功建立一个水果:苹果"); return fruit; } } /** * 葡萄工厂实现 */ class GrapeFactoryImpl implements FruitFactory{ @Override public Fruit factory() { Fruit fruit = new Grape(); System.out.println("水工工厂成功建立一个水果:葡萄"); return fruit; } }
输出结果
水工工厂成功建立一个水果:苹果
水工工厂成功建立一个水果:葡萄
苹果正在生长。。。
葡萄已经收获。。。
Process finished with exit code 0
抽象工厂模式是三个最抽象,最具通常性的。抽象工厂模式的目的是给客户端提供一个接口,能够建立多个产品族中的产品对象,使用抽象工厂模式须要知足如下条件
举例说明两个概念
抽象工厂模式的每一个工厂创造出的都是一族的产品,而不是一个或者一组。
用户买手机配充电器
public class AbstractFactoryTest { public static void main(String[] args){ phoneCharging(1, 1); } public static void phoneCharging(int phoneType, int chargerType){ //手机工厂和充电器工厂生产手机和充电器 Phone phone = PhoneFactory.createPhone(phoneType); Charger charger = ChargerFactory.createCharger(chargerType); //买手机配充电器 phone.buyPhone(); charger.configureCharger(); } } /** * 手机接口 */ interface Phone{ void buyPhone();//买手机 } class AndroidPhone implements Phone{ @Override public void buyPhone() { System.out.println("我买了一部Android手机"); } } class ApplePhone implements Phone{ @Override public void buyPhone() { System.out.println("我买了一部Apple手机"); } } /** * 充电器接口 */ interface Charger{ void configureCharger();//配置充电器 } class AndroidCharger implements Charger{ @Override public void configureCharger() { System.out.println("给我配置了Android手机充电器"); } } class AppleCharger implements Charger{ @Override public void configureCharger() { System.out.println("给我配置了Apple手机充电器"); } } /** * 手机工厂类 */ class PhoneFactory{ public static Phone createPhone(int type){ Phone phone = null; if (1 == type){ phone = new AndroidPhone(); } else if (2 == type){ phone = new ApplePhone(); } return phone; } } /** * 充电器工厂类 */ class ChargerFactory{ public static Charger createCharger(int type){ Charger charger = null; if (1 == type){ charger = new AndroidCharger(); } else if(2 == type){ charger = new AppleCharger(); } return charger; } }运行结果
我买了一部Android手机
给我配置了Android手机充电器
Process finished with exit code 0
外部使用的时候,手机与充电器的类型须要匹配,若是phoneCharging(1, 2);那手机和充电器就不兼容;在上述的简单工厂模式中,并无维护这种关系,为了解决这个问题 须要使用抽象工厂模式。简单工厂模式针对的是一个产品等级结构,而抽象工厂模式则须要面对多个产品等级结构。
用同一个工厂等级结构复杂两个不一样产品等级结构中的产品对象的建立,即Apple工厂生产Apple手机和Apple手机充电器。因为这两个产品族的产品等级结构相同,所以使用同一个工厂族也能够处理这两个产品族的建立问题,这就是抽象工厂模式。
在以前代码的基础上,只须要增长抽象工厂类和实现便可。
interface AbstractFactory{ Phone createPhone(); Charger createCharger(); } class AndroidFactory implements AbstractFactory{ @Override public Charger createCharger() { return new AndroidCharger(); } @Override public Phone createPhone() { return new ApplePhone(); } } class AppleFactory implements AbstractFactory{ @Override public Charger createCharger() { return new AppleCharger(); } @Override public Phone createPhone() { return new ApplePhone(); } } 测试客户端 public class AbstractFactoryTest { public static void main(String[] args){ //客户选择并建立须要的产品对象 AbstractFactory factory = new AppleFactory(); //让店员配套起来便可 phoneCharging(factory); } public static void phoneCharging(AbstractFactory factory){ //店员找相应的工厂获取产品 Phone phone = factory.createPhone(); Charger charger = factory.createCharger(); phone.buyPhone(); charger.configureCharger(); } }因而可知,抽象工厂模式是为一系列相关的对象或者相互依赖的对象建立一个接口。