常见的23种设计模式

这篇具有很好参考价值的文章主要介绍了常见的23种设计模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

常见的设计模式有23种,它们分别是:

1. 工厂方法模式(Factory Method Pattern)
2. 抽象工厂模式(Abstract Factory Pattern)
3. 单例模式(Singleton Pattern)
4. 建造者模式(Builder Pattern)
5. 原型模式(Prototype Pattern)
6. 适配器模式(Adapter Pattern)
7. 桥接模式(Bridge Pattern)
8. 过滤器模式(Filter Pattern)
9. 组合模式(Composite Pattern)
10. 装饰器模式(Decorator Pattern)
11. 外观模式(Facade Pattern)
12. 享元模式(Flyweight Pattern)
13. 代理模式(Proxy Pattern)
14. 责任链模式(Chain of Responsibility Pattern)
15. 命令模式(Command Pattern)
16. 解释器模式(Interpreter Pattern)
17. 迭代器模式(Iterator Pattern)
18. 中介者模式(Mediator Pattern)
19. 备忘录模式(Memento Pattern)
20. 观察者模式(Observer Pattern)
21. 状态模式(State Pattern)
22. 策略模式(Strategy Pattern)
23. 模板方法模式(Template Method Pattern)

它们分为三类:创建型模式、结构型模式和行为型模式。

下面将分别介绍每一种模式,并提供Java代码示例。

1. 创建型模式

1.1 工厂方法模式(Factory Method Pattern)

工厂方法模式是一种用于创建对象的设计模式,它将对象的创建委托给子类来处理。

interface Product {
    void use();
}

class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Using product A");
    }
}

class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Using product B");
    }
}

interface Factory {
    Product createProduct();
}

class ConcreteFactoryA implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

class ConcreteFactoryB implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

public class FactoryMethodDemo {
    public static void main(String[] args) {
        Factory factory = new ConcreteFactoryA();
        Product product = factory.createProduct();
        product.use();  // Output: Using product A

        factory = new ConcreteFactoryB();
        product = factory.createProduct();
        product.use();  // Output: Using product B
    }
}

1.2 抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式是一种类似于工厂方法模式的设计模式,但它不仅可以创建单个对象,还可以创建产品族。

interface Button {
    void click();
}

class WindowsButton implements Button {
    @Override
    public void click() {
        System.out.println("Windows button clicked");
    }
}

class MacButton implements Button {
    @Override
    public void click() {
        System.out.println("Mac button clicked");
    }
}

interface Checkbox {
    void check();
}

class WindowsCheckbox implements Checkbox {
    @Override
    public void check() {
        System.out.println("Windows checkbox checked");
    }
}

class MacCheckbox implements Checkbox {
    @Override
    public void check() {
        System.out.println("Mac checkbox checked");
    }
}

interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

class WindowsGUIFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }

    @Override
    public Checkbox createCheckbox() {
        return new WindowsCheckbox();
    }
}

class MacGUIFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new MacButton();
    }

    @Override
    public Checkbox createCheckbox() {
        return new MacCheckbox();
    }
}

public class AbstractFactoryDemo {
    public static void main(String[] args) {
        GUIFactory factory = new WindowsGUIFactory();
        Button button = factory.createButton();
        button.click();  // Output: Windows button clicked

        Checkbox checkbox = factory.createCheckbox();
        checkbox.check();  // Output: Windows checkbox checked

        factory = new MacGUIFactory();
        button = factory.createButton();
        button.click();  // Output: Mac button clicked

        checkbox = factory.createCheckbox();
        checkbox.check();  // Output: Mac checkbox checked
    }
}

1.3 单例模式(Singleton Pattern)

单例模式是一种保证一个类只有一个实例的设计模式。

class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    public void showMessage() {
        System.out.println("Hello World!");
    }
}

public class SingletonDemo {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        singleton.showMessage();  // Output: Hello World!
    }
}

1.4 建造者模式(Builder Pattern)

建造者模式是一种将一个复杂对象的构建过程与其表示相分离的设计模式,使得同样的构建过程可以创建不同的表示。

class Product {
    private int partA;
    private String partB;
    private boolean partC;

    public int getPartA() {
        return partA;
    }

    public void setPartA(int partA) {
        this.partA = partA;
    }

    public String getPartB() {
        return partB;
    }

    public void setPartB(String partB) {
        this.partB = partB;
    }

    public boolean isPartC() {
        return partC;
    }

    public void setPartC(boolean partC) {
        this.partC = partC;
    }
}

interface Builder {
    void buildPartA(int value);
    void buildPartB(String value);
    void buildPartC(boolean value);
    Product getResult();
}

class ConcreteBuilder implements Builder {
    private Product product;

    public ConcreteBuilder() {
        product = new Product();
    }

    @Override
    public void buildPartA(int value) {
        product.setPartA(value);
    }

    @Override
    public void buildPartB(String value) {
        product.setPartB(value);
    }

    @Override
    public void buildPartC(boolean value) {
        product.setPartC(value);
    }

    @Override
    public Product getResult() {
        return product;
    }
}

class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public void construct() {
        builder.buildPartA(1);
        builder.buildPartB("test");
        builder.buildPartC(true);
    }
}

public class BuilderDemo {
    public static void main(String[] args) {
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        director.construct();
        Product product = builder.getResult();

        System.out.println(product.getPartA());  // Output: 1
        System.out.println(product.getPartB());  // Output: test
        System.out.println(product.isPartC());   // Output: true
    }
}

1.5 原型模式(Prototype Pattern)

原型模式是一种通过复制现有对象来创建新对象的设计模式。

abstract class Shape implements Cloneable {
    private String id;
    protected String type;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public abstract void draw();

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

class Rectangle extends Shape {
    public Rectangle() {
        type = "Rectangle";
    }

    @Override
    public void draw() {
        System.out.println("Drawing a rectangle");
    }
}

class Circle extends Shape {
    public Circle() {
        type = "Circle";
    }

    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

public class PrototypeDemo {
    private static Map<String, Shape> shapeMap = new HashMap<>();

    static {
        shapeMap.put("rectangle", new Rectangle());
        shapeMap.put("circle", new Circle());
    }

    public static Shape getShape(String type) throws CloneNotSupportedException {
        return (Shape) shapeMap.get(type).clone();
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        Shape shape1 = getShape("rectangle");
        shape1.draw();  // Output: Drawing a rectangle

        Shape shape2 = getShape("circle");
        shape2.draw();  // Output: Drawing a circle
    }
}

2. 结构型设计模式

2.1 适配器模式(Adapter Pattern)

将一个接口转换成客户希望的另一个接口,使接口不兼容的类可以一起工作。

public interface MediaPlayer {
   public void play(String audioType, String fileName);
}

public interface AdvancedMediaPlayer {    
   public void playVlc(String fileName);
   public void playMp4(String fileName);
}

public class VlcPlayer implements AdvancedMediaPlayer{
   @Override
   public void playVlc(String fileName) {
      System.out.println("Playing vlc file. Name: "+ fileName);        
   }

   @Override
   public void playMp4(String fileName) {
      //什么也不做
   }
}

public class Mp4Player implements AdvancedMediaPlayer{

   @Override
   public void playVlc(String fileName) {
      //什么也不做
   }

   @Override
   public void playMp4(String fileName) {
      System.out.println("Playing mp4 file. Name: "+ fileName);        
   }
}

public class MediaAdapter implements MediaPlayer {

   AdvancedMediaPlayer advancedMusicPlayer;

   public MediaAdapter(String audioType){
      if(audioType.equalsIgnoreCase("vlc") ){
         advancedMusicPlayer = new VlcPlayer();           
      }else if (audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer = new Mp4Player();
      }  
   }

   @Override
   public void play(String audioType, String fileName) {

      if(audioType.equalsIgnoreCase("vlc")){
         advancedMusicPlayer.playVlc(fileName);
      }
      else if(audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer.playMp4(fileName);
      }
   }
}

public class AudioPlayer implements MediaPlayer {
   MediaAdapter mediaAdapter; 

   @Override
   public void play(String audioType, String fileName) {    

      if(audioType.equalsIgnoreCase("mp3")){
         System.out.println("Playing mp3 file. Name: " + fileName);  
      } 
      else if(audioType.equalsIgnoreCase("vlc") 
         || audioType.equalsIgnoreCase("mp4")){
         mediaAdapter = new MediaAdapter(audioType);
         mediaAdapter.play(audioType, fileName);
      }
      else{
         System.out.println("Invalid media. " + audioType + " format not supported");
      }
   }   
}

public class AdapterPatternDemo {
   public static void main(String[] args) {
      AudioPlayer audioPlayer = new AudioPlayer();

      audioPlayer.play("mp3", "beyond the horizon.mp3");
      audioPlayer.play("mp4", "alone.mp4");
      audioPlayer.play("vlc", "far far away.vlc");
      audioPlayer.play("avi", "mind me.avi");
   }
}

2.2 桥接模式(Bridge Pattern)

将抽象和实现解耦,使它们可以独立地变化。

public interface DrawAPI {
   public void drawCircle(int radius, int x, int y);
}

public class RedCircle implements DrawAPI {
   @Override
   public void drawCircle(int radius, int x, int y) {
      System.out.println("Drawing Circle[ color: red, radius: "
         + radius +", x: " +x+", "+ y +"]");
   }
}

public class GreenCircle implements DrawAPI {
   @Override
   public void drawCircle(int radius, int x, int y) {
      System.out.println("Drawing Circle[ color: green, radius: "
         + radius +", x: " +x+", "+ y +"]");
   }
}

public abstract class Shape {
   protected DrawAPI drawAPI;
   
   protected Shape(DrawAPI drawAPI){
      this.drawAPI = drawAPI;
   }
   public abstract void draw(); 
}

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;
   }

   public void draw() {
      drawAPI.drawCircle(radius,x,y);
   }
}

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();
   }
}

2.3 过滤器模式(Filter Pattern)

它允许按照某些标准筛选一组对象。该模式的主要思想是将数据和操作分离,从而提高系统的可扩展性。过滤器模式通常使用一个包含多个标准的过滤器链来对对象进行过滤。

举个例子,在一个商店中,我们需要展示所有颜色为红色并且价格低于10元的商品,可以通过过滤器模式实现。首先,我们定义一个商品类Product,并在其中定义了商品的属性:名称、价格、颜色等。然后,我们定义一个过滤器接口Criteria,其中包含了一个符合标准的方法meetCriteria()。最后,我们定义两个具体的过滤器实现类ColorCriteria和PriceCriteria,分别用于根据颜色和价格来过滤商品。

以下是Java代码示例:

// 商品类
public class Product {
    private String name;
    private double price;
    private String color;

    public Product(String name, double price, String color) {
        this.name = name;
        this.price = price;
        this.color = color;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public String getColor() {
        return color;
    }
}

// 过滤器接口
public interface Criteria {
    List<Product> meetCriteria(List<Product> products);
}

// 按颜色过滤器
public class ColorCriteria implements Criteria {
    private String color;

    public ColorCriteria(String color) {
        this.color = color;
    }

    @Override
    public List<Product> meetCriteria(List<Product> products) {
        List<Product> result = new ArrayList<>();
        for (Product product : products) {
            if (product.getColor().equals(color)) {
                result.add(product);
            }
        }
        return result;
    }
}

// 按价格过滤器
public class PriceCriteria implements Criteria {
    private double price;

    public PriceCriteria(double price) {
        this.price = price;
    }

    @Override
    public List<Product> meetCriteria(List<Product> products) {
        List<Product> result = new ArrayList<>();
        for (Product product : products) {
            if (product.getPrice() < price) {
                result.add(product);
            }
        }
        return result;
    }
}

// 测试代码
public class Test {
    public static void main(String[] args) {
        List<Product> products = new ArrayList<>();
        products.add(new Product("apple", 5.0, "red"));
        products.add(new Product("banana", 3.0, "yellow"));
        products.add(new Product("orange", 8.0, "orange"));
        products.add(new Product("watermelon", 12.0, "green"));

        Criteria colorCriteria = new ColorCriteria("red");
        Criteria priceCriteria = new PriceCriteria(10.0);

        List<Product> redProducts = colorCriteria.meetCriteria(products);
        System.out.println("红色商品:");
        for (Product product : redProducts) {
            System.out.println(product.getName());
        }

        List<Product> cheapProducts = priceCriteria.meetCriteria(products);
        System.out.println("低价商品:");
        for (Product product : cheapProducts) {
            System.out.println(product.getName());
        }
    }
}

2.4 组合模式(Composite Pattern)

将对象组合成树形结构以表示“部分-整体”的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。

public interface Employee {
   public void add(Employee employee);
   public void remove(Employee employee);
   public Employee getChild(int i);
   public String getName();
   public double getSalary();
   public void print();
}

public class Developer implements Employee {

   private String name;
   private double salary;

   public Developer(String name,double salary){
      this.name = name;
      this.salary = salary;
   }

   @Override
   public void add(Employee employee) {
     //该方法为叶子节点,不需要实现
   }

   @Override
   public Employee getChild(int i) {
     //该方法为叶子节点,不需要实现
     return null;
   }

   @Override
   public String getName() {
      return name;
   }

   @Override
   public double getSalary() {
      return salary;
   }

   @Override
   public void print() {
      System.out.println("-------------");
      System.out.println("Name ="+getName());
      System.out.println("Salary ="+getSalary());
      System.out.println("-------------");
   }

   @Override
   public void remove(Employee employee) {
     //该方法为叶子节点,不需要实现
   }

}

public class Manager implements Employee {

   private String name;
   private double salary;

   public Manager(String name,double salary){
      this.name = name;
      this.salary = salary;
   }

   List<Employee> employees = new ArrayList<Employee>();

   @Override
   public void add(Employee employee) {
      employees.add(employee);
   }

   @Override
   public Employee getChild(int i) {
      return employees.get(i);
   }

   @Override
   public String getName() {
      return name;
   }

   @Override
   public double getSalary() {
      return salary;
   }

   @Override
   public void print() {
      System.out.println("-------------");
      System.out.println("Name ="+getName());
      System.out.println("Salary ="+getSalary());
      System.out.println("-------------");

      for (Employee employee : employees) {
         employee.print();
      }
   }

   @Override
   public void remove(Employee employee) {
      employees.remove(employee);
   }

}

public class CompositePatternDemo {
   public static void main(String[] args) {
   
      Employee emp1 = new Developer("John", 10000.0);
      Employee emp2 = new Developer("David", 15000.0);
      Employee manager1 = new Manager("Daniel",25000.0);
      manager1.add(emp1);
      manager1.add(emp2);
      Employee emp3 = new Developer("Michael", 20000.0);
      Manager generalManager = new Manager("Mark", 50000.0);
      generalManager.add(emp3);
      generalManager.add(manager1);
      generalManager.print();
   }
}

2.5 装饰器模式(Decorator Pattern)

动态地将责任附加到对象上。若要扩展功能,装饰器提供了比继承更有弹性的替代方案。

public interface Shape {
   void draw();
}

public class Rectangle implements Shape {

   @Override
   public void draw() {
      System.out.println("Shape: Rectangle");
   }
}

public class Circle implements Shape {

   @Override
   public void draw() {
      System.out.println("Shape: Circle");
   }
}

public abstract class ShapeDecorator implements Shape {
   protected Shape decoratedShape;

   public ShapeDecorator(Shape decoratedShape){
      this.decoratedShape = decoratedShape;
   }

   public void draw(){
      decoratedShape.draw();
   }   
}

public class RedShapeDecorator extends ShapeDecorator {

   public RedShapeDecorator(Shape decoratedShape) {
      super(decoratedShape);        
   }

   @Override
   public void draw() {
      decoratedShape.draw();           
      setRedBorder(decoratedShape);
   }

   private void setRedBorder(Shape decoratedShape){
      System.out.println("Border Color: Red");
   }
}

public class DecoratorPatternDemo {
   public static void main(String[] args) {

      Shape circle = new Circle();

      Shape redCircle = new RedShapeDecorator(new Circle());

      Shape redRectangle = new RedShapeDecorator(new Rectangle());
      System.out.println("Circle with normal border");
      circle.draw();

      System.out.println("\nCircle of red border");
      redCircle.draw();

      System.out.println("\nRectangle of red border");
      redRectangle.draw();
   }
}

2.6 外观模式(Facade Pattern)

为子系统中的一组接口提供一个一致界面,定义了一个高层接口,这个接口使得这一子系统更加容易使用。

public interface Shape {
   void draw();
}

public class Rectangle implements Shape {

   @Override
   public void draw() {
      System.out.println("Rectangle::draw()");
   }
}

public class Square implements Shape {

   @Override
   public void draw() {
      System.out.println("Square::draw()");
   }
}

public class Circle implements Shape {

   @Override
   public void draw() {
      System.out.println("Circle::draw()");
   }
}

public class ShapeMaker {
   private Shape circle;
   private Shape rectangle;
   private Shape square;

   public ShapeMaker() {
      circle = new Circle();
      rectangle = new Rectangle();
      square = new Square();
   }

   public void drawCircle(){
      circle.draw();
   }
   public void drawRectangle(){
      rectangle.draw();
   }
   public void drawSquare(){
      square.draw();
   }
}

public class FacadePatternDemo {
   public static void main(String[] args) {
      ShapeMaker shapeMaker = new ShapeMaker();

      shapeMaker.drawCircle();
      shapeMaker.drawRectangle();
      shapeMaker.drawSquare();        
   }
}

2.7 享元模式(Flyweight Pattern)

它通过共享对象来减少内存使用和提高性能。该模式的主要思想是将对象分为可共享部分和不可共享部分,将可共享部分抽象出来作为一个享元类,多个具有相同状态的对象可以共享一个享元对象。

举个例子,在一个游戏中,我们需要绘制大量的树,每棵树都有相同的树干和枝叶,只有位置和大小不同。如果每棵树都创建一个新的树干和枝叶对象,将会浪费大量内存。通过享元模式,我们可以创建一个TreeFlyweight类来表示树干和枝叶,多个Tree对象可以共享同一个TreeFlyweight对象。

以下是Java代码示例:

// 树干和枝叶类
public class TreeFlyweight {
    private String type;
    private Color color;

    public TreeFlyweight(String type, Color color) {
        this.type = type;
        this.color = color;
    }

    public void draw(Point location, int size) {
        // 绘制树干和枝叶
    }
}

// 树类
public class Tree {
    private Point location;
    private int size;
    private TreeFlyweight flyweight;

    public Tree(Point location, int size, TreeFlyweight flyweight) {
        this.location = location;
        this.size = size;
        this.flyweight = flyweight;
    }

    public void draw() {
        flyweight.draw(location, size);
    }
}

// 测试代码
public class Test {
    public static void main(String[] args) {
        List<Tree> trees = new ArrayList<>();

        TreeFlyweight flyweight = new TreeFlyweight("oak", Color.GREEN);

        // 创建10棵相同类型的树
        for (int i = 0; i < 10; i++) {
            Point location = new Point((int) (Math.random() * 100), (int) (Math.random() * 100));
            int size = (int) (Math.random() * 10) + 1;
            Tree tree = new Tree(location, size, flyweight);
            trees.add(tree);
        }

        // 绘制所有树
        for (Tree tree : trees) {
            tree.draw();
        }
    }
}

2.8 代理模式(Proxy Pattern)

代理模式(Proxy Pattern)是一种结构型设计模式,它允许对象提供替代品或者代理来控制对这个对象的访问。代理对象可以在客户端和目标对象之间起到中介作用,避免直接访问目标对象带来的不必要复杂性。

示例

下面是一个简单的代理模式的示例,假设我们有一个接口和一个实现该接口的具体类,此外还有一个代理类,当客户端请求展示图片时,可以通过代理类来展示图片,代理类会在需要时创建一个真实的对象来进行展示。

// Image接口,定义图片展示方法
public interface Image {
    void display();
}

// RealImage类,实现Image接口
public class RealImage implements Image {
    private String fileName;

    public RealImage(String fileName) {
        this.fileName = fileName;
        loadFromDisk(fileName);
    }

    @Override
    public void display() {
        System.out.println("Displaying " + fileName);
    }

    private void loadFromDisk(String fileName) {
        System.out.println("Loading " + fileName);
    }
}

// ProxyImage类,实现Image接口,并持有一个RealImage对象
public class ProxyImage implements Image {
    private RealImage realImage;
    private String fileName;

    public ProxyImage(String fileName) {
        this.fileName = fileName;
    }

    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(fileName);
        }
        realImage.display();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Image image = new ProxyImage("test.jpg");
        image.display();
    }
}

分析

在上面的例子中,类是真实的图片展示类,类是代理类。当客户端请求展示图片时,会通过代理类来进行操作,代理类会在需要时创建一个真实的对象来进行展示。

优点:

  • 代理模式对客户端隐藏了目标对象的具体实现,使得客户端可以更加简单地访问目标对象。
  • 代理模式可以在不改变目标对象的情况下扩展目标对象的功能,例如可以在代理类中增加一些缓存等逻辑。

缺点:

  • 代理模式会增加系统复杂度,因为需要增加一些代理类。

3.行为型模式

3.1 责任链模式(Chain of Responsibility Pattern)

它使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

示例

下面是一个简单的责任链模式的示例,假设我们有一组处理日志信息的类,每个类都可以处理某一种类型的日志信息,如果当前类不能处理该类型的日志信息,则会将其传递给下一个处理类来处理。

// AbstractLogger抽象类,定义日志处理方法和后继处理者
public abstract class AbstractLogger {
    public static int INFO = 1;
    public static int DEBUG = 2;
    public static int ERROR = 3;

    protected int level;
    protected AbstractLogger nextLogger;

    public void setNextLogger(AbstractLogger nextLogger) {
        this.nextLogger = nextLogger;
    }

    public void logMessage(int level, String message) {
        if (this.level <= level) {
            write(message);
        }
        if (nextLogger != null) {
            nextLogger.logMessage(level, message);
        }
    }

    abstract protected void write(String message);
}

// ConsoleLogger类,实现AbstractLogger抽象类
public class ConsoleLogger extends AbstractLogger {

    public ConsoleLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Standard Console::Logger: " + message);
    }
}

// ErrorLogger类,实现AbstractLogger抽象类
public class ErrorLogger extends AbstractLogger {

    public ErrorLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Error Console::Logger: " + message);
    }
}

// FileLogger类,实现AbstractLogger抽象类
public class FileLogger extends AbstractLogger {

    public FileLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("File::Logger: " + message);
    }
}

// 客户端代码
public class Client {
    private static AbstractLogger getChainOfLoggers() {
        AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
        AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
        AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);

        errorLogger.setNextLogger(fileLogger);
        fileLogger.setNextLogger(consoleLogger);

        return errorLogger;
    }

    public static void main(String[] args) {
        AbstractLogger loggerChain = getChainOfLoggers();

        loggerChain.logMessage(AbstractLogger.INFO, "This is an information.");

        loggerChain.logMessage(AbstractLogger.DEBUG, "This is a debug level information.");

        loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information.");
    }
}

分析

在上面的例子中,每个日志处理类都继承自抽象类,并且都可以处理某一种类型的日志信息。如果当前类不能处理该类型的日志信息,则会将其传递给下一个处理类来处理。AbstractLogger

优点:

  • 责任链模式可以避免请求发送者和接收者之间的耦合关系。
  • 责任链模式可以动态地增加或删除处理器。

缺点:

  • 责任链模式可能会导致系统性能下降,因为每个请求都必须经过多个处理器。

3.2 命令模式(Command Pattern)

它将请求封装成一个对象,并且可以让你使用不同的请求、队列或者日志来参数化其他对象。命令模式还支持撤销操作。

示例

下面是一个简单的命令模式的示例,假设我们有一组电视机遥控器,这些遥控器可以用来控制电视机的开关、音量等操作。我们把这些操作都封装成了具体的命令类,并且通过一个类来执行这些命令。RemoteControl

// Command接口,定义命令执行方法
public interface Command {
    void execute();
}

// LightOnCommand类,实现Command接口
public class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.turnOn();
    }
}

// LightOffCommand类,实现Command接口
public class LightOffCommand implements Command {
    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.turnOff();
    }
}

// RemoteControl类,用于执行命令
public class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Light light = new Light();

        Command turnOnCommand = new LightOnCommand(light);
        Command turnOffCommand = new LightOffCommand(light);

        RemoteControl remoteControl = new RemoteControl();

        remoteControl.setCommand(turnOnCommand);
        remoteControl.pressButton();

        remoteControl.setCommand(turnOffCommand);
        remoteControl.pressButton();
    }
}

分析

在上面的例子中,我们把每个电视机操作都封装成了具体的命令类,并且通过一个类来执行这些命令。客户端只需要将命令对象传递给类即可。

优点:

  • 命令模式可以将命令请求者和命令实现者分离。
  • 命令模式支持撤销操作。

缺点:

  • 命令模式可能会导致系统性能下降

3.3 解释器模式(Interpreter Pattern)

它定义了一种语言文法,并且定义了一个解释器用于解释该语言中的句子。这种模式通常用于需要对语言进行解释的场景。

在解释器模式中,我们通常将语言中的每个句子表示为抽象语法树中的节点。解释器模式通过递归地遍历抽象语法树来解释每个句子。

以下是一个简单的解释器模式的示例:

// 抽象表达式接口
interface Expression {
    boolean interpret(String context);
}

// 终结符表达式
class TerminalExpression implements Expression {
    private String data;

    public TerminalExpression(String data) {
        this.data = data;
    }

    @Override
    public boolean interpret(String context) {
        if (context.contains(data)) {
            return true;
        }
        return false;
    }
}

// 非终结符表达式
class OrExpression implements Expression {
    private Expression expr1;
    private Expression expr2;

    public OrExpression(Expression expr1, Expression expr2) {
        this.expr1 = expr1;
        this.expr2 = expr2;
    }

    @Override
    public boolean interpret(String context) {
        return expr1.interpret(context) || expr2.interpret(context);
    }
}

// 非终结符表达式
class AndExpression implements Expression {
    private Expression expr1;
    private Expression expr2;

    public AndExpression(Expression expr1, Expression expr2) {
        this.expr1 = expr1;
        this.expr2 = expr2;
    }

    @Override
    public boolean interpret(String context) {
        return expr1.interpret(context) && expr2.interpret(context);
    }
}

// 客户端代码
public class InterpreterClient {
    public static void main(String[] args) {
        Expression person1 = new TerminalExpression("Tom");
        Expression person2 = new TerminalExpression("Jerry");
        Expression isSingle = new OrExpression(person1, person2);

        Expression married = new TerminalExpression("married");
        Expression notMarried = new NotExpression(married);

        Expression isAvailable = new AndExpression(isSingle, notMarried);

        System.out.println(isAvailable.interpret("Tom")); // true
        System.out.println(isAvailable.interpret("Jerry")); // true
        System.out.println(isAvailable.interpret("Tom married")); // false
        System.out.println(isAvailable.interpret("Jerry married")); // false
    }
}

3.4 迭代器模式(Iterator Pattern)

它定义了一种访问集合对象中元素的方法,而不暴露该集合对象的内部表示。

在迭代器模式中,我们通常将集合对象分离出来,用一个迭代器对象来遍历集合中的元素。这样可以将集合对象和迭代算法分离开来,从而使得集合对象的内部表示发生变化时不影响使用该集合的客户端代码。

以下是一个简单的迭代器模式的示例:

// 迭代器接口
interface Iterator<T> {
    boolean hasNext();
    T next();
}

// 集合接口
interface Collection<T> {
    void add(T item);
    Iterator<T> iterator();
}

// 具体迭代器实现类
class ConcreteIterator<T> implements Iterator<T> {
    private Collection<T> collection;
    private int position = 0;

    public ConcreteIterator(Collection<T> collection) {
        this.collection = collection;
    }

    @Override
    public boolean hasNext() {
        return position < collection.size();
    }

    @Override
    public T next() {
        if (hasNext()) {
            return collection.get(position++);
        }
        return null;
    }
}

// 具体集合实现类
class ConcreteCollection<T> implements Collection<T> {
    private List<T> list = new ArrayList<>();

    @Override
    public void add(T item) {
        list.add(item);
    }

    @Override
    public Iterator<T> iterator() {
        return new ConcreteIterator<>(this);
    }

    public int size() {
        return list.size();
    }

    public T get(int index) {
        return list.get(index);
    }
}

// 客户端代码
public class IteratorClient {
    public static void main(String[] args) {
        Collection<String> collection = new ConcreteCollection<>();
        collection.add("A");
        collection.add("B");
        collection.add("C");

        Iterator<String> iterator = collection.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

3.5 中介者模式(mediaator pattern)

中介者模式通过封装一系列对象之间的交互,来降低其复杂度。中介者模式将系统从网状结构变成以中介者为中心的星形结构,每个对象不再和其他对象直接通信,而是通过中介者来通信。这样可以减少对象之间的耦合度,提高系统的可维护性、可扩展性。

示例代码如下:

// 抽象中介者
interface Mediator {
    void send(String message, Colleague colleague);
}

// 具体中介者
class ConcreteMediator implements Mediator {
    private ColleagueA colleagueA;
    private ColleagueB colleagueB;

    public void setColleagueA(ColleagueA colleagueA) {
        this.colleagueA = colleagueA;
    }

    public void setColleagueB(ColleagueB colleagueB) {
        this.colleagueB = colleagueB;
    }

    @Override
    public void send(String message, Colleague colleague) {
        if (colleague == colleagueA) {
            colleagueB.notify(message);
        } else {
            colleagueA.notify(message);
        }
    }
}

// 抽象同事类
abstract class Colleague {
    protected Mediator mediator;

    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }

    abstract void notify(String message);
}

// 具体同事类A
class ColleagueA extends Colleague {
    public ColleagueA(Mediator mediator) {
        super(mediator);
    }

    @Override
    void notify(String message) {
        System.out.println("ColleagueA received message: " + message);
    }

    public void send(String message) {
        mediator.send(message, this);
    }
}

// 具体同事类B
class ColleagueB extends Colleague {
    public ColleagueB(Mediator mediator) {
        super(mediator);
    }

    @Override
    void notify(String message) {
        System.out.println("ColleagueB received message: " + message);
    }

    public void send(String message) {
        mediator.send(message, this);
    }
}

// 应用场景
public class MediatorPatternDemo {
    public static void main(String[] args) {
        ConcreteMediator mediator = new ConcreteMediator();
        ColleagueA colleagueA = new ColleagueA(mediator);
        ColleagueB colleagueB = new ColleagueB(mediator);
        mediator.setColleagueA(colleagueA);
        mediator.setColleagueB(colleagueB);

        colleagueA.send("Hello, ColleagueB.");
        colleagueB.send("Hi, ColleagueA.");
    }
}

3.6 备忘录模式(Memento Pattern)

备忘录模式可以保存一个对象的内部状态,在需要回滚时能够恢复到之前的状态。备忘录模式通常包含三个角色:原发器、备忘录和负责人。

示例代码如下:

// 备忘录类
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 String getState() {
        return state;
    }

    public Memento saveStateToMemento() {
        return new Memento(state);
    }

    public void getStateFromMemento(Memento memento) {
        this.state = memento.getState();
    }
}

// 负责人类
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);
    }
}

// 应用场景
public class MementoPatternDemo {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();

        originator.setState("State #1");
        originator.setState("State #2");
        caretaker.add(originator.saveStateToMemento());

        originator.setState("State #3");
        caretaker.add(originator.saveStateToMemento());

        originator.setState("State #4");

        System.out.println("Current State: " + originator.getState());
        originator.getStateFromMemento(caretaker.get(0));
        System.out.println("First saved State: " + originator.getState());
        originator.getStateFromMemento(caretaker.get(1));
        System.out.println("Second saved State: " + originator.getState());
    }
}

3.7 观察者模式(Observer pattern)

观察者模式定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。

Java中典型的例子是java.util.Observable类和java.util.Observer接口。Observable类是主题,Observer接口是观察者。当主题状态发生变化时,它会调用Observer接口中的update()方法,通知所有观察者进行相应的处理。

以下是示例代码:文章来源地址https://www.toymoban.com/news/detail-471066.html

import java.util.Observable;
import java.util.Observer;

public class WeatherData extends Observable {
    private float temperature;
    private float humidity;
    private float pressure;

    public void measurementsChanged() {
        setChanged();
        notifyObservers();
    }

    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }

    public float getTemperature() {
        return temperature;
    }

    public float getHumidity() {
        return humidity;
    }

    public float getPressure() {
        return pressure;
    }
}

public class CurrentConditionsDisplay implements Observer {
    private float temperature;
    private float humidity;

    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof WeatherData) {
            WeatherData weatherData = (WeatherData) o;
            this.temperature = weatherData.getTemperature();
            this.humidity = weatherData.getHumidity();
            display();
        }
    }

    public void display() {
        System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
    }
}

public class Main {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay();
        weatherData.addObserver(currentConditionsDisplay);
        weatherData.setMeasurements(80, 65, 30.4f);
    }
}

 3.8 状态模式(State Pattern)

它允许对象在其内部状态发生改变时改变它的行为。这个模式将一个对象的状态从该对象中移出来,以便在需要时进行修改和管理。

举个例子,假设我们正在开发一个文本编辑器,它具有多种状态,如只读、编辑、选择等等。在不同的状态下,文本编辑器的行为应该是不同的。这时候可以使用状态模式来实现。

以下是一个简单的状态模式的Java代码示例,以文本编辑器为例:

// 状态接口
interface TextEditorState {
    void type(String words, TextEditor editor);
}

// 只读状态
class ReadOnlyState implements TextEditorState {
    @Override
    public void type(String words, TextEditor editor) {
        System.out.println("Sorry, the editor is in read-only mode.");
    }
}

// 编辑状态
class EditState implements TextEditorState {
    @Override
    public void type(String words, TextEditor editor) {
        System.out.println("Typing: " + words);
        editor.setContent(editor.getContent() + words);
    }
}

// 选择状态
class SelectState implements TextEditorState {
    @Override
    public void type(String words, TextEditor editor) {
        // 选择状态下不能输入文字
        System.out.println("Please select a range of text first.");
    }
}

// 文本编辑器类
class TextEditor {
    private String content = "";
    private TextEditorState state;

    public TextEditor() {
        this.state = new ReadOnlyState(); // 默认为只读状态
    }

    public void setState(TextEditorState state) {
        this.state = state;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void type(String words) {
        state.type(words, this);
    }
}

// 测试代码
public class StatePatternDemo {
    public static void main(String[] args) {
        TextEditor editor = new TextEditor();
        editor.type("Hello World!"); // 输出 "Sorry, the editor is in read-only mode."
        
        editor.setState(new EditState()); // 切换到编辑状态
        editor.type("This is editable now."); // 输出 "Typing: This is editable now."
        
        editor.setState(new SelectState()); // 切换到选择状态
        editor.type("Now I cannot type anything."); // 输出 "Please select a range of text first."
    }
}

在这个例子中,类是一个上下文对象,它维护着当前的状态,并将请求委托给当前状态处理。不同的状态实现了共同的接口,并在实现中改变了对象的行为。这样,当状态发生变化时,对象的行为也会相应地改变。

总体来说,状态模式可以让代码更加清晰,易于扩展和维护。

3.9 策略模式(Strategy Pattern)

它定义了一系列的算法,将每个算法都封装起来并使它们之间可以互换。

这种模式让算法的变化独立于使用算法的客户。

举个例子,我们有一个商场,里面有很多商品,折扣也不同。假设现在商场正在搞活动,所有商品打9折。但是,同时还有一些商品是特价商品,本身就有更低的价格。那么对于这些特价商品,我们不需要再打9折了。

这时候,我们就可以使用策略模式来实现这个功能。首先,定义一个抽象类 DiscountStrategy,其中包含一个 calculateDiscount 方法,用于计算不同商品的折扣。然后,分别实现 NormalDiscount 和 SpecialDiscount 两个具体策略类,分别对应普通商品打折和特价商品不打折。最后,在客户端中根据不同的商品选择不同的策略即可。

下面是代码示例:

// 抽象策略类
interface DiscountStrategy {
    double calculateDiscount(double price);
}

// 具体策略类:普通商品打9折
class NormalDiscount implements DiscountStrategy {
    @Override
    public double calculateDiscount(double price) {
        return price * 0.9;
    }
}

// 具体策略类:特价商品不打折
class SpecialDiscount implements DiscountStrategy {
    @Override
    public double calculateDiscount(double price) {
        return price;
    }
}

// 上下文类
class ShoppingCart {
    private List<Double> items = new ArrayList<>();
    private DiscountStrategy discountStrategy;

    public void addItem(double price) {
        items.add(price);
    }

    public void setDiscountStrategy(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }

    public double getTotal() {
        double sum = 0;
        for (double item : items) {
            sum += item;
        }
        if (discountStrategy != null) {
            sum = discountStrategy.calculateDiscount(sum);
        }
        return sum;
    }
}

// 客户端代码
public class StrategyDemo {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
        cart.addItem(100);
        cart.addItem(200);
        cart.addItem(300);

        // 普通商品打9折
        cart.setDiscountStrategy(new NormalDiscount());
        System.out.println("Total price after normal discount: " + cart.getTotal());

        // 特价商品不打折
        cart.setDiscountStrategy(new SpecialDiscount());
        System.out.println("Total price after special discount: " + cart.getTotal());
    }
}

输出结果为:

Total price after normal discount: 540.0
Total price after special discount: 600.0

 3.10 模板方法模式

模板方法模式定义了一个算法的框架,将一些步骤延迟到子类中实现。在模板方法模式中,模板方法负责定义算法的流程,具体实现则由子类来完成。

Java中的经典例子是java.util.Collections.sort()方法。这个方法可以排序任何实现了Comparable接口的对象列表。在该方法内部,使用了Comparator接口来实现排序算法的策略,而排序过程的具体实现则延迟到了各自实现Comparable接口的类中。

以下是示例代码:

public abstract class AbstractSort<T extends Comparable<T>> {
    public abstract void sort(T[] array);

    protected boolean less(T v, T w) {
        return v.compareTo(w) < 0;
    }

    protected void swap(T[] array, int i, int j) {
        T temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

public class InsertionSort<T extends Comparable<T>> extends AbstractSort<T> {
    @Override
    public void sort(T[] array) {
        for (int i = 0; i < array.length; i++) {
            for (int j = i; j > 0 && less(array[j], array[j - 1]); j--) {
                swap(array, j, j - 1);
            }
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Integer[] array = {3, 1, 4, 1, 5, 9, 2, 6, 5};
        AbstractSort<Integer> sortAlgorithm = new InsertionSort<>();
        sortAlgorithm.sort(array);
        System.out.println(Arrays.toString(array));
    }
}

到了这里,关于常见的23种设计模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 永不磨灭的设计模式(23种设计模式全集)

    设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。 单一职责原则 里氏替换原则 依赖倒置原则 开闭原则 接口隔离原则 迪米特法则

    2024年02月08日
    浏览(26)
  • 设计模式(23)解释器模式

    一、介绍: 1、定义:解释器(Interpreter)模式是一种对象的行为模式。给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 2、组成结构: (1)AbstractExpression(抽象表达式):约定解释器的解释操作,主要是一个interpret()方

    2024年02月06日
    浏览(37)
  • 【23种设计模式】组合模式(八)

    组合模式 ,英文名称是: Composite Pattern 。当我们谈到这个模式的时候,有一个物件和这个模式很像,也符合这个模式要表达的意思,那就是“俄罗斯套娃”。“俄罗斯套娃”就是大的瓷器娃娃里面装着一个小的瓷器娃娃,小的瓷器娃娃里面再装着更小的瓷器娃娃,直到最后

    2024年02月09日
    浏览(34)
  • 【23种设计模式】组合模式(七)

    组合模式 ,英文名称是: Composite Pattern 。当我们谈到这个模式的时候,有一个物件和这个模式很像,也符合这个模式要表达的意思,那就是“俄罗斯套娃”。“俄罗斯套娃”就是大的瓷器娃娃里面装着一个小的瓷器娃娃,小的瓷器娃娃里面再装着更小的瓷器娃娃,直到最后

    2024年02月09日
    浏览(34)
  • 23种设计模式之:命令模式

    命令模式是一种行为设计模式,它将一个请求封装成一个对象,从而让你使用不同的请求、队列或者请求的日志来参数化其他对象。它也支持可撤销的操作。命令模式的关键是引入了抽象层——命令接口,具体命令实现该接口,执行操作的对象从执行具体操作的职责中解耦出

    2024年02月21日
    浏览(31)
  • 【23种设计模式】桥接模式(七)

    【 桥接模式 】是【 结构型 】设计模式的第二个模式,也有叫【桥模式】的,英文名称: Bridge Pattern 。 大家第一次看到这个名称会想到什么呢?我第一次看到这个模式根据名称猜肯定是连接什么东西的。因为桥在我们现实生活中经常是连接着A地和B地,再往后来发展,桥引

    2024年02月10日
    浏览(30)
  • 【23种设计模式】外观模式(十)

    外观模式 ,英文名称是: Facade Pattern 。我们先从名字上来理解一下“外观模式”。我看到了“外观”这个词语,就想到了“外表”这个词语,两者有着很相近的意思。就拿谈恋爱来说,“外表”很重要,如果第一眼看着很舒服、有眼缘,那就有交往下去的可能。如果长的“

    2024年02月08日
    浏览(37)
  • 【23种设计模式】享元模式【⭐】

    个人主页 :金鳞踏雨 个人简介 :大家好,我是 金鳞 ,一个初出茅庐的Java小白 目前状况 :22届普通本科毕业生,几经波折了,现在任职于一家国内大型知名日化公司,从事Java开发工作 我的博客 :这里是CSDN,是我学习技术,总结知识的地方。希望和各位大佬交流,共同进

    2024年02月09日
    浏览(35)
  • 【23种设计模式】原型模式(五)

    在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这就会增加创建类的复杂度和创建过程与客户代码复杂的耦合度。如果采用工厂模式来创建这样的实例对象的话,随着产品类的不

    2024年02月10日
    浏览(21)
  • 【23种设计模式】装饰器模式

    个人主页 :金鳞踏雨 个人简介 :大家好,我是 金鳞 ,一个初出茅庐的Java小白 目前状况 :22届普通本科毕业生,几经波折了,现在任职于一家国内大型知名日化公司,从事Java开发工作 我的博客 :这里是CSDN,是我学习技术,总结知识的地方。希望和各位大佬交流,共同进

    2024年02月07日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包