设计模式专题 主要是代码复用、简洁 ,经过前辈总结的通用 的一套方法设计模版,分为 创建着模式、行为模式、结构模式
创建者模式: 简单工厂、工厂方法、抽象工厂、单例、建造者模式、原型模式
行为模式:观察者模式、迭代器模式、命令模式、状态模式、策略模式、责任链模式、备忘录模式 、解释器模式、*中介者模式
结构模式: 代理模式、装饰模式、门面模式、组合模式、适配器模式、享元模式、桥接模式
创建型模式(Creational Patterns) 单例模式(Singleton):
优点:在整个应用生命周期中确保类的唯一实例。
缺点:可能引入全局状态,降低可测试性。
简单工厂(Simple Factory) 以下是一个简单工厂模式(Simple Factory Pattern)的 Java 示例,用于展示简单工厂模式的核心原理。
首先,我们创建一个名为 Animal
的接口:
1 2 3 public interface Animal { void speak () ; }
接下来,我们创建两个实现 Animal
接口的类,分别为 Dog
和 Cat
:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Dog implements Animal { @Override public void speak () { System.out.println("Woof!" ); } } public class Cat implements Animal { @Override public void speak () { System.out.println("Meow!" ); } }
然后,我们创建一个名为 AnimalFactory
的工厂类,用于根据传入的参数创建不同类型的 Animal
实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class AnimalFactory { public enum AnimalType { DOG, CAT } public static Animal createAnimal (AnimalType type) { switch (type) { case DOG: return new Dog (); case CAT: return new Cat (); default : throw new IllegalArgumentException ("Invalid animal type!" ); } } }
最后,创建一个测试类来展示简单工厂模式的用法:
1 2 3 4 5 6 7 8 9 public class SimpleFactoryDemo { public static void main (String[] args) { Animal dog = AnimalFactory.createAnimal(AnimalFactory.AnimalType.DOG); dog.speak(); Animal cat = AnimalFactory.createAnimal(AnimalFactory.AnimalType.CAT); cat.speak(); } }
在这个简化的示例中,简单工厂模式用于将 Animal
类的创建逻辑封装在 AnimalFactory
类中,从而将对象的创建和客户端代码解耦。客户端只需要知道所需的 AnimalType
(例如 DOG
或 CAT
),然后调用 AnimalFactory.createAnimal()
方法来创建相应类型的 Animal
实例。
运行测试类,你会看到如下输出:
这个例子展示了简单工厂模式的基本用法,它可以简化客户端代码并将对象创建过程集中管理。
工厂方法模式(Factory Method):
优点:抽象出对象创建过程,解耦了客户端和具体产品类。
缺点:可能引入更多类和复杂性。
抽象工厂模式(Abstract Factory):
优点:支持一组相关产品的创建,而无需指定具体实现类。
缺点:添加新产品可能需要修改接口,违反开闭原则。
建造者模式(Builder):
优点:让可选、有默认值的参数组合更易管理。
缺点:可能引入更多类和复杂性。
组合模式允许你构建对象的树形结构,并以统一的方式处理单一对象和组合对象。以下是一个简单的 Java 代码示例,演示如何使用组合模式构建一个表示文件和文件夹的层次结构。
首先,创建一个 Component
抽象类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.List;import java.util.ArrayList;public abstract class Component { protected String name; public Component (String name) { this .name = name; } public void add (Component component) { throw new UnsupportedOperationException ("Unsupported operation." ); } public void remove (Component component) { throw new UnsupportedOperationException ("Unsupported operation." ); } public List<Component> getChildren () { throw new UnsupportedOperationException ("Unsupported operation." ); } public String getName () { return name; } public abstract void display (int depth) ; }
然后创建 File
和 Directory
类,分别继承 Component
类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public class File extends Component { public File (String name) { super (name); } @Override public void display (int depth) { for (int i = 0 ; i < depth; i++) { System.out.print("-" ); } System.out.println("File: " + getName()); } } public class Directory extends Component { private List<Component> children = new ArrayList <>(); public Directory (String name) { super (name); } @Override public void add (Component component) { children.add(component); } @Override public void remove (Component component) { children.remove(component); } @Override public List<Component> getChildren () { return children; } @Override public void display (int depth) { for (int i = 0 ; i < depth; i++) { System.out.print("-" ); } System.out.println("Directory: " + getName()); for (Component child : children) { child.display(depth + 2 ); } } }
最后,创建一个测试类来演示组合模式的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class CompositePatternDemo { public static void main (String[] args) { Directory root = new Directory ("root" ); Directory dir1 = new Directory ("dir1" ); Directory dir2 = new Directory ("dir2" ); File file1 = new File ("file1" ); File file2 = new File ("file2" ); File file3 = new File ("file3" ); root.add(dir1); root.add(file1); dir1.add(dir2); dir1.add(file2); dir2.add(file3); root.display(0 ); } }
浏览组合结构的输出如下:
1 2 3 4 5 6 Directory: root --Directory: dir1 ----Directory: dir2 ------File: file3 ----File: file2 --File: file1
在这个示例中,Component
抽象类表示文件和文件夹的共同接口。File
和 Directory
类分别表示文件和文件夹对象。通过将 File
和 Directory
作为 Component
的子类,可以统一地处理文件和文件夹,并轻松地构建树形结构。
原型模式(Prototype):
优点:通过克隆来创建新对象,避免了复杂的初始化操作。
缺点:需要实现克隆方法,不能与单例模式结合使用。
原型模式是一种创建型设计模式,用于通过克隆现有对象来创建新对象。以下是一个简单的 Java 示例,展示了如何使用原型模式创建一个 Sheep
类,该类实现了 Cloneable
接口:
首先,创建一个名为 Sheep
的对象,它将克隆自身来创建新对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class Sheep implements Cloneable { private String name; public Sheep (String name) { this .name = name; } public String getName () { return name; } public void setName (String name) { this .name = name; } @Override public Sheep clone () { try { return (Sheep) super .clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null ; } } @Override public String toString () { return "Sheep{" + "name='" + name + '\'' + '}' ; } }
然后,创建一个测试类来展示原型模式的用法:
1 2 3 4 5 6 7 8 9 10 11 12 public class PrototypePatternDemo { public static void main (String[] args) { Sheep originalSheep = new Sheep ("Dolly" ); System.out.println("Original sheep: " + originalSheep); Sheep clonedSheep = originalSheep.clone(); System.out.println("Cloned sheep: " + clonedSheep); System.out.println("Are originalSheep and clonedSheep the same instance? " + (originalSheep == clonedSheep)); } }
在这个示例中,我们创建了一个名为 Sheep
的类,它实现了 Cloneable
接口。clone
方法从父类 Object
继承而来,我们需要重写该方法,使其返回 Sheep
类型的实例。
main
方法创建了一个名为 originalSheep
的原始实例。接下来,我们使用 clone
方法创建了一个名为 clonedSheep
的新实例。请注意,新实例与原始实例具有相同的属性,但它们是两个不同的对象。
原型模式在对象的创建过程成本较高时非常有用,例如大对象的创建或引用其他类库的创建。通过简单地克隆现有对象,可以避免即时的构造过程,从而减轻创建新对象的负担。
结构型模式(Structural Patterns) 适配器模式(Adapter): - 优点:使具有不兼容接口的类可以相互协作。 - 缺点:如果过多使用,将降低系统结构的透明度。
首先,创建一个名为 Charger
的接口:
1 2 3 public interface Charger { void charge () ; }
接着,创建一个名为 USCharger
的类实现 Charger
接口:
1 2 3 4 5 6 public class USCharger implements Charger { @Override public void charge () { System.out.println("Charging with US charger." ); } }
此外,我们新创建一个名为 EUCharger
的接口供适配:
1 2 3 public interface EUCharger { void chargeWithEUCharger () ; }
现在我们创建一个名为 ChargerAdapter
的适配器类,用于将 EUCharger
适配为 Charger
:
1 2 3 4 5 6 7 8 9 10 11 12 public class ChargerAdapter implements Charger { private EUCharger euCharger; public ChargerAdapter (EUCharger euCharger) { this .euCharger = euCharger; } @Override public void charge () { euCharger.chargeWithEUCharger(); } }
最后,创建一个名为 EUSocket
的类,实现 EUCharger
接口:
1 2 3 4 5 6 public class EUSocket implements EUCharger { @Override public void chargeWithEUCharger () { System.out.println("Charging with EU charger." ); } }
然后,创建一个测试类来展示适配器模式的用法:
1 2 3 4 5 6 7 8 9 10 public class AdapterPatternDemo { public static void main (String[] args) { USCharger usCharger = new USCharger (); usCharger.charge(); EUSocket euSocket = new EUSocket (); Charger euChargerAdapter = new ChargerAdapter (euSocket); euChargerAdapter.charge(); } }
在这个简化的示例中,适配器模式使一个 Charger
接口与一个 EUCharger
接口兼容。ChargerAdapter
是一个适配器类,它实现 Charger
接口并接受一个 EUCharger
实例。通过调用适配器的 charge()
方法可以使用 EUCharger
类型的实例。
运行测试类,你会看到如下输出:
1 2 Charging with US charger. Charging with EU charger.
建造者模式(Builder): - 优点:将抽象部分与实现部分分离,提高系统的可扩展性。 - 缺点:增加类的数量,增加系统的复杂度。
桥接模式将抽象和实现分离,使两者可以独立地变化。以下是一个简单的 Java 代码示例,演示如何使用桥接模式定义一个跨平台的图形绘制应用。
首先,创建 DrawAPI
接口,作为实现部分:
1 2 3 public interface DrawAPI { void drawCircle (int radius, int x, int y) ; }
然后,创建两个不同的实现类:RedCircle
和 GreenCircle
,分别表示两种颜色的圆形:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class RedCircle implements DrawAPI { @Override public void drawCircle (int radius, int x, int y) { System.out.println("Drawing red circle [radius: " + radius + ", x: " + x + ", y:" + y + "]" ); } } public class GreenCircle implements DrawAPI { @Override public void drawCircle (int radius, int x, int y) { System.out.println("Drawing green circle [radius: " + radius + ", x: " + x + ", y:" + y + "]" ); } }
接下来,创建抽象类 Shape
,用于表示抽象部分:
1 2 3 4 5 6 7 8 9 public abstract class Shape { protected DrawAPI drawAPI; protected Shape (DrawAPI drawAPI) { this .drawAPI = drawAPI; } public abstract void draw () ; }
创建具体的 Circle
类,继承自 Shape
类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Circle extends Shape { private int x, y, radius; public Circle (int x, int y, int radius, DrawAPI drawAPI) { super (drawAPI); this .x = x; this .y = y; this .radius = radius; } @Override public void draw () { drawAPI.drawCircle(radius, x, y); } }
最后,创建一个演示类,用于展示桥接模式的用法:
1 2 3 4 5 6 7 8 9 public class BridgePatternDemo { public static void main (String[] args) { Shape redCircle = new Circle (100 , 100 , 10 , new RedCircle ()); Shape greenCircle = new Circle (100 , 100 , 10 , new GreenCircle ()); redCircle.draw(); greenCircle.draw(); } }
组合模式(Composite):
- 优点:统一对待组合对象和单一对象,简化客户端代码。 - 缺点:设计过程中需要有明确的叶子对象和组合对象的区分。
组合模式允许你构建对象的树形结构,并以统一的方式处理单一对象和组合对象。以下是一个简单的 Java 代码示例,演示如何使用组合模式构建一个表示文件和文件夹的层次结构。
首先,创建一个 Component
抽象类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.List;import java.util.ArrayList;public abstract class Component { protected String name; public Component (String name) { this .name = name; } public void add (Component component) { throw new UnsupportedOperationException ("Unsupported operation." ); } public void remove (Component component) { throw new UnsupportedOperationException ("Unsupported operation." ); } public List<Component> getChildren () { throw new UnsupportedOperationException ("Unsupported operation." ); } public String getName () { return name; } public abstract void display (int depth) ; }
然后创建 File
和 Directory
类,分别继承 Component
类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public class File extends Component { public File (String name) { super (name); } @Override public void display (int depth) { for (int i = 0 ; i < depth; i++) { System.out.print("-" ); } System.out.println("File: " + getName()); } } public class Directory extends Component { private List<Component> children = new ArrayList <>(); public Directory (String name) { super (name); } @Override public void add (Component component) { children.add(component); } @Override public void remove (Component component) { children.remove(component); } @Override public List<Component> getChildren () { return children; } @Override public void display (int depth) { for (int i = 0 ; i < depth; i++) { System.out.print("-" ); } System.out.println("Directory: " + getName()); for (Component child : children) { child.display(depth + 2 ); } } }
最后,创建一个测试类来演示组合模式的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class CompositePatternDemo { public static void main (String[] args) { Directory root = new Directory ("root" ); Directory dir1 = new Directory ("dir1" ); Directory dir2 = new Directory ("dir2" ); File file1 = new File ("file1" ); File file2 = new File ("file2" ); File file3 = new File ("file3" ); root.add(dir1); root.add(file1); dir1.add(dir2); dir1.add(file2); dir2.add(file3); root.display(0 ); } }
浏览组合结构的输出如下:
1 2 3 4 5 6 Directory: root --Directory: dir1 ----Directory: dir2 ------File: file3 ----File: file2 --File: file1
在这个示例中,Component
抽象类表示文件和文件夹的共同接口。File
和 Directory
类分别表示文件和文件夹对象。通过将 File
和 Directory
作为 Component
的子类,可以统一地处理文件和文件夹,并轻松地构建树形结构。
装饰器模式(Decorator): - 优点:通过装饰器类,动态地为对象添加新功能,符合开闭原则。 - 缺点:可能导致大量小型类,使系统变得复杂。
以下是一个简单的装饰器模式的 Java 示例,用于展示装饰器模式的核心原理。
首先,创建一个名为 Beverage
的接口:
1 2 3 4 public interface Beverage { String getDescription () ; double cost () ; }
然后,创建一个实现 Beverage
接口的具体组件(ConcreteComponent)类,名为 Coffee
:
1 2 3 4 5 6 7 8 9 10 11 public class Coffee implements Beverage { @Override public String getDescription () { return "Coffee" ; } @Override public double cost () { return 1.5 ; } }
接下来,创建一个抽象装饰类(Decorator)来实现 Beverage
接口,并包含一个 Beverage
类型的组件引用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public abstract class BeverageDecorator implements Beverage { private Beverage beverage; public BeverageDecorator (Beverage beverage) { this .beverage = beverage; } @Override public String getDescription () { return beverage.getDescription(); } @Override public double cost () { return beverage.cost(); } }
然后,创建一个具体装饰器(ConcreteDecorator)类来扩展 BeverageDecorator
,名为 Milk
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Milk extends BeverageDecorator { public Milk (Beverage beverage) { super (beverage); } @Override public String getDescription () { return super .getDescription() + ", Milk" ; } @Override public double cost () { return super .cost() + 0.3 ; } }
最后,创建一个测试类来展示装饰器模式的用法:
1 2 3 4 5 6 7 8 9 public class DecoratorPatternDemo { public static void main (String[] args) { Beverage coffee = new Coffee (); System.out.println(coffee.getDescription() + " $" + coffee.cost()); Beverage coffeeWithMilk = new Milk (coffee); System.out.println(coffeeWithMilk.getDescription() + " $" + coffeeWithMilk.cost()); } }
在这个简化的示例中,装饰器模式用于为现有的类(Coffee
)动态地添加新的功能(Milk
),而不是通过继承来实现。BeverageDecorator
是一个抽象的装饰类,它实现了 Beverage
接口并包含一个 Beverage
引用。具体装饰器类 Milk
扩展了 BeverageDecorator
,并可以修改 getDescription()
和 cost()
方法来实现额外的功能。
运行测试类,你会看到如下输出:
1 2 Coffee \$1.5 Coffee, Milk \$1.8
外观模式(Facade): - 优点:简化外部操作,降低模块间耦合。 - 缺点:过度使用可能限制用户选项。
首先,我们创建三个简单的类,分别为 ClassA
,ClassB
和ClassC
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class ClassA { public void operationA () { System.out.println("Operation A" ); } } public class ClassB { public void operationB () { System.out.println("Operation B" ); } } public class ClassC { public void operationC () { System.out.println("Operation C" ); } }
接下来,创建一个名为 Facade
的类,用于简化这三个类的使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Facade { private ClassA classA; private ClassB classB; private ClassC classC; public Facade () { classA = new ClassA (); classB = new ClassB (); classC = new ClassC (); } public void doSomethingA () { classA.operationA(); } public void doSomethingB () { classB.operationB(); } public void doSomethingC () { classC.operationC(); } }
最后,创建一个测试类来展示外观模式的用法:
1 2 3 4 5 6 7 8 9 public class FacadePatternDemo { public static void main (String[] args) { Facade facade = new Facade (); facade.doSomethingA(); facade.doSomethingB(); facade.doSomethingC(); } }
在这个简化的示例中,外观模式用于将 ClassA
,ClassB
和 ClassC
的操作封装在一个简单的接口(Facade
)中。客户端不需要关心这些具体的组件是如何实现和协作的,而只需要和 Facade
类进行交互。这样不仅简化了客户端的使用,还降低了客户端和各个子系统之间的耦合。
运行测试类,你会看到如下输出:
1 2 3 Operation A Operation B Operation C
这个例子展示了如何使用外观模式来简化复杂系统的使用,并且可以将子系统的实现细节隐藏在外观类的背后。
享元模式(Flyweight): - 优点:复用对象,降低系统中大量小对象的开销。 - 缺点:实现较复杂,需要区分内部状态和外部状态。
首先,创建一个 Shape
接口:
1 2 3 public interface Shape { void draw () ; }
然后,创建具体的 Circle
类实现 Shape
接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Circle implements Shape { private String color; private int x; private int y; public Circle (String color) { this .color = color; } public void setX (int x) { this .x = x; } public void setY (int y) { this .y = y; } @Override public void draw () { System.out.println("Drawing circle [color: " + color + ", x: " + x + ", y: " + y + "]" ); } }
接下来,创建一个 ShapeFactory
类,负责按需创建新的 Circle
对象或复用现有的对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.HashMap;public class ShapeFactory { private static final HashMap<String, Shape> circleMap = new HashMap <>(); public static Shape getCircle (String color) { Circle circle = (Circle) circleMap.get(color); if (circle == null ) { circle = new Circle (color); circleMap.put(color, circle); System.out.println("Creating a new circle of color: " + color); } return circle; } }
最后,创建一个演示类,利用 ShapeFactory
来绘制不同颜色的圆形:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.Random;public class FlyweightPatternDemo { private static final String[] colors = {"Red" , "Green" , "Blue" , "White" , "Black" }; public static void main (String[] args) { for (int i = 0 ; i < 20 ; ++i) { Circle circle = (Circle) ShapeFactory.getCircle(getRandomColor()); circle.setX(getRandomX()); circle.setY(getRandomY()); circle.draw(); } } private static String getRandomColor () { return colors[(int ) (Math.random() * colors.length)]; } private static int getRandomX () { return (int ) (Math.random() * 100 ); } private static int getRandomY () { return (int ) (Math.random() * 100 ); } }
在这个例子中,ShapeFactory
通过维护一个颜色到 Circle
对象的映射,确保每种颜色只创建一次 Circle
。当需要绘制相同颜色的圆时,直接从工厂中获取现有的对象。这样,即使应用中绘制了多个圆形,实际创建的 Circle
对象数量也被显著减少。
代理模式(Proxy): - 优点:代理类实现原对象附加功能,如:访问控制、延迟计算等。 - 缺点:可能增加延迟,并降低代码透明度
动态代理
首先,我们创建一个名为 Greeting
的接口:
1 2 3 public interface Greeting { void sayHello (String name) ; }
然后,创建一个实现 Greeting
接口的 GreetingImpl
类:
1 2 3 4 5 6 public class GreetingImpl implements Greeting { @Override public void sayHello (String name) { System.out.println("Hello, " + name); } }
接下来创建一个实现了 java.lang.reflect.InvocationHandler
的 GreetingInvocationHandler
类,用于处理代理实例上的方法调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class GreetingInvocationHandler implements InvocationHandler { private final Object target; public GreetingInvocationHandler (Object target) { this .target = target; } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before method call: " + method.getName()); Object result = method.invoke(target, args); System.out.println("After method call: " + method.getName()); return result; } }
最后,我们创建一个测试类来展示动态代理的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.lang.reflect.Proxy;public class DynamicProxyDemo { public static void main (String[] args) { GreetingImpl greetingImpl = new GreetingImpl (); GreetingInvocationHandler invocationHandler = new GreetingInvocationHandler (greetingImpl); Greeting greetingProxy = (Greeting) Proxy.newProxyInstance( greetingImpl.getClass().getClassLoader(), greetingImpl.getClass().getInterfaces(), invocationHandler); greetingProxy.sayHello("JDK Dynamic Proxy" ); } }
静态代理:
首先,我们创建一个名为 Database
的接口:
1 2 3 public interface Database { void executeQuery (String query) ; }
接下来,我们创建实现 Database
接口的 RealDatabase
类:
1 2 3 4 5 6 public class RealDatabase implements Database { @Override public void executeQuery (String query) { System.out.println("Executing query: " + query); } }
然后,我们创建一个实现 Database
接口的代理类 DatabaseProxy
:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class DatabaseProxy implements Database { private RealDatabase database; public DatabaseProxy () { database = new RealDatabase (); } @Override public void executeQuery (String query) { System.out.println("Proxy checking access..." ); database.executeQuery(query); } }
最后,我们创建一个测试类来展示代理模式的用法:
1 2 3 4 5 6 7 public class ProxyPatternDemo { public static void main (String[] args) { Database database = new DatabaseProxy (); database.executeQuery("SELECT * FROM users;" ); } }
行为型模式(Behavioral Patterns) 职责链模式(Chain of Responsibility): - 优点:解耦请求者与处理者,提高灵活性。 - 缺点:不保证请求被处理,可能会增加延迟。
先创建一个抽象校验器类(Validator
),它包含指向下一个校验器的引用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public abstract class Validator { protected Validator nextValidator; protected boolean valid; public void setNextValidator (Validator nextValidator) { this .nextValidator = nextValidator; } public abstract void validate (String data) ; public boolean isValid () { return valid; } }
接下来,创建两个具体的校验器类(LengthValidator
和 CharacterValidator
),分别从抽象校验器类 Validator
继承:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class LengthValidator extends Validator { @Override public void validate (String data) { if (data.length() >= 5 ) { System.out.println("LengthValidator passed." ); valid = true ; if (nextValidator != null ) { nextValidator.validate(data); valid = nextValidator.isValid(); } } else { System.out.println("LengthValidator failed." ); valid = false ; } } } public class CharacterValidator extends Validator { @Override public void validate (String data) { if (data.matches("[a-zA-Z]+" )) { System.out.println("CharacterValidator passed." ); valid = true ; } else { System.out.println("CharacterValidator failed." ); valid = false ; } } }
最后,创建一个测试类来展示责任链模式在校验场景中的应用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class ValidationChainDemo { public static void main (String[] args) { Validator lengthValidator = new LengthValidator (); Validator characterValidator = new CharacterValidator (); lengthValidator.setNextValidator(characterValidator); String[] inputs = {"abc" , "abcdef" , "abc123" , "abc&^%" }; for (String input : inputs) { System.out.println("Input: " + input); lengthValidator.validate(input); if (!lengthValidator.isValid()) { System.out.println("Skipping next validators..." ); } System.out.println("Validation result: " + lengthValidator.isValid()); System.out.println("------" ); } } }
在这个修改后的示例中,遇到一个 false
结果就停止接下来的校验。现在,如果 LengthValidator
失败,它不会传递给下一个校验器 CharacterValidator
。### 命令模式(Command):
- 优点:将请求和处理分离,增加系统的灵活性。 - 缺点:可能引入较多的具体命令类,增加复杂性。
命令模式(Command Pattern)用于将操作封装成一个对象,从而解耦请求者和实际操作的执行者。以下是一个简单的 Java 示例:
创建一个 Command
接口,定义命令操作:
1 2 3 public interface Command { void execute () ; }
创建一个具体的命令类(例如 PrintCommand
),实现 Command
接口:
1 2 3 4 5 6 7 8 9 10 11 12 public class PrintCommand implements Command { private String message; public PrintCommand (String message) { this .message = message; } @Override public void execute () { System.out.println(message); } }
创建一个请求者类 Invoker
,用于接收和执行命令:
1 2 3 4 5 6 7 8 9 10 11 public class Invoker { private Command command; public void setCommand (Command command) { this .command = command; } public void executeCommand () { command.execute(); } }
最后创建一个测试类来演示命令模式的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class CommandPatternDemo { public static void main (String[] args) { Invoker invoker = new Invoker (); Command printHello = new PrintCommand ("Hello, World!" ); Command printGoodbye = new PrintCommand ("Goodbye, World!" ); invoker.setCommand(printHello); invoker.executeCommand(); invoker.setCommand(printGoodbye); invoker.executeCommand(); } }
在这个简单的示例中,我们创建了一个命令接口 Command
和一个具体的命令实现类 PrintCommand
。Invoker
类将命令对象与实际操作的执行者解耦。我们可以轻松地更换 Command
对象,而不会影响到 Invoker
的实现。在此示例中,我们创建了两个不同的 PrintCommand
对象并分别通过 Invoker
对象执行它们。
解释器模式(Interpreter): - 优点:便于为文法规则添加新的解释表示。 - 缺点:当文法规则复杂时,效率较低。
解释器模式(Interpreter Pattern)通常用于解析和处理具有良好结构的文本或者其他形式的数据。以下是一个简化的 Java 示例,用于理解解释器模式。
我们将创建一个简单的解释器,用于将输入的数字(1-7)转换为星期的名称。
定义 Expression
接口,表示抽象表达式:
1 2 3 public interface Expression { String interpret (int number) ; }
创建一个具体的解释器类 DayOfWeekInterpreter
,实现 Expression
接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class DayOfWeekInterpreter implements Expression { @Override public String interpret (int number) { switch (number) { case 1 : return "Sunday" ; case 2 : return "Monday" ; case 3 : return "Tuesday" ; case 4 : return "Wednesday" ; case 5 : return "Thursday" ; case 6 : return "Friday" ; case 7 : return "Saturday" ; default : return "Invalid day number" ; } } }
创建一个测试类来演示解释器模式的用法:
1 2 3 4 5 6 7 8 9 10 public class InterpreterPatternDemo { public static void main (String[] args) { Expression dayOfWeekInterpreter = new DayOfWeekInterpreter (); int [] dayNumbers = {1 , 3 , 5 , 7 , 8 }; for (int dayNumber : dayNumbers) { System.out.println("Day " + dayNumber + " is " + dayOfWeekInterpreter.interpret(dayNumber)); } } }
在这个简化的示例中,我们创建了一个 Expression
接口和一个具体的解释器实现类 DayOfWeekInterpreter
。DayOfWeekInterpreter
根据输入的数字返回星期的名称。实际应用中,解释器模式的使用场景可以复杂得多,例如处理各种具体语法规则、语法分析器等。这个例子只是为了简化理解。
迭代器模式(Iterator): - 优点:为容器提供统一的访问接口,降低遍历复杂性。 - 缺点:对于简单的容器,接口可能显得冗余。
迭代器模式(Iterator Pattern)提供一种遍历容器内元素的统一方法,同时不暴露容器的内部表示。以下是一个简化的 Java 示例,用于理解迭代器模式。
定义迭代器接口 Iterator
:
1 2 3 4 public interface Iterator <E> { boolean hasNext () ; E next () ; }
定义需要遍历的容器接口 Container
:
1 2 3 public interface Container <E> { Iterator<E> getIterator () ; }
创建具体的容器实现类 ListContainer
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import java.util.ArrayList;import java.util.List;public class ListContainer <E> implements Container <E> { private List<E> elements; public ListContainer () { this .elements = new ArrayList <>(); } public void addElement (E element) { elements.add(element); } @Override public Iterator<E> getIterator () { return new ListIterator (); } private class ListIterator implements Iterator <E> { private int index = 0 ; @Override public boolean hasNext () { return index < elements.size(); } @Override public E next () { if (hasNext()) { return elements.get(index++); } return null ; } } }
创建一个测试类来演示迭代器模式的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class IteratorPatternDemo { public static void main (String[] args) { ListContainer<String> names = new ListContainer <>(); names.addElement("Alice" ); names.addElement("Bob" ); names.addElement("Charlie" ); Iterator<String> iterator = names.getIterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } } }
在这个简化的示例中,我们定义了一个 Iterator
接口和一个需要遍历的容器接口 Container
。ListContainer
实现了 Container
接口,并通过内部类 ListIterator
提供了实际的迭代器。测试类展示了如何使用迭代器遍历容器内的数据。
这个简洁的例子展示了迭代器模式的核心思想。实际应用中,Java 提供了现成的 Iterator
接口和许多实现了 Iterable
接口的集合类(如 ArrayList
,HashSet
等),因此无需手动创建这些接口和实现类。
- 优点:减少对象之间的直接调用,降低耦合。 - 缺点:中介者可能变得庞大且复杂。
中介者模式(Mediator Pattern)用于降低系统组件之间的耦合度,使得组件可以通过一个中介对象进行相互通信。以下是一个简化的 Java 示例,以方便理解中介者模式。
假设我们有两个按钮,它们需要相互协调来解锁或锁定一个门。
创建 Colleague
抽象类来表示组件:
1 2 3 4 5 6 7 8 9 public abstract class Colleague { protected Mediator mediator; public Colleague (Mediator mediator) { this .mediator = mediator; } public abstract void toggle () ; }
创建两个具体的 Colleague
类:ButtonA
和 ButtonB
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class ButtonA extends Colleague { public ButtonA (Mediator mediator) { super (mediator); } @Override public void toggle () { System.out.println("Button A toggled" ); mediator.changeState(this ); } } public class ButtonB extends Colleague { public ButtonB (Mediator mediator) { super (mediator); } @Override public void toggle () { System.out.println("Button B toggled" ); mediator.changeState(this ); } }
创建 Mediator
接口来表示中介者:
1 2 3 public interface Mediator { void changeState (Colleague colleague) ; }
创建具体的中介者类 DoorMediator
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class DoorMediator implements Mediator { private boolean is_unlocked; private ButtonA buttonA; private ButtonB buttonB; public DoorMediator (ButtonA buttonA, ButtonB buttonB) { this .buttonA = buttonA; this .buttonB = buttonB; is_unlocked = false ; } @Override public void changeState (Colleague colleague) { if (colleague instanceof ButtonA) { is_unlocked = !is_unlocked; } if (colleague instanceof ButtonB) { if (is_unlocked) { System.out.println("Door has been locked" ); is_unlocked = false ; } else { System.out.println("Door cannot be locked before unlocking" ); } } } }
创建一个测试类来演示中介者模式的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class MediatorPatternDemo { public static void main (String[] args) { DoorMediator mediator = new DoorMediator (null , null ); ButtonA buttonA = new ButtonA (mediator); ButtonB buttonB = new ButtonB (mediator); mediator = new DoorMediator (buttonA, buttonB); buttonA.toggle(); buttonB.toggle(); buttonA.toggle(); buttonB.toggle(); } }
在这个简化示例中,我们创建了一个 Colleague
抽象类,两个具体的组件 ButtonA
和 ButtonB
,以及一个 Mediator
接口和一个具体的中介者类 DoorMediator
。通过让按钮与中介者进行交互,而非直接相互沟通,我们降低了按钮 ButtonA
和 ButtonB
之间的耦合。
在实际项目中,中介者模式可以应用于更复杂的系统,以减轻各个组件间的通信压力。
备忘录模式(Memento):
- 优点:允许在不破坏封装性的前提下保存和恢复对象的状态。 - 缺点:如果需要保存的对象状态较大,会占用较多的内存资源。
忘录模式(Memento Pattern)用于捕获对象的内部状态,并在以后将对象恢复到此状态。以下是一个简化的 Java 示例,用于理解备忘录模式。
假设我们正在编写一个非常简单的撤销功能的文本编辑器。
创建 Memento
类来存储文本编辑器的状态:
1 2 3 4 5 6 7 8 9 10 11 public class Memento { private String state; public Memento (String state) { this .state = state; } public String getState () { return state; } }
创建需要保存状态的 Originator
类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Originator { private String state; public void setState (String state) { this .state = state; } public String getState () { return state; } public Memento saveStateToMemento () { return new Memento (state); } public void getStateFromMemento (Memento memento) { state = memento.getState(); } }
创建一个负责保存备忘录的 Caretaker
类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import java.util.ArrayList;import java.util.List;public class Caretaker { private List<Memento> mementoList = new ArrayList <>(); public void add (Memento state) { mementoList.add(state); } public Memento get (int index) { return mementoList.get(index); } }
创建一个测试类来演示备忘录模式的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class MementoPatternDemo { public static void main (String[] args) { Originator originator = new Originator (); Caretaker caretaker = new Caretaker (); originator.setState("State #1" ); caretaker.add(originator.saveStateToMemento()); originator.setState("State #2" ); caretaker.add(originator.saveStateToMemento()); originator.setState("State #3" ); originator.getStateFromMemento(caretaker.get(1 )); System.out.println("Restored state: " + originator.getState()); } }
在这个简化示例中,我们创建了一个 Memento
类,用于存储文本编辑器的状态。Originator
类负责设置和获取状态以及将状态保存到实例化的 Memento
对象外部。Caretaker
类负责保存Memento
实例,并在需要时提供恢复状态的功能。
这个简洁的例子展示了备忘录模式的核心思想,用于保存和恢复对象的内部状态。实际应用中,备忘录模式可用于实现撤销和重做操作、程序快照等功能。
观察者模式(Observer): - 优点:支持发布-订阅模式,降低对象间耦合度。 - 缺点:通知顺序不固定,可能导致死循环。
使用以下简化版的观察者(Observer)和主题(Subject)接口:
1 2 3 4 5 6 7 8 9 public interface Observer { void update (String topic) ; } public interface Subject { void addObserver (Observer observer) ; void removeObserver (Observer observer) ; void notifyObservers () ; }
创建一个 Lecturer 类作为 Subject:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import java.util.ArrayList;import java.util.List;public class Lecturer implements Subject { private List<Observer> students; private String topic; public Lecturer () { students = new ArrayList <>(); } @Override public void addObserver (Observer observer) { students.add(observer); } @Override public void removeObserver (Observer observer) { students.remove(observer); } @Override public void notifyObservers () { for (Observer student : students) { student.update(topic); } } public void setTopic (String topic) { this .topic = topic; notifyObservers(); } }
创建一个 Student 类作为具体的观察者:
1 2 3 4 5 6 7 8 9 10 11 12 public class Student implements Observer { private String name; public Student (String name) { this .name = name; } @Override public void update (String topic) { System.out.println(name + " received the new topic: " + topic); } }
创建一个测试类来演示观察者模式的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class SimpleLectureExample { public static void main (String[] args) { Lecturer lecturer = new Lecturer (); Student student1 = new Student ("Alice" ); Student student2 = new Student ("Bob" ); lecturer.addObserver(student1); lecturer.addObserver(student2); lecturer.setTopic("Design Patterns" ); lecturer.setTopic("Big Data" ); } }
这个简单的例子展示了一对多依赖关系的核心概念:当主讲人的课题发生变化时,所有订阅学生都会及时收到通知。
状态模式(State): - 优点:封装内部状态行为,降低外部调用复杂性。 - 缺点:增加了类的数量,增加系统负担。
假设我们有一个简单的交通信号灯,只有红、黄、绿三种状态。首先我们创建一个状态接口:
1 2 3 public interface TrafficLightState { void change () ; }
然后为红、黄、绿三种状态创建具体的状态类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public class RedState implements TrafficLightState { private TrafficLight trafficLight; public RedState (TrafficLight trafficLight) { this .trafficLight = trafficLight; } @Override public void change () { System.out.println("Red light turns to Green" ); trafficLight.setState(trafficLight.getGreenState()); } } public class YellowState implements TrafficLightState { private TrafficLight trafficLight; public YellowState (TrafficLight trafficLight) { this .trafficLight = trafficLight; } @Override public void change () { System.out.println("Yellow light turns to Red" ); trafficLight.setState(trafficLight.getRedState()); } } public class GreenState implements TrafficLightState { private TrafficLight trafficLight; public GreenState (TrafficLight trafficLight) { this .trafficLight = trafficLight; } @Override public void change () { System.out.println("Green light turns to Yellow" ); trafficLight.setState(trafficLight.getYellowState()); } }
创建一个 TrafficLight
类,用于管理状态转换:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public class TrafficLight { private TrafficLightState redState; private TrafficLightState yellowState; private TrafficLightState greenState; private TrafficLightState currentState; public TrafficLight () { redState = new RedState (this ); yellowState = new YellowState (this ); greenState = new GreenState (this ); currentState = redState; } public void change () { currentState.change(); } public void setState (TrafficLightState state) { this .currentState = state; } public TrafficLightState getRedState () { return redState; } public TrafficLightState getYellowState () { return yellowState; } public TrafficLightState getGreenState () { return greenState; } }
策略模式(Strategy): - 优点:将一组算法封装,提高算法的可互换性和复用性。 - 缺点:客户端必须了解具体策略的区别。
个完整的策略模式包括策略接口、具体策略实现、上下文类以及它们的使用。以下是一个关于支付方式的完整的策略模式示例:
策略接口 - PaymentStrategy
1 2 3 public interface PaymentStrategy { void pay (double amount) ; }
具体策略实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class CreditCardStrategy implements PaymentStrategy { private String name; private String cardNumber; private String cvv; private String dateOfExpiry; public CreditCardStrategy (String name, String cardNumber, String cvv, String dateOfExpiry) { this .name = name; this .cardNumber = cardNumber; this .cvv = cvv; this .dateOfExpiry = dateOfExpiry; } @Override public void pay (double amount) { System.out.println(amount + " paid with credit/debit card" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class PaypalStrategy implements PaymentStrategy { private String email; private String password; public PaypalStrategy (String email, String password) { this .email = email; this .password = password; } @Override public void pay (double amount) { System.out.println(amount + " paid using PayPal." ); } }
上下文类 - ShoppingCart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import java.util.ArrayList;import java.util.List;public class ShoppingCart { private List<Item> items; public ShoppingCart () { this .items = new ArrayList <>(); } public void addItem (Item item) { items.add(item); } public void removeItem (Item item) { items.remove(item); } public double calculateTotal () { double sum = 0 ; for (Item item : items) { sum += item.getPrice(); } return sum; } public void pay (PaymentStrategy paymentStrategy) { double amount = calculateTotal(); paymentStrategy.pay(amount); } }
数据类 - Item(产品)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Item { private String code; private double price; public Item (String code, double price) { this .code = code; this .price = price; } public String getCode () { return code; } public double getPrice () { return price; } }
策略模式的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class ShoppingCartTest { public static void main (String[] args) { ShoppingCart cart = new ShoppingCart (); Item item1 = new Item ("item1" , 100 ); Item item2 = new Item ("item2" , 150 ); cart.addItem(item1); cart.addItem(item2); cart.pay(new CreditCardStrategy ("John Doe" , "1234567890" , "123" , "01/2025" )); cart.pay(new PaypalStrategy ("johndoe@example.com" , "mypassword" )); } }
在这个完整的策略模式示例中,我们创建了一个支付策略接口,以及两个不同的具体支付策略实现:信用卡支付和PayPal支付。通常,这两种支付方式的处理过程和API可能有很大差异,但从客户(购物车)的角度来看,它们具有相同的行为:支付金额。购物车充当上下文,并在运行时接收一个支付策略对象来完成支付。这使得购物车及其支付逻辑具有更高的灵活性,阅读代码时可通过不同支付接口而无需更改其实现。
模板方法模式(Template Method): - 优点:将不变的行为定义在父类,将可变的行为定义在子类。 - 缺点:可能导致过多的子类。
模板方法模式是一种行为设计模式,它定义了算法的基本步骤,在父类中提供通用实现。子类可以根据需要覆写这些方法,从而实现特定行为。以下是一个关于制作三明治的完整模板方法模式示例:
抽象类 - Sandwich
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public abstract class Sandwich { public final void make () { cutBread(); addMeat(); addCondiments(); addVegetables(); if (customerWantsCheese()) { addCheese(); } wrapSandwich(); } void cutBread () { System.out.println("Bread is sliced." ); } abstract void addMeat () ; abstract void addCondiments () ; void addVegetables () { System.out.println("Adding vegetables." ); } boolean customerWantsCheese () { return true ; } void addCheese () { System.out.println("Adding Cheese." ); } void wrapSandwich () { System.out.println("Wrapping the sandwich." ); } }
具体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class HamSandwich extends Sandwich { @Override void addMeat () { System.out.println("Adding ham." ); } @Override void addCondiments () { System.out.println("Adding mayo and mustard." ); } @Override boolean customerWantsCheese () { return false ; } }
1 2 3 4 5 6 7 8 9 10 11 public class TurkeySandwich extends Sandwich { @Override void addMeat () { System.out.println("Adding turkey." ); } @Override void addCondiments () { System.out.println("Adding ketchup." ); } }
使用模板方法模式
1 2 3 4 5 6 7 8 9 10 11 12 public class SandwichMaker { public static void main (String[] args) { Sandwich hamSandwich = new HamSandwich (); System.out.println("Making Ham Sandwich:" ); hamSandwich.make(); System.out.println(); Sandwich turkeySandwich = new TurkeySandwich (); System.out.println("Making Turkey Sandwich:" ); turkeySandwich.make(); } }
在此示例中,Sandwich
抽象类定义了制作三明治的基本步骤。该类中实现了一些方法,如 cutBread
和 wrapSandwich
,它们对所有子类都是通用的。同时,一些抽象方法,如 addMeat
和 addCondiments
,需要具体子类去实现。我们还提供了一个钩子方法 customerWantsCheese
,允许子类覆盖默认行为。
我们创建了两个具体三明治子类:HamSandwich
和 TurkeySandwich
。这些子类实现了抽象方法,以便对特定类型的三明治调整步骤。我们在 SandwichMaker
类中实例化这些子类并调用 make
方法。make
方法在父类 Sandwich
中定义,并依次调用基本步骤。子类可以根据需要覆写这些方法,从而实现特定行为。
访问者模式(Visitor): - 优点:将操作与数据结构分离,增加新操作不修改数据结构。 - 缺点:增加新的数据结构需要修改现有的操作类,违反开闭原则。
访问者模式是一种行为设计模式,允许你在不改变类的前提下定义关于这些类的新操作。下面是一个以计算机硬件组件为例的完整访问者模式示例:
元素接口 - ComputerPart
1 2 3 public interface ComputerPart { void accept (ComputerPartVisitor computerPartVisitor) ; }
具体元素类
1 2 3 4 5 6 public class Keyboard implements ComputerPart { @Override public void accept (ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this ); } }
1 2 3 4 5 6 public class Monitor implements ComputerPart { @Override public void accept (ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this ); } }
1 2 3 4 5 6 public class Mouse implements ComputerPart { @Override public void accept (ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Computer implements ComputerPart { ComputerPart[] parts; public Computer () { parts = new ComputerPart [] { new Mouse (), new Keyboard (), new Monitor () }; } @Override public void accept (ComputerPartVisitor computerPartVisitor) { for (int i = 0 ; i < parts.length; i++) { parts[i].accept(computerPartVisitor); } computerPartVisitor.visit(this ); } }
访问者接口 - ComputerPartVisitor
1 2 3 4 5 6 public interface ComputerPartVisitor { void visit (Computer computer) ; void visit (Mouse mouse) ; void visit (Keyboard keyboard) ; void visit (Monitor monitor) ; }
具体访问者类 - ComputerPartDisplayVisitor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class ComputerPartDisplayVisitor implements ComputerPartVisitor { @Override public void visit (Computer computer) { System.out.println("Displaying Computer." ); } @Override public void visit (Mouse mouse) { System.out.println("Displaying Mouse." ); } @Override public void visit (Keyboard keyboard) { System.out.println("Displaying Keyboard." ); } @Override public void visit (Monitor monitor) { System.out.println("Displaying Monitor." ); } }
使用访问者模式
1 2 3 4 5 6 public class VisitorPatternDemo { public static void main (String[] args) { ComputerPart computer = new Computer (); computer.accept(new ComputerPartDisplayVisitor ()); } }
在上面的示例中,我们定义了一个 ComputerPart
接口以及几个具体的组件类。这些组件实现了 ComputerPart
接口,它仅包含一个 accept
方法,用于接受访问者对象。
接下来,我们定义了 ComputerPartVisitor
接口,它有四个不同的 visit
方法,分别处理不同类型的组件。然后创建一个具体的访问者类 ComputerPartDisplayVisitor
,它实现了 ComputerPartVisitor
接口。在这个类中,我们可以针对不同的计算机组件执行不同的操作,这些操作与组件类本身是解耦的。
最后,在 VisitorPatternDemo
中,我们创建了一个计算机元素对象,并用具体的访问者 ComputerPartDisplayVisitor
来访问它。我们可以随时创建更多的具体访问者类来处理组件对象,而无需修改组件类的实现。这使得添加新功能更加灵活,且不会破坏现有代码的封装性。
__END__