设计模式-工厂设计模式
背景:
在Java中,万物皆对象。要想使用这些对象,就需要创建它,如果在使用该对象的类中都采用new方式创建该对象,会严重耦合,假如要更换对象,所以new该对象的地方都要做修改,这违背了软件的开闭设计原则。
如果使用工厂来生产对象,就只和工厂打交道了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦
工厂设计模式解决的问题:
在系统重构或增加产品时类的建立,如果类的建立放在主逻辑中。会导致修改工作量大而且在分工合作时代码结构化变差、书写难度增加、代码通用性变差
工厂设计模式属于创建型设计模式中的一种,他提供了创建对象的最佳方式。
简单工厂案例:
先将产品类抽象出来,比如,苹果和梨都属于水果,抽象出来一个水果类Fruit,苹果和梨就是具体的产品类,然后创建一个水果工厂,分别用来创建苹果和梨;代码如下:
水果接口
public interface IFruit { void get(); }
苹果
public class Apple implements IFruit { @Override public void get() { System.out.println(“apple”); } }
梨
public class Pear implements Fruit { @Override public void get() { System.out.println(“pear”); } }
水果工厂
public class FruitFactory { public Fruit createFruit(String type) { if (type.equals("apple")) {//生产苹果 return new Apple(); } else if (type.equals("pear")) {//生产梨 return new Pear(); } return null; } }
使用:
FruitFactory factory = new FruitFactory(); Apple apple = (Apple) factory.createFruit("apple");//获得苹果 Pear pear = (Pear) factory.createFruit("pear");//获得梨
一个非常简单的工厂设计模式就完成了。
那么问题来了,我想吃桃子、香蕉,我还想吃其他的水果,那不是都得创建桃子、香蕉、等等其他水果实现IFruit接口,然后在FruitFactory的createFruit修改添加创建桃子、香蕉等代码。显然,每当需要添加一种水果的时候,就需要修改工厂类,这显然违背了开闭原则。
所以简单工厂只适合于产品对象较少,且产品固定的需求,对于产品变化无常的需求来说显然不合适。
工厂方法设计模式:
将工厂提取成一个接口或抽象类,具体生产什么产品由子类决定
工厂接口
public interface FruitFactory { Fruit createFruit();//生产水果 }
苹果工厂
public class AppleFactory implements FruitFactory { @Override public Fruit createFruit() { return new Apple(); } }
梨工厂
public class PearFactory implements FruitFactory { @Override public Fruit createFruit() { return new Pear(); } }
使用
AppleFactory appleFactory = new AppleFactory();//创建苹果工厂 PearFactory pearFactory = new PearFactory();//创建梨工厂 Apple apple = (Apple) appleFactory.createFruit();//获得苹果 Pear pear = (Pear) pearFactory.createFruit();//获得梨
以上这种方式,虽然解耦了,也遵循了开闭原则,问题根本还是没有解决,如果需要的产品很多的话,需要创建非常多的工厂,所以这种方式的缺点也很明显
抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象

代码实现:
1)为形状创建一个接口 Shape.java public interface Shape { void draw(); } 2)创建具体形状类,实现形状接口 Rectangle.java public class Rectangle implements Shape { @Override public void draw() { System.out.println("Rectangle"); } } Square.java public class Square implements Shape { @Override public void draw() { System.out.println("Square "); } } 3)为颜色创建一个接口 Color.java public interface Color{ void fill(); } 4)创建具体颜色类,实现颜色接口 Red.java public class Red implements Color{ @Override public void fill() { System.out.println("Red"); } } Blue.java public class Blueimplements Color{ @Override public void fill() { System.out.println("Blue"); } } 5)为 Color 和 Shape 对象创建抽象类来获取工厂 AbstractFactory.java public abstract class AbstractFactory { public abstract Color getColor(String color); public abstract Shape getShape(String shape) ; } 6)创建Color和Shape 对应的工厂,都集成AbstractFactory //ShapeFactory生产shape public class ShapeFactory extends AbstractFactory{ @Override public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } @Override public Color getColor(String color) { return null; } } //ColorFactory生产color public class ColorFactory extends AbstractFactory{ @Override public Shape getShape(String shapeType){ return null; } @Override public Color getColor(String color) { if(color == null){ return null; } if(color.equalsIgnoreCase("RED")){ return new Red(); }else if(color.equalsIgnoreCase("BLUE")){ return new Blue(); } return null; } } 7)创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂 public class FactoryProducer { public static AbstractFactory getFactory(String choice){ if(choice.equalsIgnoreCase("SHAPE")){ return new ShapeFactory(); } else if(choice.equalsIgnoreCase("COLOR")){ return new ColorFactory(); } return null; } } 8)使用 FactoryProducer 来获取 AbstractFactory,通过传递类型信息来获取实体类的对象 public class AbstractFactoryPatternDemo { public static void main(String[] args) { //获取形状工厂 AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE"); //获取形状为 Square的对象 Shape shape1 = shapeFactory.getShape("SQUARE"); //调用 Square的 draw 方法 shape1.draw(); //获取形状为 Rectangle 的对象 Shape shape2 = shapeFactory.getShape("RECTANGLE"); //调用 Rectangle 的 draw 方法 shape2.draw(); //获取颜色工厂 AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR"); //获取颜色为 Red 的对象 Color color1 = colorFactory.getColor("RED"); //调用 Red 的 fill 方法 color1.fill(); //获取颜色为 Blue 的对象 Color color2 = colorFactory.getColor("BLUE"); //调用 Green 的 fill 方法 color2.fill(); } }
三种工厂方式总结:
1、对于简单工厂和工厂方法来说,两者的使用方式实际上是一样的,如果对于产品的分类和名称是确定的,数量是相对固定的,推荐使用简单工厂模式;
2、抽象工厂用来解决相对复杂的问题,适用于一系列、大批量的对象生产;