设计模式——创建型——简单工厂模式、工厂模式、抽象工厂模式
简单工厂模式
简单工厂模式把对象的创建和使用分离,使用者只关心产品的类型,而不需要知道产品创建的细节,用于产品类型较少且不经常变化,或是使用者不关心创建对象过程的情况
优点
封装好、拓展好、符合单一职责
缺点
违反开闭原则,工厂类职责负担较重
总结
本质可以看做是三个类,分别是:
-
一个产品接口类
-
一个产品具体实现类
-
一个工厂类
产品接口类负责定义产品接口,还可以声明产品的通用功能。
具体实现类需要继承产品接口类,并且实现其声明的全部方法,也可以增加自己独有的方法。
工厂类实际上是一个普通的类,类内有一个创建产品的方法,返回的类型是抽象接口类,这个方法可以接受一个参数,以此来确定调用哪个实现类。
例子
// 产品接口
public interface Product {
void show();
}
// 具体产品类
// --具体产品类 B
public class ConcreteProductB implements Product {
@Override
public void show() {
System.out.println("Concrete Product B");
}
}
// --具体产品类 C
public class ConcreteProductC implements Product {
@Override
public void show() {
System.out.println("Concrete Product C");
}
}
// 工厂类
public class Factory {
public Product createProduct(String type) {
if ("B".equals(type)) {
return new ConcreteProductB();
} else if ("C".equals(type)) {
return new ConcreteProductC();
} else {
throw new IllegalArgumentException("Invalid product type.");
}
}
}
// 调用
public class Main {
public static void main(String[] args) {
Factory factory = new Factory();
Product productB = factory.createProduct("B");
productB.show();
Product productC = factory.createProduct("C");
productC.show();
}
}
工厂模式
把对象的创建和使用分离,比起简单工厂模式,工厂模式多了一个工厂接口类,需要多一个工厂实现类去具体实现对象的创建,同样的,使用者也不需要关心对象的创建细节,工厂模式是为了解决简单工厂模式违反的开闭原则
优点
- 用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名
- 工厂接口可以多态
- 符合开闭原则
缺点
- 添加新产品,可能会带来额外的系统开销(每个新产品都要增加一个工厂类,可能会比较臃肿)
- 有可能需要引入抽象层,增加实现难度
总结
简单工厂的加强版,本质可以分为四个类:
- 一个产品接口类
- 一个产品具体实现类
- 一个工厂接口类
- 一个工厂具体实现类
产品接口类负责定义产品接口,还可以声明产品的通用功能。
产品具体实现类需要继承产品接口类,并且实现其声明的全部方法,也可以增加自己独有的方法。
工厂接口类是为了解决简单工厂模式导致的不符合开闭原则的问题,也可以声明工厂类的通用方法或者使用重载来提高系统的灵活性。
工厂具体实现类继承工厂接口类,并返回对应的对象给调用者。
例子
// 产品接口类
public interface Shape {
void draw();
}
// 具体产品实现类
public class Circle implements Shape {
public void draw() {
System.out.println("Circle.draw()");
}
}
public class Rectangle implements Shape {
public void draw() {
System.out.println("Rectangle.draw()");
}
}
// 工厂接口类
public interface ShapeFactory {
Shape createShape();
}
// 工厂接口实现类
public class CircleFactory implements ShapeFactory {
public Shape createShape() {
return new Circle();
}
}
public class RectangleFactory implements ShapeFactory {
public Shape createShape() {
return new Rectangle();
}
}
// 使用
public class Client {
public static void main(String[] args) {
ShapeFactory circleFactory = new CircleFactory();
Shape circle = circleFactory.createShape();
circle.draw();
ShapeFactory rectangleFactory = new RectangleFactory();
Shape rectangle = rectangleFactory.createShape();
rectangle.draw();
}
}
抽象工厂模式
抽象工厂模式主要解决工厂模式在大量产品的情况下,同时存在大量的具体工厂类而导致高系统开销的问题
为了更好理解,引入产品等级结构
和产品族
这两个概念。
①产品等级结构:换个说法就是产品的继承结构
,例如一个电视机抽象类,子类有A,B,C,这里电视机类是父类,A,B,C是其子类。如下图的正方形、圆形和椭圆形。
②产品族:例如A工厂生成A电视机,A电脑,A洗衣机;A电视机和A电脑和A洗衣机就构成了一个产品族。
如此依赖,就可以大大减少了具体工厂实现类的数目,减少了开销。
优点
封装好、拓展好、符合单一职责
缺点
违反开闭原则,工厂类职责负担较重
总结
依我的理解,抽象工厂模式本质也是四个类,分别是:
- 产品接口类
- 产品具体实现类
- 工厂接口类
- 工厂具体实现类
1和2这两个类同工厂模式中的描述是一致的
工厂接口类的声明的工厂方法数和对应产品接口类的声明的产品数是基本一致的,从下面的例子可以看出。
具体工厂类中主要以产品族作为一个实现方法。
例子
// 产品接口
interface Television {
void play();
}
interface AirConditioner {
void cool();
}
// 具体产品类
class SonyTelevision implements Television {
public void play() {
System.out.println("Sony TV playing");
}
}
class LGTelevision implements Television {
public void play() {
System.out.println("LG TV playing");
}
}
class SonyAirConditioner implements AirConditioner {
public void cool() {
System.out.println("Sony AC cooling");
}
}
class LGAirConditioner implements AirConditioner {
public void cool() {
System.out.println("LG AC cooling");
}
}
// 抽象工厂接口
interface ElectronicFactory {
Television createTelevision();
AirConditioner createAirConditioner();
}
// 具体工厂类
class SonyFactory implements ElectronicFactory {
public Television createTelevision() {
return new SonyTelevision();
}
public AirConditioner createAirConditioner() {
return new SonyAirConditioner();
}
}
class LGFactory implements ElectronicFactory {
public Television createTelevision() {
return new LGTelevision();
}
public AirConditioner createAirConditioner() {
return new LGAirConditioner();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ElectronicFactory sonyFactory = new SonyFactory();
Television sonyTV = sonyFactory.createTelevision();
AirConditioner sonyAC = sonyFactory.createAirConditioner();
sonyTV.play();
sonyAC.cool();
ElectronicFactory lgFactory = new LGFactory();
Television lgTV = lgFactory.createTelevision();
AirConditioner lgAC = lgFactory.createAirConditioner();
lgTV.play();
lgAC.cool();
}
}