2.2 工厂方法模式
2.2.1 定义
定义一个用于创建对象的接口,让子类决定实例化哪一个类。 遵循了开放—封闭原则。具体而言,核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂的角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
2.2.2 四个角色:
1. 抽象工厂:核心,与应用程序无关,任何在模式中创建的对象的工厂类都必须要实现这个接口
2. 具体工厂:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
3. 抽象对象:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
4. 具体对象:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
2.2.3 应用场景:
2.2.4 工厂模式 VS 简单工厂模式
共同优点:都集中封装了对象的创建,使得要更换对象时,不需要做很大的改动就可以实现,降低了客户端程序与产品对象的耦合
角色 | 实现原理 | 优点 | 缺点 | |
简单工厂模式 |
3个角色: 抽象类,具体类,工厂类 |
过一个工厂类,根据已有信息, 使得实例对象的创建在子类进行。 |
工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类, 对于客户端来说,去除了与具体产品的依赖。 |
没有遵守开放—封闭原则。 如果增加了一个新的产品类别,我们需要修改产品类,还需要修改工厂类。 |
工厂模式 |
4个角色: 抽象类、具体类、抽象工厂、具体工厂类 其中具体工厂类与具体类一一对应 |
定义一个抽象工厂接口, 让其子类决定实例化哪一个类 |
在简单工厂模式上进一步抽象, 遵循了“开放-关闭”原则 |
把简单工厂的内部逻辑判断转移到了客户端代码来执行; 每增加一产品就要增加一个产品工厂的类,增加了额外的开发量。 |
2.3 抽象工厂模式
2.3.1 原理:
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决的问题:接口选择问题。当系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
使用场景:
- QQ换皮肤,一整套一起换
- 生成不同操作系统的程序
2.3.2 优缺点:
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
2.3.3 实现:
我们将创建 Shape 和 Color 接口和实现这些接口的实体类。下一步是创建抽象工厂类 AbstractFactory。接着定义工厂类 ShapeFactory 和 ColorFactory,这两个工厂类都是扩展了 AbstractFactory。然后创建一个工厂创造器/生成器类 FactoryProducer。
AbstractFactoryPatternDemo,我们的演示类使用 FactoryProducer 来获取 AbstractFactory 对象。它将向 AbstractFactory 传递形状信息 Shape(CIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。同时它还向 AbstractFactory 传递颜色信息 Color(RED / GREEN / BLUE),以便获取它所需对象的类型。
1. 为形状创建一个接口
Shape.java
public interface Shape{ void draw(); }
2. 创建实现形状接口的实体类:Rectangle、Circle、Square
Rectangle.java
public class Rectangle implements Shape{ @override public void draw(){ System.out.println("Inside Rectangle :: draw() method.") } }
Circle.java
public class Circle implements Shape{ @override public void draw(){ System.out.println("Inside Circle :: draw() method.") } }
Square.java
public class Square implements Shape{ @override public void draw(){ System.out.println("Inside Square :: draw() method.") } }
3. 为颜色创建一个接口
Color.java
public interface Color{ void fill(); }
4. 创建实现颜色接口的实体类:Red、Green、Blue
Red.java
public class Red implements Color{ @override public voif fill(){ System.out.println("Inside Red :: fill() method.") } }
Green.java
public class Green implements Color{ @override public voif fill(){ System.out.println("Inside Green :: fill() method.") } }
Blue.java
public class Blue implements Color{ @override public voif fill(){ System.out.println("Inside Blue :: fill() method.") } }
5. 为Color、Shape对象创建抽象类来获取工厂
AbstractFactory
public abstract AbstractFactory{ abstract Color getColor(String Color); abstract Shape getShape(String Shape); }
6. 创建扩展AbstractFactory的工厂类,基于给定信息生成实体类的对象:ShapeFactory、ColorFactory
ShapeFactory.java
public class ShapeFactory extends AbstractFactory{ @override public 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 Color getColor(String color) { return null; } }
ColorFactory.java
public class ColorFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ return null; } @Override 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; } }
7. 创建一个工厂生成器类,通过传递形状或颜色信息来获取工厂。
FactoryProducer.java
public class FactoryProducer{ public static AbstractFactory getFactory(String choice){ if (choice.equalsIgnoreCase("Shape")) return new ShapeFactory(); else if (choice.equalsIgnoreCase("Colore")) return new ColorFactory; return null; }
8. 创建一个客户端测试类,使用FactoryProducer来创建工厂,通过传递类信息来获取实体类的对象
public class AbstractFactoryDemo{ public static void main(String[] args){ //使用FactoryProducer创建ShapeFactory AbstractFactory shapeFactory = FactoryProducer.getFactory("Shape"); //使用ShapeFactory来获取形状为Circle对象 Shape shapeCircle = shapeFactory.getShape("Circle"); //调用Circle对象的draw()方法 shapeCircle.draw(); //使用FactoryProducer创建ColorFactory AbstractFactory ColorFactory = FactoryProducer.getFactory("Color"); //使用ColorFactory创建Red实例对象 Color colorRed = ColorFactory.getColor("red"); //调用Red实例对象的fill()方法 colorRed.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.