Java 中的基本设计模式
设计模式是针对常见软件设计问题的可复用解决方案。它们提供了一种以一致且高效的方式组织和构建代码的方法。一些常见的设计模式包括:
- 工厂模式是一种创建型设计模式,它为在超类中创建对象提供了一个接口,但允许子类改变要创建的对象的类型。
- 抽象工厂模式是一种创建型设计模式,它提供了一个接口,用于创建相关或依赖的对象族,而无需指定它们的具体类。
- 建造者模式是一种创建型设计模式,它将复杂对象的构建与其表示形式分离,从而允许相同的构建过程创建不同的表示形式。
- 策略模式是一种行为设计模式,它允许在运行时选择算法的行为。
- 装饰器模式是一种结构设计模式,它允许向单个对象添加行为(无论是静态的还是动态的),而不会影响同一类中其他对象的行为。
- 单例模式是一种创建型设计模式,它确保一个类只有一个实例,同时提供对该实例的全局访问点。
- 观察者模式是一种行为设计模式,它允许一个对象(主体)在其状态发生变化时通知其他对象(观察者)。
这些模式很有用,因为它们为开发人员提供了一种通用语言,可以使代码更易于维护和理解。
下面列举了 6 种最常用的设计模式,并附有 Java 示例。
工厂模式
工厂模式是一种创建型设计模式,它提供了一种无需指定要创建的对象的具体类即可创建对象的方法。它允许一个类将创建对象的责任委托给其子类。
以下是如何在 Java 中实现工厂模式的示例:
interface Shape {
void draw();
}
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
class Square implements Shape {
@Override
public void draw() {
System.out.println("Drawing a square");
}
}
class ShapeFactory {
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;
}
}
在上面的例子中,ShapeFactory类是一个工厂类,它根据客户端提供的输入创建不同具体类(Rectangle和Square)的对象。客户端使用工厂类来创建对象,无需知道将要创建的对象的具体类。
以下是一个客户端代码如何使用工厂模式创建对象的示例:
ShapeFactory shapeFactory = new ShapeFactory();
//get an object of Rectangle and call its draw method.
Shape shape1 = shapeFactory.getShape("RECTANGLE");
//call draw method of Rectangle
shape1.draw();
//get an object of Square and call its draw method.
Shape shape2 = shapeFactory.getShape("SQUARE");
//call draw method of square
shape2.draw();
在这个例子中,客户端可以通过向工厂类提供不同的输入来创建不同形状的对象,而无需知道将要创建的对象的具体类。这提高了代码的灵活性,并且使得在不修改现有代码的情况下添加新类变得更加容易。
构建器模式
建造者模式是一种创建型设计模式,它允许以清晰有序的方式逐步构建复杂对象。它将对象的构建与其表示分离,从而更容易在不影响客户端代码的情况下更改对象的内部表示。
以下是如何在 Java 中实现建造者模式的示例:
class Computer {
private String CPU;
private String RAM;
private String GPU;
private String storage;
private Computer(ComputerBuilder builder) {
this.CPU = builder.CPU;
this.RAM = builder.RAM;
this.GPU = builder.GPU;
this.storage = builder.storage;
}
public String getCPU() {
return CPU;
}
public String getRAM() {
return RAM;
}
public String getGPU() {
return GPU;
}
public String getStorage() {
return storage;
}
public static class ComputerBuilder {
private String CPU;
private String RAM;
private String GPU;
private String storage;
public ComputerBuilder setCPU(String CPU) {
this.CPU = CPU;
return this;
}
public ComputerBuilder setRAM(String RAM) {
this.RAM = RAM;
return this;
}
public ComputerBuilder setGPU(String GPU) {
this.GPU = GPU;
return this;
}
public ComputerBuilder setStorage(String storage) {
this.storage = storage;
return this;
}
public Computer build() {
return new Computer(this);
}
}
}
在这个例子中,Computer类代表正在构建的复杂对象,而ComputerBuilder类是构建器类,它逐步构建Computer对象。ComputerBuilder类为Computer类中的每个字段都提供了 setter 方法,还有一个build()方法,用于返回已构建的Computer对象。
以下示例展示了客户端代码如何使用建造者模式创建Computer对象:
Computer computer = new Computer.ComputerBuilder()
.setCPU("i7")
.setRAM("16GB")
.setGPU("GTX 1080")
.setStorage("1TB")
.build();
在这个例子中,客户端可以使用构建器类,通过逐步为每个字段提供不同的值来创建一个Computer对象。这使得代码更易读、更易理解,因为客户端无需关心Computer对象的内部实现。
策略设计模式
策略模式是一种行为设计模式,它允许在运行时选择算法。它定义了一系列算法,封装了每个算法,并使它们可以互换。这使得算法可以独立于使用它的客户端而变化。
以下是如何在 Java 中实现策略模式的示例:
interface PaymentStrategy {
void pay(int amount);
}
class CreditCardStrategy implements PaymentStrategy {
private String name;
private String cardNumber;
private String cvv;
private String dateOfExpiry;
public CreditCardStrategy(String nm, String ccNum, String cvv, String expiryDate){
this.name=nm;
this.cardNumber=ccNum;
this.cvv=cvv;
this.dateOfExpiry=expiryDate;
}
@Override
public void pay(int amount) {
System.out.println(amount + " paid with credit/debit card");
}
}
class PayPalStrategy implements PaymentStrategy {
private String emailId;
private String password;
public PayPalStrategy(String email, String pwd){
this.emailId=email;
this.password=pwd;
}
@Override
public void pay(int amount) {
System.out.println(amount + " paid using PayPal.");
}
}
class ShoppingCart {
List<Item> items;
PaymentStrategy paymentStrategy;
public ShoppingCart(){
this.items=new ArrayList<Item>();
}
public void addItem(Item item){
this.items.add(item);
}
public void removeItem(Item item){
this.items.remove(item);
}
public int calculateTotal(){
int sum = 0;
for(Item item : items){
sum += item.getPrice();
}
return sum;
}
public void pay(){
int amount = calculateTotal();
paymentStrategy.pay(amount);
}
public void setPaymentStrategy(PaymentStrategy paymentMethod){
this.paymentStrategy=paymentMethod;
}
}
在这个例子中,PaymentStrategy接口定义了用于支付的支付方式。CreditCardStrategy和PayPalStrategy类是该接口的具体实现,它们提供了不同的支付方式(例如使用信用卡/借记卡或 PayPal)。ShoppingCart类是使用PaymentStrategy接口进行支付的客户端。ShoppingCart 类可以使用setPaymentStrategy方法在运行时设置支付策略。
以下是客户端代码如何使用策略模式的示例:
ShoppingCart cart = new ShoppingCart();
cart.addItem(new Item("item1", 100));
cart.addItem(new Item("item2", 50));
// Selecting the CreditCardStrategy
cart.setPaymentStrategy(new CreditCardStrategy("John Doe","1234567890123456", "123", "12/2022"));
cart.pay();
// Selecting the PayPalStrategy
cart.setPaymentStrategy(new PayPalStrategy("test@example.com", "password"));
cart.pay();
在这个例子中,客户端创建了一个ShoppingCart类的实例,并向其中添加了一些商品。然后,客户端使用ShoppingCart对象的setPaymentStrategy方法设置支付策略。由于可以在运行时进行此操作,因此客户端可以根据需要切换不同的支付策略。最后,客户端调用 ShoppingCart对象的 pay() 方法,使用所选的支付策略完成付款。
在这个例子中,客户端代码可以在信用卡和PayPal支付方式之间切换,但它也可以包含其他类型的支付方式,例如银行转账等。使用这种模式,客户端代码无需关心每种支付方式的细节,它只需要知道通用的PaymentStrategy接口以及实现该接口的具体类能够进行支付即可。
装饰图案
装饰器模式是一种结构化设计模式,它允许动态地向单个对象添加行为,可以通过使用装饰器对象包装对象,也可以通过扩展对象来添加额外的功能。装饰器模式有助于创建灵活且可重用的代码。
以下是如何在 Java 中实现装饰器模式的示例:
interface Shape {
void draw();
}
class Circle implements Shape {
public void draw() {
System.out.println("Drawing Circle");
}
}
abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
public void draw(){
decoratedShape.draw();
}
}
class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape){
System.out.println("Border Color: Red");
}
}
在这个例子中,Shape接口定义了用于绘制形状的draw()方法。Circle类是该接口的具体实现,它提供了绘制圆的行为。ShapeDecorator是一个抽象类,它也实现了 Shape 接口,但它有一个额外的DecorativeShape属性,用于引用它所装饰的形状。RedShapeDecorator类是一个具体的装饰器,它会给被装饰的形状添加红色边框。
以下是客户端代码如何使用装饰器模式的示例:
Shape circle = new Circle();
Shape redCircle = new RedShapeDecorator(new Circle());
circle.draw();
redCircle.draw();
在这个例子中,客户端创建了一个Circle类的实例,然后创建了一个RedShapeDecorator类的实例,并将Circle实例作为参数传递给它。RedShapeDecorator类包装了Circle实例,并添加了绘制红色边框的额外行为。之后,客户端可以分别调用circle和redCircle对象的draw()方法, Circle类的行为将被RedShapeDecorator类提供的额外行为所修饰。
在这个例子中,我们使用装饰器模式为形状添加了红色边框,但您也可以使用此模式为被装饰对象添加或修改其他特性或行为。此模式的关键在于,客户端无需了解装饰器类,只需了解被装饰对象的接口即可。
单例模式
单例模式是一种创建型设计模式,它确保一个类只有一个实例,同时提供一个全局访问该实例的入口点。单例模式适用于需要由类的单个实例在整个执行过程中控制操作的情况。
以下是如何在 Java 中实现单例模式的示例:
class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
public void doSomething() {
// some code
}
}
在这个例子中,Singleton类有一个私有构造函数,这意味着该类不能从类外部实例化。该类还有一个静态实例属性,用于保存该类的唯一实例。getInstance ()方法用于获取该类的唯一实例,并且它使用延迟初始化,仅在首次需要时才创建实例。
以下是客户端代码如何使用单例模式的示例:
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
System.out.println(singleton1 == singleton2); // true
在这个例子中,客户端代码调用了两次`getInstance()`方法,但只获取到了Singleton类的一个实例。`==` 运算符用于比较这两个实例的引用,由于它们是同一个实例,因此返回 true。
单例模式在您希望确保一个类只被实例化一次,并且只有一个全局可访问的实例时非常有用。当您想要控制类的资源或实例数量,并希望强制执行单一控制点时,它也很有用。
需要注意的是,单例模式默认情况下并非线程安全。如果多个线程同时访问 ` getInstance()`方法,则可能会创建 `Singleton` 类的多个实例。要使单例模式线程安全,可以在`getInstance`方法上使用 `synchronized` 关键字,或者使用双重检查锁定模式。
观察者模式

观察者模式是一种行为设计模式,它允许一个对象(主体)在其状态发生变化时通知其他对象(观察者)。观察者模式适用于一个对象需要了解另一个对象状态变化,但这两个对象之间没有直接引用关系的情况。
以下是如何在 Java 中实现观察者模式的示例:
interface Observer {
void update(String message);
}
class ConcreteObserver implements Observer {
public void update(String message) {
System.out.println("Received message: " + message);
}
}
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private String message;
public void registerObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(message);
}
}
public void setMessage(String message) {
this.message = message;
notifyObservers();
}
}
在这个例子中,Observer接口定义了update()方法,该方法会在被观察者的状态发生变化时被调用。ConcreteObserver类是 Observer 接口的具体实现,它提供了处理更新的行为。
Subject接口定义了注册和移除观察者的方法,以及在主题状态改变时通知所有已注册观察者的方法。ConcreteSubject类是 Subject 接口的具体实现,它维护一个观察者列表,并提供注册和移除观察者的方法,以及在主题状态改变时通知所有已注册观察者的方法。
以下是客户端代码如何使用观察者模式的示例:
ConcreteSubject subject = new ConcreteSubject();
Observer observer = new ConcreteObserver();
subject.registerObserver(observer);
subject.setMessage("Hello World!");
在这个例子中,客户端代码创建了ConcreteSubject类的一个实例和一个ConcreteObserver类的一个实例。然后,使用registerObserver()方法将观察者注册到主题中。最后,客户端使用setMessage()方法设置主题的消息。
总之,设计模式是软件开发的重要组成部分,它们帮助开发人员解决常见问题,并使代码更易于维护、重用和扩展。理解和使用设计模式可以帮助开发人员编写更好、更高效的代码。需要注意的是,设计模式并非万能的解决方案,在应用特定模式之前,必须充分理解问题及其背景。
本文由人工智能辅助生成。
文章来源:https://dev.to/cliffsilla/essential-design-patterns-in-java-2pgd


