又叫做静态工厂方法模式,但不属于23种GOF设计模式之一。
意图:由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类 优点:我们可以对创建的对象进行一些 “加工” ,而且客户端并不知道,因为工厂隐藏了这些细节。如果,没有工厂的话,那我们是不是就得自己在客户端上写这些代码,这就好比本来可以在工厂里生产的东西,拿来自己手工制作,不仅麻烦以后还不好维护。 缺点:如果需要在方法里写很多与对象创建有关的业务代码,而且需要的创建的对象还不少的话,我们要在这个简单工厂类里编写很多个方法,每个方法里都得写很多相应的业务代码,而每次增加子类或者删除子类对象的创建都需要打开这简单工厂类来进行修改。这会导致这个简单工厂类很庞大臃肿、耦合性高,而且增加、删除某个子类对象的创建都需要打开简单工厂类来进行修改代码也违反了开-闭原则。 使用场景:
javaWeb用于Servlet抽取数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。创建一个接口: Car.java
public interface Car { void run(); }创建实现接口的实体类。 BMWCar.java
public class BMWCar implements Car{ @Override public void run() { // TODO Auto-generated method stub System.out.println("bmw car running..."); } }BenChiCar.java
public class BenChiCar implements Car{ @Override public void run() { // TODO Auto-generated method stub System.out.println("benchi car running"); } }DaZhongCar.java
public class DaZhongCar implements Car{ @Override public void run() { // TODO Auto-generated method stub System.out.println("dazhong car running..."); } }创建一个工厂,生成基于给定信息的实体类的对象。 CarFactory.java
public class CarFactory { public Car getCar(String carName) { Car car = null; if(carName.equals("bmw")) { car = new BMWCar(); }else if(carName.equals("benchi")) { car = new BenChiCar(); }else if(carName.equals("dazhong")) { car = new DaZhongCar(); } return car; } }使用该工厂,通过传递类型信息来获取实体类的对象。 CarFactoryDemo.java
public class CarFactoryDemo { public static void main(String[] args) { CarFactory carFactory = new CarFactory(); Car bmw = carFactory.getCar("bmw"); Car benchi = carFactory.getCar("benchi"); Car dazhong = carFactory.getCar("dazhong"); bmw.run(); benchi.run(); dazhong.run(); } }执行程序,输出结果:
bmw car running benchi car running dazhong car running工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。 主要解决:主要解决接口选择的问题。 何时使用:我们明确地计划不同条件下创建不同实例时。 如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。 关键代码:创建过程在其子类执行。 优点:
一个调用者想创建一个对象,只要知道其名称就可以了。扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。屏蔽产品的具体实现,调用者只关心产品的接口。缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。可以采用下面抽象工厂解决
使用场景:
日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。Spring使用工厂模式可以通过BeanFactory或ApplicationContext创建bean对象。注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
我们将创建一个 Shape 接口和实现 Shape 接口的实体类。下一步是定义工厂类 ShapeFactory。
创建一个接口: Shape.java
public interface Shape { void draw(); }创建实现接口的实体类。 Rectangle.java
public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } }Square.java
public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } }Circle.java
public class Circle implements Shape { @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }创建一个工厂,生成基于给定信息的实体类的对象。 ShapeFactory.java
public class ShapeFactory { //使用 getShape 方法获取形状类型的对象 public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } }使用该工厂,通过传递类型信息来获取实体类的对象。 FactoryPatternDemo.java
public class FactoryPatternDemo { public static void main(String[] args) { ShapeFactory shapeFactory = new ShapeFactory(); //获取 Circle 的对象,并调用它的 draw 方法 Shape shape1 = shapeFactory.getShape("CIRCLE"); //调用 Circle 的 draw 方法 shape1.draw(); //获取 Rectangle 的对象,并调用它的 draw 方法 Shape shape2 = shapeFactory.getShape("RECTANGLE"); //调用 Rectangle 的 draw 方法 shape2.draw(); //获取 Square 的对象,并调用它的 draw 方法 Shape shape3 = shapeFactory.getShape("SQUARE"); //调用 Square 的 draw 方法 shape3.draw(); } }执行程序,输出结果:
Inside Circle::draw() method. Inside Rectangle::draw() method. Inside Square::draw() method.抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 主要解决:主要解决接口选择的问题。 何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。 如何解决:在一个产品族里面,定义多个产品。 关键代码:在一个工厂里聚合多个同类产品。 优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。 缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。 使用场景:
QQ 换皮肤,一整套一起换。生成不同操作系统的程序。注意事项:产品族难扩展,产品等级易扩展。
为形状创建一个接口。 Shape.java
public interface Shape { void draw(); }创建实现接口的实体类。 Rectangle.java
public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } }Square.java
public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } }Circle.java
public class Circle implements Shape { @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }为颜色创建一个接口。 Color.java
public interface Color { void fill(); }创建实现接口的实体类。 Red.java
public class Red implements Color { @Override public void fill() { System.out.println("Inside Red::fill() method."); } }Green.java
public class Green implements Color { @Override public void fill() { System.out.println("Inside Green::fill() method."); } }Blue.java
public class Blue implements Color { @Override public void fill() { System.out.println("Inside Blue::fill() method."); } }为 Color 和 Shape 对象创建抽象类来获取工厂。 AbstractFactory.java
public abstract class AbstractFactory { public abstract Color getColor(String color); public abstract Shape getShape(String shape) ; }创建扩展了 AbstractFactory 的工厂类,基于给定的信息生成实体类的对象。 ShapeFactory.java
public class ShapeFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else 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.java
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("GREEN")){ return new Green(); } else if(color.equalsIgnoreCase("BLUE")){ return new Blue(); } return null; } }创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂。 FactoryProducer.java
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; } }使用 FactoryProducer 来获取 AbstractFactory,通过传递类型信息来获取实体类的对象。 AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo { public static void main(String[] args) { //获取形状工厂 AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE"); //获取形状为 Circle 的对象 Shape shape1 = shapeFactory.getShape("CIRCLE"); //调用 Circle 的 draw 方法 shape1.draw(); //获取形状为 Rectangle 的对象 Shape shape2 = shapeFactory.getShape("RECTANGLE"); //调用 Rectangle 的 draw 方法 shape2.draw(); //获取形状为 Square 的对象 Shape shape3 = shapeFactory.getShape("SQUARE"); //调用 Square 的 draw 方法 shape3.draw(); //获取颜色工厂 AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR"); //获取颜色为 Red 的对象 Color color1 = colorFactory.getColor("RED"); //调用 Red 的 fill 方法 color1.fill(); //获取颜色为 Green 的对象 Color color2 = colorFactory.getColor("Green"); //调用 Green 的 fill 方法 color2.fill(); //获取颜色为 Blue 的对象 Color color3 = colorFactory.getColor("BLUE"); //调用 Blue 的 fill 方法 color3.fill(); } }执行程序,输出结果:
Inside Circle::draw() method. Inside Rectangle::draw() method. Inside Square::draw() method. Inside Red::fill() method. Inside Green::fill() method. Inside Blue::fill() method.抽象工厂模式也就是不仅生产鼠标,同时生产键盘。 也就是 PC 厂商是个父类,有生产鼠标,生产键盘两个接口。 戴尔工厂,惠普工厂继承它,可以分别生产戴尔鼠标+戴尔键盘,和惠普鼠标+惠普键盘。 创建工厂时,由戴尔工厂创建。 后续工厂.生产鼠标()则生产戴尔鼠标,工厂.生产键盘()则生产戴尔键盘。
在抽象工厂模式中,假设我们需要增加一个工厂
假设我们增加华硕工厂,则我们需要增加华硕工厂,和戴尔工厂一样,继承 PC 厂商。 之后创建华硕鼠标,继承鼠标类。创建华硕键盘,继承键盘类即可。
在抽象工厂模式中,假设我们需要增加一个产品
假设我们增加耳麦这个产品,则首先我们需要增加耳麦这个父类,再加上戴尔耳麦,惠普耳麦这两个子类。 之后在PC厂商这个父类中,增加生产耳麦的接口。最后在戴尔工厂,惠普工厂这两个类中,分别实现生产戴尔耳麦,惠普耳麦的功能。 以上。
