文章目录
工厂模式是一种创建型设计模式,它提供了一种创建对象的接口,但由子类决定要实例化的类是哪一个。工厂模式让一个类的实例化延迟到其子类。工厂模式主要分为三种: 简单工厂模式、 工厂方法模式 和 抽象工厂模式。
1. 简单工厂模式
简单工厂模式又称为静态工厂方法模式,它通过一个工厂类直接创建对象,而不需要将对象创建代码放到客户端。
//定义抽象产品角色
public interface Transport {
void travel();
}
// 定义具体产品角色
public class Car implements Transport {
@Override
public void travel() {
System.out.println("Driving a car...");
}
}
// 定义具体产品角色
public class Airplane implements Transport {
@Override
public void travel() {
System.out.println("Flying an airplane...");
}
}
//定义工厂角色
public class TransportFactory {
public static Transport createTransport(String type) {
if (type == null) {
return null;
} else if (type.equalsIgnoreCase("car")) {
return new Car();
} else if (type.equalsIgnoreCase("airplane")) {
return new Airplane();
} else {
throw new IllegalArgumentException("Unknown transport type: " + type);
}
}
}
//客户端代码
public class Client {
public static void main(String[] args) {
Transport car = TransportFactory.createTransport("car");
car.travel(); // 输出: Driving a car...
Transport airplane = TransportFactory.createTransport("airplane");
airplane.travel(); // 输出: Flying an airplane...
}
}
优点:
- 封装了创建对象的代码,使得客户端不需要直接实例化对象,降低了客户端代码的复杂度
- 通过一个工厂类来管理对象的创建,提高了代码的可维护性。
缺点:
2. 工厂方法模式
工厂方法模式定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类。
// 产品接口
public interface Shape {
void draw();
}
// 具体产品类:Circle
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a Circle...");
}
}
// 具体产品类:Rectangle
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a Rectangle...");
}
}
// 定义抽象工厂角色
public interface ShapeFactory {
Shape getShape();
}
// 具体工厂类:CircleFactory
class CircleFactory extends ShapeFactory {
@Override
Shape getShape() {
return new Circle();
}
}
// 具体工厂类:RectangleFactory
class RectangleFactory extends ShapeFactory {
@Override
Shape getShape() {
return new Rectangle();
}
}
// 客户端代码
public class FactoryMethodDemo {
public static void main(String[] args) {
// 获取 Circle 的工厂对象,通过工厂对象获取 Circle 对象,并调用它的 draw 方法
ShapeFactory circleFactory = new CircleFactory();
Shape circle = circleFactory.getShape();
circle.draw();
// 获取 Rectangle 的工厂对象,通过工厂对象获取 Rectangle 对象,并调用它的 draw 方法
ShapeFactory rectangleFactory = new RectangleFactory();
Shape rectangle = rectangleFactory.getShape();
rectangle.draw();
}
}
优点:
- 定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。这使得工厂方法模式将对象的实例化推迟到子类。
- 遵循了“单一职责原则”和“开闭原则”,因为每个工厂类只负责创建一种类型的产品,且新增产品时只需添加新的工厂类和产品类,无需修改已有代码。
缺点:
- 增加了类的数量,使得系统更加复杂。
- 当产品类具有较多共同行为时,需要在每个工厂类中重复这些行为,导致代码冗余。
3. 抽象工厂模式
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
// 抽象按钮接口
public interface Button {
void render();
}
// 抽象文本框接口
public interface TextField {
void displayText();
}
// Windows按钮实现
public class WindowsButton implements Button {
@Override
public void render() {
System.out.println("Rendering a Windows button...");
}
}
// Windows文本框实现
public class WindowsTextField implements TextField {
@Override
public void displayText() {
System.out.println("Displaying text in a Windows text field...");
}
}
// Mac按钮实现
public class MacButton implements Button {
@Override
public void render() {
System.out.println("Rendering a Mac button...");
}
}
// Mac文本框实现
public class MacTextField implements TextField {
@Override
public void displayText() {
System.out.println("Displaying text in a Mac text field...");
}
}
//定义抽象工厂角色
public interface GUIFactory {
Button createButton();
TextField createTextField();
}
// Windows工厂实现
public class WindowsFactory implements GUIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public TextField createTextField() {
return new WindowsTextField();
}
}
// Mac工厂实现
public class MacFactory implements GUIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public TextField createTextField() {
return new MacTextField();
}
}
public class Client {
public static void main(String[] args) {
// 使用Windows工厂创建对象
GUIFactory windowsFactory = new WindowsFactory();
Button windowsButton = windowsFactory.createButton();
windowsButton.render(); // 输出: Rendering a Windows button...
TextField windowsTextField = windowsFactory.createTextField();
windowsTextField.displayText(); // 输出: Displaying text in a Windows text field...
// 使用Mac工厂创建对象
GUIFactory macFactory = new MacFactory();
Button macButton = macFactory.createButton();
macButton.render(); // 输出: Rendering a Mac button...
TextField macTextField = macFactory.createTextField();
macTextField.displayText(); // 输出: Displaying text in a Mac text field...
}
}
优点:
- 提供了一个接口,用于创建相关或依赖对象的家族,而无需明确指定具体类。
- 增加了新的产品族时无需修改客户端代码,只需添加新的具体工厂和具体产品类。
- 提高了代码的灵活性和可维护性,因为客户端代码与具体产品类解耦。
缺点:
- 产品族难以扩展,因为一旦定义了抽象工厂接口,添加新产品族就需要修改该接口及其所有实现类。
- 增加了系统的复杂度,因为引入了更多的抽象层次和具体类。
设计模式七大原则
- 单一职责原则(Single Responsibility Principle):
- 定义:一个类只负责一个功能领域中的相应职责,或者可以定义为,就一个类而言,应该只有一个引起它变化的原因。
- 目的:降低类的复杂度,提高类的可读性、可维护性,降低变更引起的风险。
- 里氏替换原则(Liskov Substitution Principle, LSP):
- 定义:所有引用基类(父类)的地方必须能透明地使用其子类的对象。
- 目的:增强程序的健壮性,确保子类在扩展父类功能时不破坏父类的原有功能。
- 依赖倒置原则(Dependence Inversion Principle):
- 定义:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
- 目的:提高系统的稳定性,降低类间的耦合性,提高代码的可读性和可维护性。该原则要求面向接口编程,而不是面向实现编程。
- 接口隔离原则(Interface Segregation Principle, ISP):
- 定义:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
- 目的:提高系统的灵活性和可维护性,预防外来变更的扩散。该原则要求将臃肿庞大的接口分解为多个粒度小的接口。
- 迪米特原则(Law of Demeter, LOD):
- 定义:一个软件实体应当尽可能少地与其他实体发生相互作用,即只与你的直接朋友交谈,不跟“陌生人”说话。
- 目的:降低类之间的耦合度,提高模块的相对独立性。该原则要求一个对象只能与直接朋友发生交互。
- 开闭原则(Open/Closed Principle):
- 定义:一个软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
- 目的:使软件实体在不需要修改现有代码的情况下就可以进行扩展。该原则要求用抽象构建架构,用实现扩展功能。
- 合成复用原则(Composite Reuse Principle):
- 定义:尽量使用合成/聚合的方式,而不是使用继承来获得复用。
- 目的:通过组合多个简单对象来创建复杂对象,而不是通过继承关系来达到复用的目的。这样可以降低系统的复杂性,提高系统的灵活性和可扩展性。