设计模式专题 主要是代码复用、简洁 ,经过前辈总结的通用 的一套方法设计模版,分为 创建着模式、行为模式、结构模式
创建者模式: 简单工厂、工厂方法、抽象工厂、单例、建造者模式、原型模式 
行为模式:观察者模式、迭代器模式、命令模式、状态模式、策略模式、责任链模式、备忘录模式 、解释器模式、*中介者模式 
结构模式: 代理模式、装饰模式、门面模式、组合模式、适配器模式、享元模式、桥接模式 
创建型模式(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__