设计模式通常被分为三种类型:创建型模式、结构型模式和行为型模式。
创建型模式
创建型模式主要关注对象的创建机制,它们提供了一种将对象创建和实例化的机制,使得系统在不直接依赖于具体类的情况下能够灵活地创建对象。
创建型模式的典型代表包括工厂模式、抽象工厂模式、建造者模式、原型模式和单例模式。
单例模式
java">public class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}
工厂模式
java">interface Shape {void draw();
}class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Drawing a rectangle");}
}class Circle implements Shape {@Overridepublic void draw() {System.out.println("Drawing a circle");}
}class ShapeFactory {public static Shape getShape(String type) {if (type.equalsIgnoreCase("rectangle")) {return new Rectangle();} else if (type.equalsIgnoreCase("circle")) {return new Circle();}return null;}
}
结构型模式
结构型模式主要关注对象的组合和结构,它们描述了如何将类或对象按照某种方式组合成更大的结构,以满足系统的需求。
结构型模式的典型代表包括适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式和代理模式。
装饰者模式
装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许在运行时动态地将责任附加到对象上,同时不改变其接口。装饰者模式通过创建装饰者类,用来包装原始类的对象,并向其添加新的行为或责任,从而实现了对对象功能的动态扩展。
装饰者模式通常涉及以下几种角色:
-
Component(组件):组件是一个接口或抽象类,定义了被装饰者和装饰者共同的接口。它可以是一个抽象类,也可以是一个接口,用于定义被装饰者和装饰者共同的行为。
-
ConcreteComponent(具体组件):具体组件是实现了组件接口的具体类,它是被装饰者,负责提供基本的功能。
-
Decorator(装饰者):装饰者是一个抽象类,它实现了组件接口,并持有一个指向组件的引用。装饰者通常包含一个组件对象,用来装饰或包装真实的组件对象。
-
ConcreteDecorator(具体装饰者):具体装饰者是实现了装饰者接口的具体类,它负责向组件添加新的行为或责任。
装饰者模式的核心思想是通过嵌套具体装饰者对象来动态地扩展对象的功能,而不是通过继承来实现。这样可以避免继承导致的类爆炸问题,并且使得每个类的职责更加清晰,更易于维护和扩展。
下面是一个简单的装饰者模式的示例代码:
java">// 组件接口
interface Coffee {String getDescription();double getCost();
}// 具体组件
class Espresso implements Coffee {@Overridepublic String getDescription() {return "Espresso";}@Overridepublic double getCost() {return 1.99;}
}// 装饰者抽象类
abstract class CoffeeDecorator implements Coffee {protected Coffee decoratedCoffee;public CoffeeDecorator(Coffee decoratedCoffee) {this.decoratedCoffee = decoratedCoffee;}@Overridepublic String getDescription() {return decoratedCoffee.getDescription();}@Overridepublic double getCost() {return decoratedCoffee.getCost();}
}// 具体装饰者
class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee decoratedCoffee) {super(decoratedCoffee);}@Overridepublic String getDescription() {return super.getDescription() + ", Milk";}@Overridepublic double getCost() {return super.getCost() + 0.5;}
}class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee decoratedCoffee) {super(decoratedCoffee);}@Overridepublic String getDescription() {return super.getDescription() + ", Sugar";}@Overridepublic double getCost() {return super.getCost() + 0.2;}
}// 测试类
public class Test{public static void main(String[] args) {Coffee espresso = new Espresso();System.out.println("Description: " + espresso.getDescription());System.out.println("Cost: $" + espresso.getCost());Coffee milkCoffee = new MilkDecorator(espresso);System.out.println("Description: " + milkCoffee.getDescription());System.out.println("Cost: $" + milkCoffee.getCost());Coffee sugarMilkCoffee = new SugarDecorator(milkCoffee);System.out.println("Description: " + sugarMilkCoffee.getDescription());System.out.println("Cost: $" + sugarMilkCoffee.getCost());}
}
行为型模式
行为型模式主要关注对象之间的通信和交互,它们描述了对象之间的相互作用和协作方式,以实现系统中的功能。
行为型模式的典型代表包括责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。
观察者模式
观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象的状态发生变化时,所有依赖于它的观察者都会得到通知并自动更新。
这种模式主要涉及两种角色:
-
Subject(主题):也称为被观察者或可观察对象,它是一个具体类,负责维护一组观察者对象,并提供注册和删除观察者的接口,以及通知观察者的方法。
-
Observer(观察者):也称为订阅者或监听者,它是一个接口或抽象类,定义了一个更新的接口,以便在主题状态变化时接收通知。
观察者模式的优点包括:
- 松耦合:主题和观察者之间是松耦合的,主题只知道观察者实现了特定接口,而不需要了解其具体实现。
- 可重用性:可以在同一主题上添加或移除不同的观察者对象,而无需修改主题代码。
- 扩展性:可以轻松添加新的观察者以应对主题状态变化。
观察者模式的典型应用场景包括:
- GUI(图形用户界面)程序中的事件处理:例如按钮点击事件、鼠标移动事件等。
- 被观察者对象的状态变化需要通知多个观察者对象进行更新的情况。
下面是一个简单的观察者模式的示例代码:
java">import java.util.ArrayList;
import java.util.List;interface Observer {void update(String message);
}class Subject {private List<Observer> observers = new ArrayList<>();public void addObserver(Observer observer) {observers.add(observer);}public void notifyObservers(String message) {for (Observer observer : observers) {observer.update(message);}}
}class ConcreteObserver implements Observer {private String name;public ConcreteObserver(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + " received message: " + message);}
}// 测试类
public class Test{public static void main(String[] args) {// 创建一个主题对象Subject subject = new Subject();// 创建两个观察者对象Observer observer1 = new ConcreteObserver("Observer 1");Observer observer2 = new ConcreteObserver("Observer 2");// 注册观察者subject.addObserver(observer1);subject.addObserver(observer2);// 主题对象状态发生变化,通知观察者subject.notifyObservers("Hello, observers!");}
}
策略模式
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法(策略),并将每个算法封装到具有公共接口的独立类中,使得它们可以相互替换。策略模式使得算法可以独立于使用它们的客户端而变化,从而使得算法可以根据需要动态地切换、选择或替换。
策略模式主要涉及三种角色:
-
Context(上下文):上下文是客户端使用策略的入口,它持有一个策略对象,并在需要的时候调用策略对象的方法。上下文类通常会将请求委派给策略对象来执行具体的算法。
-
Strategy(策略):策略是一个接口或抽象类,它定义了一个算法族的共同接口。具体的策略类实现了这个接口,并实现了具体的算法。
-
ConcreteStrategy(具体策略):具体策略类实现了策略接口,并提供了具体的算法实现。每个具体策略类都代表了一个具体的算法,客户端可以根据需求选择不同的具体策略来执行相应的算法。
策略模式的优点包括:
- 可扩展性:新的策略可以很容易地添加到系统中,而不会影响现有的代码。
- 可维护性:每个具体策略类都相对独立,易于维护和修改。
- 松耦合:上下文类与具体策略类之间的耦合度较低,可以相互独立地变化。
下面是一个简单的策略模式的示例代码:
java">// 策略接口
interface Strategy {void execute();
}// 具体策略A
class ConcreteStrategyA implements Strategy {@Overridepublic void execute() {System.out.println("Executing strategy A");}
}// 具体策略B
class ConcreteStrategyB implements Strategy {@Overridepublic void execute() {System.out.println("Executing strategy B");}
}// 上下文类
class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public void setStrategy(Strategy strategy) {this.strategy = strategy;}public void executeStrategy() {strategy.execute();}
}// 测试类
public class Test{public static void main(String[] args) {// 创建具体策略对象Strategy strategyA = new ConcreteStrategyA();Strategy strategyB = new ConcreteStrategyB();// 创建上下文对象,并设置具体策略Context context = new Context(strategyA);// 执行具体策略context.executeStrategy();// 切换策略context.setStrategy(strategyB);context.executeStrategy();}
}
应用场景如,多种方式付款:
java">interface PaymentStrategy {void pay(int amount);
}class CreditCardStrategy implements PaymentStrategy {private String cardNumber;private String cvv;private String expirationDate;public CreditCardStrategy(String cardNumber, String cvv, String expirationDate) {this.cardNumber = cardNumber;this.cvv = cvv;this.expirationDate = expirationDate;}@Overridepublic void pay(int amount) {System.out.println("Paid " + amount + " using credit card.");}
}class ShoppingCart {private PaymentStrategy paymentStrategy;public void setPaymentStrategy(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}public void checkout(int amount) {paymentStrategy.pay(amount);}
}