java基础之----23种设计模式(工厂模式)
概述
平时工作中我们写程序不会刻意去思考这里是不是需要使用一下设计模式,而且很少关心这个东西,但是在一些工具框架中却大量使用设计模式,比如spring框架中就大量使用工厂模式,那问题来了,到底什么是设计模式?为什么要使用设计模式?,因为本文是设计模式系列的第一篇,所以需要回答上面两个问题,才可以向下写。其实设计模式一开始并不是开始于软件工程中,而是开始于建筑行业,美国有个大佬发现建筑上人们对舒适住宅和城市环境存在一些共同的认同规律,后来就在这些规律中找到了253中模式,比如富人区适合盖什么楼,穷人区适合盖什么楼,后来软件工程界效仿建筑工程的模式来搞,最早开始把这个引入软件工程界的是"四人帮",简称GoF,在1994年他们归纳出了23中设计模式。
(四人帮)
设计模式是什么?为什么要使用设计模式?
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。
下面开始本篇文章的正文,工厂模式
工厂模式简介
简单来说工厂模式分为三大类,简单工厂模式,工厂方法模式,抽象工厂模式,复杂度是逐渐提高的,所能解决的问题也越来越复杂。
简单工厂模式
简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。简单工厂模式的要点在于:当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。
下面直接通过代码演示,基本看了代码就知道什么是简单工厂模式。
抽象产品类,供具体的产品类继承,里面有抽象方法,我当前的例子中使用的抽象产品类是服装类,那他的子类可以是裤子,内衣,帽子等等。
/** * Description: 抽象产品类 */ public abstract class AbstractClotheProduct { //产品公共方法 public void methodSame(){ System.out.println("我是服装"); } //每个产品不同的方法,由具体产品具体实现 public void methodDiff(){ } }
具体产品类帽子
/** * Description: 具体产品类,hat */ public class HatProduct extends AbstractClotheProduct { public void methodDiff() { System.out.println("我是hat,我关心你是谁,因为不要随便戴绿帽子"); } }
具体产品类shirt
/** * Description: 具体产品类,shirt */ public class ShirtProduct extends AbstractClotheProduct{ public void methodDiff(){ System.out.println("我是shirt,我不关心你是谁"); } }
简单工厂,用于生产服装产品
/** * Description: 简单工厂 */ public class SimpleFactory { //静态工厂方法 public static AbstractClotheProduct createProduct(String args) { AbstractClotheProduct abstractClotheProduct = null; if (args.equals("shirt")) { abstractClotheProduct = new ShirtProduct(); } else if (args.equals("hat")) { abstractClotheProduct = new HatProduct(); } return abstractClotheProduct; } }
客户端,使用工厂生产产品
package com.gxl.demo.DesignPattern.factorypattern.simple; /** * Description: 客户端 */ public class Client { public static void main(String[] args) { AbstractClotheProduct shirtProduct = SimpleFactory.createProduct("shirt"); shirtProduct.methodDiff(); AbstractClotheProduct hatProduct = SimpleFactory.createProduct("hat"); hatProduct.methodDiff(); } }
简单工厂模式总结
首先,简单工厂模式并不包括在23中设计模式之中,可能四人帮觉得太简单了吧。先说一下简单工厂模式的优点,简单工厂模式主要的优点就是客户端可以不用自己创建对象,而是由工厂创建,使对象的创建和使用分离,减少系统的复杂度。缺点是由于工厂类中集中了所有的对象的创建逻辑,使工厂类变得很复杂,很重,扩展困难,扩展的话要修改原来的代码,不符合单一职责原则和开闭原则(至于这两个是什么玩意,可以参考这篇文章:设计模式:面向对象设计的六大原则 (绝对详细))
工厂方法模式
为了解决简单工厂模式扩展需要修改原代码的问题,不符合开闭原则,引入了工厂方法模式。在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不同的工厂,系统提供一个与产品等级结构对应的工厂等级结构。下面通过一个例子就可以明白上面那句很绕的话。
抽象产品
package com.gxl.demo.DesignPattern.factorypattern.method; /** * Description: 抽象产品 */ public interface Product { public void methodDiff(); }
具体产品,shirt
package com.gxl.demo.DesignPattern.factorypattern.method; /** * Description: 具体工厂 */ public class ShirtFactory implements Factory{ //创建具体工厂 public Product createFactory(){ Product product = new ShirtProduct(); return product; } }
具体产品,hat
package com.gxl.demo.DesignPattern.factorypattern.method; /** * Description: 具体产品,hat */ public class HatProduct implements Product { public void methodDiff(){ System.out.println("我是hat,我关心你是谁,因为不要随便戴绿帽子"); } }
抽象工厂(工厂是干什么的?工厂就是生产产品的,简单工厂模式是一个工厂生产所有产品,而工厂方法模式,是每种产品由独立的工厂来生产,而所有的工厂都要实现抽象工厂)
package com.gxl.demo.DesignPattern.factorypattern.method; /** * Description: 抽象工厂 */ public interface Factory { Product createFactory(); }
具体工厂,生产shirt的工厂
package com.gxl.demo.DesignPattern.factorypattern.method; /** * Description: 具体工厂 */ public class ShirtFactory implements Factory{ //创建具体工厂 public Product createFactory(){ Product product = new ShirtProduct(); return product; } }
具体工厂,生产hat的工厂
package com.gxl.demo.DesignPattern.factorypattern.method; /** * Description: 具体工厂,hat */ public class HatFactory implements Factory { public Product createFactory() { Product product = new HatProduct(); return product; } }
客户端,使用具体的工厂生产产品
package com.gxl.demo.DesignPattern.factorypattern.method; /** * Description: 客户端 */ public class Client { public static void main(String[] args) { Factory factory = null; Product product = null; factory = new HatFactory(); product = factory.createFactory(); product.methodDiff(); } }
工厂方法模式总结
工厂方法模式有效的解决了简单工厂模式扩展的问题,但是由于工厂方法模式每生产一种产品就要建立一个工厂,导致工厂过多,也不是一种很完美的办法,这个就要留给抽象工厂模式来解决了。
抽象工厂模式
为了解决工厂方法模式工厂过多的问题,考虑将一些相关的产品组成一个“产品族”,用一个工厂来生产,举个例子,比如产品有电视,空调,洗衣机,品牌有海尔,美的,格力,那属于海尔的电视,空调,洗衣机就构成一组产品族用一个工厂来生产,这样就可以大大减少工厂的数量。同样下面通过一个例子来说明。
抽象产品,hat
package com.gxl.demo.DesignPattern.factorypattern.abstractfactory; /** * @Description 抽象商品 */ public interface Hat { public void methodDiff(); }
抽象产品,shirt
package com.gxl.demo.DesignPattern.factorypattern.abstractfactory; /** * Description:抽象产品 */ public interface Shirt { public void methodDiff(); }
具体产品,夏季戴的hat
package com.gxl.demo.DesignPattern.factorypattern.abstractfactory; /** * Description: 夏天帽子,具体产品 */ public class SummerHat implements Hat { public void methodDiff(){ System.out.println("我是夏天的帽子,我们只生产绿色的哦"); } }
具体产品,冬天戴的hat
package com.gxl.demo.DesignPattern.factorypattern.abstractfactory; /** * Description: 冬天帽子,具体产品 */ public class WinterHat implements Hat { public void methodDiff(){ System.out.println("我是冬天的帽子,我们只生产绿色的哦"); } }
具体产品,夏天穿的shirt
package com.gxl.demo.DesignPattern.factorypattern.abstractfactory; /** * Description: 夏天shirt,具体产品 */ public class SummerShirt implements Shirt { public void methodDiff(){ System.out.println("我是夏天的shirt,我是纯棉的"); } }
具体产品,冬天穿的shirt
package com.gxl.demo.DesignPattern.factorypattern.abstractfactory; /** * Description: 冬天shirt,具体产品 */ public class WinterShirt implements Shirt { public void methodDiff(){ System.out.println("我是冬天的shirt,我是纯羊毛的"); } }
抽象工厂
package com.gxl.demo.DesignPattern.factorypattern.abstractfactory; /** * @Desciption 抽象工厂 */ public interface Factory { Hat createHatFactory(); Shirt createShirtFactory(); }
具体工厂,生产夏季服装的工厂
package com.gxl.demo.DesignPattern.factorypattern.abstractfactory; /** * Description: 生产夏天服装,具体工厂 */ public class SummerFactory implements Factory { public Hat createHatFactory() { Hat summerHat = new SummerHat(); return summerHat; } public Shirt createShirtFactory() { Shirt summerShirt = new SummerShirt(); return summerShirt; } }
具体工厂,生产冬天服装的工厂
package com.gxl.demo.DesignPattern.factorypattern.abstractfactory; /** * Description: 生产动机服装,具体工厂 */ public class WinterFactory implements Factory { public Hat createHatFactory(){ Hat winterHat = new WinterHat(); return winterHat; } public Shirt createShirtFactory(){ Shirt wintereShirt = new WinterShirt(); return wintereShirt; } }
客户端
package com.gxl.demo.DesignPattern.factorypattern.abstractfactory; /** * Description: 客户端 */ public class Client { public static void main(String[] args) { Factory factory = null; Hat hat = null; Shirt shirt = null; factory = new SummerFactory(); hat = factory.createHatFactory(); shirt = factory.createShirtFactory(); hat.methodDiff(); shirt.methodDiff(); } }
抽象工厂模式总结
抽象工厂模式虽然解决了工厂方法模式工厂过多的问题,而且如果需要扩展一个产品族,也可以很容易在不修改原来的代码的基础上新增产品族(这个就是满足开闭原则),但是原来的产品族如果需要新增产品时就不行了,就需要修改原来的代码,举个例子,上面的代码中生产夏季服装的工厂只生产帽子和衬衫,但是如果我想生产裤子,不好意思,只能修改原来的工厂。这就是开闭原则的“倾斜性”,也是抽象工厂模式的最大的缺点。