设计模式(Design pattern) 是解决软件开发某些特定问题而提出的一些解决方案也可以理解成解决问题的一些思路。通过设计模式可以帮助我们增强代码的可重用性、可扩充性、 可维护性、灵活性好。我们使用设计模式最终的目的是实现代码的高内聚和低耦合。
23中设计模式的关系
定义一个用户创建对象的接口,但由子类决定实例化哪个类。
当一个类无法准确预知需要创建的对象的确切类时,将对象的创建延迟到子类。
// 抽象产品
interface Product {
void operation();
}
// 具体产品
class ConcreteProduct implements Product {
@Override
public void operation() {
System.out.println("具体产品的操作");
}
}
// 抽象工厂
interface Factory {
Product createProduct();
}
// 具体工厂
class ConcreteFactory implements Factory {
@Override
public Product createProduct() {
return new ConcreteProduct();
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Factory factory = new ConcreteFactory();
Product product = factory.createProduct();
product.operation();
}
}
提供一个创建相关或依赖接口的接口,而无需指定具体类。
当需要创建一些列相互关联或依赖的对象时,且不希望暴露它们的具体实现细节。
角色
1、抽象工厂(Creator)
是抽象工厂方法模式的核心角色,任何在模式中创建的对象的工厂类必须实现这此产品族接口;
2、具体工厂(Concrete Creator)
这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象;
3、抽象产品(Product)
所要创建的对象的基类,也就是产品对象的共同父类或共同拥有的接口;
// 抽象产品族
interface AbstractProductA {
void operationA();
}
// 具体产品族
class ConcreteProductA1 implements AbstractProductA {
@Override
public void operationA() {
System.out.println("具体产品A1的操作");
}
}
// 具体产品族
class ConcreteProductA2 implements AbstractProductA {
@Override
public void operationA() {
System.out.println("具体产品A2的操作");
}
}
// 抽象产品族
interface AbstractProductB {
void operationB();
}
// 具体产品族
class ConcreteProductB1 implements AbstractProductB {
@Override
public void operationB() {
System.out.println("具体产品B1的操作");
}
}
// 具体产品族
class ConcreteProductB2 implements AbstractProductB {
@Override
public void operationB() {
System.out.println("具体产品B2的操作");
}
}
// 抽象工厂
interface AbstractFactory {
AbstractProductA createProductA();
AbstractProductB createProductB();
}
// 具体工厂
class ConcreteFactory1 implements AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
}
// 具体工厂
class ConcreteFactory2 implements AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB2();
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
AbstractProductA productA1 = factory1.createProductA();
AbstractProductB productB1 = factory1.createProductB();
productA1.operationA();
productB1.operationB();
AbstractFactory factory2 = new ConcreteFactory2();
AbstractProductA productA2 = factory2.createProductA();
AbstractProductB productB2 = factory2.createProductB();
productA2.operationA();
productB2.operationB();
}
}
确保一个类只有一个实例,并提供对该例的全局访问点。
当需要确保一个类只有一个实例,并且需要全局访问该实例时。
class Singleton {
private static Singleton instance;
private Singleton() {
// 私有构造函数
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
public void operation() {
System.out.println("单例对象的操作");
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
singleton.operation();
}
}
将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
当需要创建复杂对象,并且希望通过一步一步的方式构建对象。
计算机是由 CPU、主板、内存、硬盘、显卡、机箱、显示器、键盘、鼠标等部件组装而成的,采购员不可能自己去组装计算机,而是将计算机的配置要求告诉计算机销售公司,计算机销售公司安排技术人员去组装计算机,然后再交给要买计算机的采购员。
特点:
建造者(Builder)模式的定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
class Product {
private String partA;
private String partB;
private String partC;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void setPartC(String partC) {
this.partC = partC;
}
public void operation() {
System.out.println("产品的操作");
}
}
interface Builder {
void buildPartA();
void buildPartB();
void buildPartC();
Product getResult();
}
class ConcreteBuilder implements Builder {
private Product product;
public ConcreteBuilder() {
this.product = new Product();
}
@Override
public void buildPartA() {
product.setPartA("部件A");
}
@Override
public void buildPartB() {
product.setPartB("部件B");
}
@Override
public void buildPartC() {
product.setPartC("部件C");
}
@Override
public Product getResult() {
return product;
}
}
class Director {
public void construct(Builder builder) {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director();
director.construct(builder);
Product product = builder.getResult();
product.operation();
}
}
用原型实例指定创建对象的种类,并且通过复制这个原型来创建新的对象。
当需要创建多个相似的对象,并且创建过程比较复杂或耗时时,可以使用原型模式。
一个图形绘制软件可以使用原型模式,通过复制已有的图形对象来创建新的图形对象,而无需重新创建和实例化对象。
import java.util.HashMap;
import java.util.Map;
// 抽象原型类
abstract class Shape implements Cloneable {
protected String type;
public abstract void draw();
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
// 具体原型类
class Circle extends Shape {
public Circle() {
type = "Circle";
}
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
class Rectangle extends Shape {
public Rectangle() {
type = "Rectangle";
}
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
// 原型管理器
class ShapeCache {
private static Map<String, Shape> shapeMap = new HashMap<>();
public static Shape getShape(String type) {
Shape shape = shapeMap.get(type);
return (Shape) shape.clone();
}
public static void loadCache() {
Circle circle = new Circle();
shapeMap.put(circle.type, circle);
Rectangle rectangle = new Rectangle();
shapeMap.put(rectangle.type, rectangle);
}
}
// 示例用法
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
ShapeCache.loadCache();
Shape clonedShape1 = ShapeCache.getShape("Circle");
clonedShape1.draw();
Shape clonedShape2 = ShapeCache.getShape("Rectangle");
clonedShape2.draw();
}
}
将一个类的接口转换成客户希望的另一个接口,使得原本不兼容的类可以一起工作。
当需要将一个类的接口转换成另一个类的接口时,可以使用适配器模式。
一个手机充电器可以使用适配器模式,将电源插头的接口转换成手机充电接口的接口,使得不同类型的电源可以连通给手机充电。
// 目标接口
interface Target {
void request();
}
// 需要适配的类
class Adaptee {
public void specificRequest() {
System.out.println("适配者类的特殊请求");
}
}
// 适配器类
class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest();
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target target = new Adapter(adaptee);
target.request();
}
}
将抽象部分与它的实现部分分离,使他们可以独立地变化。
当需要将抽象部分与实现部分分离,使他们可以独立地变化,可以使用桥接模式。
一个电视机可以使用桥接模式,将遥控器的抽象部分与电视机的实现部分分离,使他们可以独立地进行扩展。
// 实现部分的接口
interface Implementor {
void operationImpl();
}
// 具体实现部分A
class ConcreteImplementorA implements Implementor {
@Override
public void operationImpl() {
System.out.println("具体实现部分A的操作");
}
}
// 具体实现部分B
class ConcreteImplementorB implements Implementor {
@Override
public void operationImpl() {
System.out.println("具体实现部分B的操作");
}
}
// 抽象部分的接口
abstract class Abstraction {
protected Implementor implementor;
public Abstraction(Implementor implementor) {
this.implementor = implementor;
}
public abstract void operation();
}
// 扩展抽象部分的实现A
class RefinedAbstractionA extends Abstraction {
public RefinedAbstractionA(Implementor implementor) {
super(implementor);
}
@Override
public void operation() {
implementor.operationImpl();
System.out.println("扩展抽象部分A的操作");
}
}
// 扩展抽象部分的实现B
class RefinedAbstractionB extends Abstraction {
public RefinedAbstractionB(Implementor implementor) {
super(implementor);
}
@Override
public void operation() {
implementor.operationImpl();
System.out.println("扩展抽象部分B的操作");
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Implementor implementorA = new ConcreteImplementorA();
Abstraction abstractionA = new RefinedAbstractionA(implementorA);
abstractionA.operation();
Implementor implementorB = new ConcreteImplementorB();
Abstraction abstractionB = new RefinedAbstractionB(implementorB);
abstractionB.operation();
}
}
将对象组合成树形结构以表示“整体-部分”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
当需要表示对象的层次结构,并且希望用户可以一致地对待单个对象和组合对象时,可以使用组合模式。
一个文件系统可以使用组合模式,将文件和文件夹组合成树状结构,使得用户可以一致地对待文件和文件夹。
// 抽象构件
interface Component {
void operation();
}
// 叶子构件
class Leaf implements Component {
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void operation() {
System.out.println("叶子构件" + name + "的操作");
}
}
// 容器构件
class Composite implements Component {
private List<Component> components = new ArrayList<>();
public void add(Component component) {
components.add(component);
}
public void remove(Component component) {
components.remove(component);
}
@Override
public void operation() {
for (Component component : components) {
component.operation();
}
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Component leaf1 = new Leaf("Leaf 1");
Component leaf2 = new Leaf("Leaf 2");
Component composite1 = new Composite();
composite1.add(leaf1);
composite1.add(leaf2);
Component leaf3 = new Leaf("Leaf 3");
Component leaf4 = new Leaf("Leaf 4");
Component composite2 = new Composite();
composite2.add(leaf3);
composite2.add(leaf4);
Component composite3 = new Composite();
composite3.add(composite1);
composite3.add(composite2);
composite3.operation();
}
}
动态地给一个对象添加一些额外的职责,即在不改变其结构的情况下,对对象进行扩展。
当需要动态地给一个对象添加功能,并且希望这些功能可以动态组合时,可以使用装饰器模式。
一个咖啡店可以使用装饰器模式,将咖啡对象进行装饰,添加额外的配料(如牛奶、糖等)。
// 抽象组件
interface Component {
void operation();
}
// 具体组件
class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("具体组件的操作");
}
}
// 抽象装饰器
abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
// 具体装饰器A
class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("具体装饰器A的操作");
}
}
// 具体装饰器B
class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("具体装饰器B的操作");
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Component component = new ConcreteComponent();
Component decoratorA = new ConcreteDecoratorA(component);
Component decoratorB = new ConcreteDecoratorB(decoratorA);
decoratorB.operation();
}
}
提供了一个统一的接口,用于访问子系统中的一群接口,从而简化了客户端与子系统之间的交互。
当需要简化复杂子系统的接口,并提供一个统一的接口给客户端使用时,可以使用外观模式。
一个家庭影院系统可以使用外观模式,将各种设备(如投影仪、音响、DVD播放器等)的复杂操作封装在一个外观类中,提供一个简单的接口给用户操作整个家庭影院系统。
// 子系统类A
class SubsystemA {
public void operationA() {
System.out.println("子系统A的操作");
}
}
// 子系统类B
class SubsystemB {
public void operationB() {
System.out.println("子系统B的操作");
}
}
// 外观类
class Facade {
private SubsystemA subsystemA;
private SubsystemB subsystemB;
public Facade() {
this.subsystemA = new SubsystemA();
this.subsystemB = new SubsystemB();
}
public void operation() {
subsystemA.operationA();
subsystemB.operationB();
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Facade facade = new Facade();
facade.operation();
}
}
运用共享技术有效地支持大量细粒度的对象。
当需要创建大量相似对象,并且这些对象可以共享一些公共的状态时,可以使用享元模式。
享元模式(Flyweight Pattern)又称为轻量级模式,是对象池的一种实现.类似于线程池,线程池可以避免不停的创建和销毁多个对象,消耗性能.提供了减少对象数量从而改善应用所需的对象结构的方式.其宗旨是共享细粒度对象,将多个对同一对象的访问集中起来,不必为每个访问者创建一个单独的对象,从此来降低内存的消耗,属于结构型模式.
// 抽象享元类
interface Flyweight {
void operation();
}
// 具体享元类
class ConcreteFlyweight implements Flyweight {
private String intrinsicState;
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void operation() {
System.out.println("具体享元类的操作,内部状态为:" + intrinsicState);
}
}
// 享元工厂类
class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String key) {
if (flyweights.containsKey(key)) {
return flyweights.get(key);
} else {
Flyweight flyweight = new ConcreteFlyweight(key);
flyweights.put(key, flyweight);
return flyweight;
}
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
FlyweightFactory factory = new FlyweightFactory();
Flyweight flyweight1 = factory.getFlyweight("key1");
flyweight1.operation();
Flyweight flyweight2 = factory.getFlyweight("key2");
flyweight2.operation();
Flyweight flyweight3 = factory.getFlyweight("key1");
flyweight3.operation();
}
}
为其他对象提供一种代理以控制对这个对象的访问。
当需要控制对一个对象的访问,并且希望通过代理来实现对原始对象的访问时,可以使用代理模式。
一个网络代理服务器可以使用代理模式,代理服务器充当客户端和目标服务器之间的中间人,控制对目标服务器的访问。
// 抽象主题
interface Subject {
void request();
}
// 真实主题
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("真实主题的请求");
}
}
// 代理类
class Proxy implements Subject {
private RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void request() {
// 在调用真实主题之前可以执行一些操作
System.out.println("代理类的请求");
realSubject.request();
// 在调用真实主题之后可以执行一些操作
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Proxy proxy = new Proxy(realSubject);
proxy.request();
}
}
定义一个操作中的算法框架,将一些步骤延迟到子类中实现。
当有一系列算法步骤,其中一些步骤的实现可能不同,但整体框架是固定的时,可以使用模板方法模式。
假如你正在开发一款分析公司文档的数据挖掘程序。 用户需要向程序输入各种格式 (PDF、 DOC 或 CSV) 的文档, 程序则会试图从这些文件中抽取有意义的数据, 并以统一的格式将其返回给用户。
该程序的首个版本仅支持 DOC 文件。 在接下来的一个版本中, 程序能够支持 CSV 文件。 一个月后, 你 “教会” 了程序从 PDF 文件中抽取数据。
abstract class AbstractClass {
public void templateMethod() {
step1();
step2();
step3();
}
protected abstract void step1();
protected abstract void step2();
protected abstract void step3();
}
class ConcreteClass extends AbstractClass {
@Override
protected void step1() {
System.out.println("ConcreteClass step1");
}
@Override
protected void step2() {
System.out.println("ConcreteClass step2");
}
@Override
protected void step3() {
System.out.println("ConcreteClass step3");
}
}
public class Main {
public static void main(String[] args) {
AbstractClass abstractClass = new ConcreteClass();
abstractClass.templateMethod();
}
}
将请求封装成一个对象,从而可以用不同的请求对客户进行参数化。
当需要将请求发送者和接受者解耦,并且希望以队列方式执行请求时,可以使用命令模式。
假设有一个遥控器,这个遥控器可以控制各种家电设备,比如电视机、音响、灯光等等。每个家电设备都有自己的开关命令,而遥控器上的按钮就代表不同的命令对象。这样一来,用户只需要按下相应的按钮,就可以控制不同的家电设备,而无需关心具体的实现细节。
interface Command {
void execute();
}
class Receiver {
public void action() {
System.out.println("Receiver action");
}
}
class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
}
class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
command.execute();
}
}
public class Main {
public static void main(String[] args) {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.executeCommand();
}
}
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部表示。
当需要遍历一个聚合对象的元素,并且不希望暴露其内部表示时,可以使用迭代器模式。
简单来说,迭代器模式使得你能够获取到序列中的所有元素而不用关心是其类型是array,list,linked list或者是其他什么序列结构。这一点使得能够非常高效的构建数据处理通道(data pipeline)–即数据能够进入处理通道,进行一系列的变换,或者过滤,然后得到结果。事实上,这正是Linq的核心模式。
interface Iterator {
boolean hasNext();
Object next();
}
interface Aggregate {
Iterator createIterator();
}
class ConcreteIterator implements Iterator {
private Object[] elements;
private int position = 0;
public ConcreteIterator(Object[] elements) {
this.elements = elements;
}
@Override
public boolean hasNext() {
return position < elements.length;
}
@Override
public Object next() {
return elements[position++];
}
}
class ConcreteAggregate implements Aggregate {
private Object[] elements;
public ConcreteAggregate(Object[] elements) {
this.elements = elements;
}
@Override
public Iterator createIterator() {
return new ConcreteIterator(elements);
}
}
public class Main {
public static void main(String[] args) {
Object[] elements = { "Element 1", "Element 2", "Element 3" };
Aggregate aggregate = new ConcreteAggregate(elements);
Iterator iterator = aggregate.createIterator();
while (iterator.hasNext()) {
Object element = iterator.next();
System.out.println(element);
}
}
}
定义了一种1对多的依赖关系,使得当一个对象的状态发生变化时,其所有依赖对象都会收到通知并自动更新。
当一个对象的状态发生变化时,需要通知其他对象,并且对象之间的关系是一对多关系时,可以使用观察者模式。
一个新闻发布系统可以使用观察者模式,当有新闻发布时,订阅了该类新闻的观察者都会收到通知。
import java.util.ArrayList;
import java.util.List;
// 主题接口
interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObservers();
}
// 具体主题
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
public void setState(String state) {
this.state = state;
notifyObservers();
}
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
}
// 观察者接口
interface Observer {
void update(String state);
}
// 具体观察者
class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String state) {
System.out.println(name + " received state update: " + state);
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer observer1 = new ConcreteObserver("Observer 1");
Observer observer2 = new ConcreteObserver("Observer 2");
subject.attach(observer1);
subject.attach(observer2);
subject.setState("State 1");
subject.setState("State 2");
subject.detach(observer2);
subject.setState("State 3");
}
}
通过封装一系列对象之间的交互,使这些对象不需要显示地相互引用,从而使其耦合度降低。
当一组对象之间存在复杂的相互关系,并且需要通过一个中介来协调时,可以使用中介者模式。
一个聊天室可以使用中介者模式,将聊天室中的用户对象解耦,通过中介者进行消息的传递和处理。
interface Mediator {
void sendMessage(String message, User user);
}
class ConcreteMediator implements Mediator {
private List<User> users = new ArrayList<>();
public void addUser(User user) {
users.add(user);
}
@Override
public void sendMessage(String message, User sender) {
for (User user : users) {
if (user != sender) {
user.receiveMessage(message);
}
}
}
}
class User {
private String name;
private Mediator mediator;
public User(String name, Mediator mediator) {
this.name = name;
this.mediator = mediator;
}
public void sendMessage(String message) {
mediator.sendMessage(message, this);
}
public void receiveMessage(String message) {
System.out.println(name + " received message: " + message);
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Mediator mediator = new ConcreteMediator();
User user1 = new User("User 1", mediator);
User user2 = new User("User 2", mediator);
User user3 = new User("User 3", mediator);
mediator.addUser(user1);
mediator.addUser(user2);
mediator.addUser(user3);
user1.sendMessage("Hello, everyone!");
}
}
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便之后可以恢复原先的状态。
当需要保存和恢复对象的状态时,使用备忘录模式。
一个文本编辑器可以使用备忘录模式,通过保存文本编辑器的状态(如光标位置、文本内容等),以便之后可以恢复到之前的状态。
class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
class Originator {
private String state;
public void setState(String state) {
this.state = state;
}
public Memento createMemento() {
return new Memento(state);
}
public void restoreMemento(Memento memento) {
state = memento.getState();
}
public void showState() {
System.out.println("Current state: " + state);
}
}
class Caretaker {
private Memento memento;
public void setMemento(Memento memento) {
this.memento = memento;
}
public Memento getMemento() {
return memento;
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("State 1");
originator.showState();
caretaker.setMemento(originator.createMemento());
originator.setState("State 2");
originator.showState();
originator.restoreMemento(caretaker.getMemento());
originator.showState();
}
}
给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器来解释语言中的句子。
当需要解释和执行一种语言的语法时,可以使用解释器模式。
一个数学表达式解析器可以使用解释器模式,将数学表达式的字符串解析成可以计算的表达式。
interface Expression {
int interpret();
}
class NumberExpression implements Expression {
private int number;
public NumberExpression(int number) {
this.number = number;
}
@Override
public int interpret() {
return number;
}
}
class AddExpression implements Expression {
private Expression left;
private Expression right;
public AddExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() + right.interpret();
}
}
class SubtractExpression implements Expression {
private Expression left;
private Expression right;
public SubtractExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() - right.interpret();
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Expression expression = new SubtractExpression(
new AddExpression(new NumberExpression(10), new NumberExpression(5)),
new NumberExpression(2)
);
int result = expression.interpret();
System.out.println("Result: " + result);
}
}
允许一个对象在其内部状态改变时修改其行为,对象看起来似乎修改了它的类。
当一个对象的行为取决于其内部状态,并且需要在其运行时根据内部状态改变其行为时,可以使用状态模式。
一个订单状态管理系统可以使用状态模式,根据订单的不同状态(如待支付、已支付、已发货等),订单对象的行为会有所不同。
interface State {
void handle();
}
class ConcreteStateA implements State {
@Override
public void handle() {
System.out.println("处理状态A的逻辑");
}
}
class ConcreteStateB implements State {
@Override
public void handle() {
System.out.println("处理状态B的逻辑");
}
}
class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle();
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Context context = new Context();
State stateA = new ConcreteStateA();
State stateB = new ConcreteStateB();
context.setState(stateA);
context.request();
context.setState(stateB);
context.request();
}
}
表示一个作用于某对象结构中的各元素的操作,使得可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
当需要对一个对象中的各个元素进行不同的操作,并且希望在不改变元素类的情况下增加新的操作时,可以使用访问者模式。
一个图形绘制软件可以使用访问者模式,通过访问者对象对不同类型的图形元素进行不同的操作,如计算面积、计算轮廓等。
// 抽象元素
interface Element {
void accept(Visitor visitor);
}
// 具体元素A
class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public void operationA() {
System.out.println("具体元素A的操作");
}
}
// 具体元素B
class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public void operationB() {
System.out.println("具体元素B的操作");
}
}
// 抽象访问者
interface Visitor {
void visit(ConcreteElementA elementA);
void visit(ConcreteElementB elementB);
}
// 具体访问者
class ConcreteVisitor implements Visitor {
@Override
public void visit(ConcreteElementA elementA) {
elementA.operationA();
}
@Override
public void visit(ConcreteElementB elementB) {
elementB.operationB();
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Element elementA = new ConcreteElementA();
Element elementB = new ConcreteElementB();
Visitor visitor = new ConcreteVisitor();
elementA.accept(visitor);
elementB.accept(visitor);
}
}
定义一系列算法,将每个算法封装起来,并使他们可以互换。
当需要再运行时根据不同的情况选择不同的算法时,可以使用策略模式。
一个支付系统可以使用策略模式,根据用户的支付方式(如支付宝、微信支付等),使用不同的支付策略进行支付。
interface PaymentStrategy {
void pay(double amount);
}
class AlipayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("使用支付宝支付:" + amount + "元");
}
}
class WechatPayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("使用微信支付:" + amount + "元");
}
}
class PaymentContext {
private PaymentStrategy strategy;
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void pay(double amount) {
strategy.pay(amount);
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
PaymentContext context = new PaymentContext();
PaymentStrategy alipayStrategy = new AlipayStrategy();
PaymentStrategy wechatPayStrategy = new WechatPayStrategy();
context.setStrategy(alipayStrategy);
context.pay(100.0);
context.setStrategy(wechatPayStrategy);
context.pay(200.0);
}
}
将请求的发送者和接受者解耦,使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
当有多个对象可以处理一个请求,并且希望请求的发送者和接受者解耦时,可以使用责任链模式。
一个审批流程可以使用责任链模式,将多个审批人组成一条链,依次处理审批请求,直到有一个人员处理为止。
abstract class Approver {
protected Approver nextApprover;
public void setNextApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
}
public abstract void approve(int amount);
}
class Manager extends Approver {
@Override
public void approve(int amount) {
if (amount <= 1000) {
System.out.println("Manager approved");
} else if (nextApprover != null) {
nextApprover.approve(amount);
}
}
}
class Director extends Approver {
@Override
public void approve(int amount) {
if (amount <= 5000) {
System.out.println("Director approved");
} else if (nextApprover != null) {
nextApprover.approve(amount);
}
}
}
class CEO extends Approver {
@Override
public void approve(int amount) {
if (amount <= 10000) {
System.out.println("CEO approved");
} else {
System.out.println("Amount too large, approval denied");
}
}
}
// 示例用法
public class Main {
public static void main(String[] args) {
Approver manager = new Manager();
Approver director = new Director();
Approver ceo = new CEO();
manager.setNextApprover(director);
director.setNextApprover(ceo);
manager.approve(500);
manager.approve(5000);
manager.approve(15000);
}
}