设计模式简述

2023-07-10  本文已影响0人  小成都人

设计模式分为三大类型,24种模式

创建型

单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

结构:

单例模式分为两种:

  1. 饿汉式-方式1(静态变量方式)

    /**
     * 饿汉式
     *      静态变量创建类的对象
     */
    public class Singleton {
        //私有构造方法
        private Singleton() {}
    
        //在成员位置创建该类的对象
        private static Singleton instance = new Singleton();
    
        //对外提供静态方法获取该对象
        public static Singleton getInstance() {
            return instance;
        }
    }
    

    说明:

    该方式在成员位置声明Singleton类型的静态变量,并创建Singleton类的对象instance。instance对象是随着类的加载而创建的。如果该对象足够大的话,而一直没有使用就会造成内存的浪费。

  1. 饿汉式-方式2(静态代码块方式)

    /**
     * 饿汉式
     *      在静态代码块中创建该类对象
     */
    public class Singleton {
    
        //私有构造方法
        private Singleton() {}
    
        //在成员位置创建该类的对象
        private static Singleton instance;
    
        static {
            instance = new Singleton();
        }
    
        //对外提供静态方法获取该对象
        public static Singleton getInstance() {
            return instance;
        }
    }
    

    <font color='red'>说明:</font>

    该方式在成员位置声明Singleton类型的静态变量,而对象的创建是在静态代码块中,也是对着类的加载而创建。所以和饿汉式的方式1基本上一样,当然该方式也存在内存浪费问题。

  1. 懒汉式-方式1(线程不安全)

    /**
     * 懒汉式
     *  线程不安全
     */
    public class Singleton {
        //私有构造方法
        private Singleton() {}
    
        //在成员位置创建该类的对象
        private static Singleton instance;
    
        //对外提供静态方法获取该对象
        public static Singleton getInstance() {
    
            if(instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    <font color='red'>说明:</font>

    从上面代码我们可以看出该方式在成员位置声明Singleton类型的静态变量,并没有进行对象的赋值操作,那么什么时候赋值的呢?当调用getInstance()方法获取Singleton类的对象的时候才创建Singleton类的对象,这样就实现了懒加载的效果。但是,如果是多线程环境,会出现线程安全问题。

  1. 懒汉式-方式2(线程安全)

    /**
     * 懒汉式
     *  线程安全
     */
    public class Singleton {
        //私有构造方法
        private Singleton() {}
    
        //在成员位置创建该类的对象
        private static Singleton instance;
    
        //对外提供静态方法获取该对象
        public static synchronized Singleton getInstance() {
    
            if(instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    <font color='red'>说明:</font>

    该方式也实现了懒加载效果,同时又解决了线程安全问题。但是在getInstance()方法上添加了synchronized关键字,导致该方法的执行效果特别低。从上面代码我们可以看出,其实就是在初始化instance的时候才会出现线程安全问题,一旦初始化完成就不存在了。

  1. 懒汉式-方式3(双重检查锁)

    再来讨论一下懒汉模式中加锁的问题,对于 getInstance() 方法来说,绝大部分的操作都是读操作,读操作是线程安全的,所以我们没必让每个线程必须持有锁才能调用该方法,我们需要调整加锁的时机。由此也产生了一种新的实现模式:双重检查锁模式

    /**
     * 双重检查方式
     */
    public class Singleton { 
    
        //私有构造方法
        private Singleton() {}
    
        private static Singleton instance;
    
       //对外提供静态方法获取该对象
        public static Singleton getInstance() {
         //第一次判断,如果instance不为null,不进入抢锁阶段,直接返回实例
            if(instance == null) {
                synchronized (Singleton.class) {
                    //抢到锁之后再次判断是否为null
                    if(instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    双重检查锁模式是一种非常好的单例实现模式,解决了单例、性能、线程安全问题,上面的双重检测锁模式看上去完美无缺,其实是存在问题,在多线程的情况下,可能会出现空指针问题,出现问题的原因是JVM在实例化对象的时候会进行优化和指令重排序操作。

    要解决双重检查锁模式带来空指针异常的问题,只需要使用 volatile 关键字, volatile 关键字可以保证可见性和有序性。

    /**
     * 双重检查方式
     */
    public class Singleton {
    
        //私有构造方法
        private Singleton() {}
    
        private static volatile Singleton instance;
    
       //对外提供静态方法获取该对象
        public static Singleton getInstance() {
         //第一次判断,如果instance不为null,不进入抢锁阶段,直接返回实际
            if(instance == null) {
                synchronized (Singleton.class) {
                    //抢到锁之后再次判断是否为空
                    if(instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    <font color="red">小结:</font>

    添加 volatile 关键字之后的双重检查锁模式是一种比较好的单例实现模式,能够保证在多线程的情况下线程安全也不会有性能问题。

  1. 懒汉式-方式4(静态内部类方式)

    静态内部类单例模式中实例由内部类创建,由于 JVM 在加载外部类的过程中, 是不会加载静态内部类的, 只有内部类的属性/方法被调用时才会被加载, 并初始化其静态属性。静态属性由于被 static 修饰,保证只被实例化一次,并且严格保证实例化顺序。

    /**
     * 静态内部类方式
     */
    public class Singleton {
    
        //私有构造方法
        private Singleton() {}
    
        private static class SingletonHolder {
            private static final Singleton INSTANCE = new Singleton();
        }
    
        //对外提供静态方法获取该对象
        public static Singleton getInstance() {
            return SingletonHolder.INSTANCE;
        }
    }
    

    <font color='red'>说明:</font>

    第一次加载Singleton类时不会去初始化INSTANCE,只有第一次调用getInstance,虚拟机加载SingletonHolder

    并初始化INSTANCE,这样不仅能确保线程安全,也能保证 Singleton 类的唯一性。

    <font color="red">小结:</font>

    静态内部类单例模式是一种优秀的单例模式,是开源项目中比较常用的一种单例模式。在没有加任何锁的情况下,保证了多线程下的安全,并且没有任何性能影响和空间的浪费。

  1. 枚举方式

    枚举类实现单例模式是极力推荐的单例实现模式,因为枚举类型是线程安全的,并且只会装载一次,设计者充分的利用了枚举的这个特性来实现单例模式,枚举的写法非常简单,而且枚举类型是所用单例实现中唯一一种不会被破坏的单例实现模式。

    /**
     * 枚举方式
     */
    public enum Singleton {
        INSTANCE;
    }
    

    <font color='red'>说明:</font>

    枚举方式属于饿汉式方式。

简单工厂模式

介绍
简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,它提供了一个统一的接口来创建对象,但由工厂类来决定实例化哪一个类。简单工厂模式并不属于23种经典设计模式之一,但它是最简单、最常用的设计模式之一,适用于创建对象较少的情况下。

结构
简单工厂模式包含三个角色:

  1. 工厂(Factory): 负责创建对象的工厂类,通过传递不同的参数来创建不同的实例。
  2. 产品(Product): 抽象产品类,定义了产品的规范,描述了产品的属性和功能。
  3. 具体产品(Concrete Product): 实现了抽象产品类的具体子类。

示例
假设我们有一个简单的图形绘制程序,可以绘制圆形和矩形。我们使用简单工厂模式来创建不同的图形对象。

  1. 创建抽象图形类:
// 抽象图形类
interface Shape {
  void draw();
}

// 圆形类
class Circle implements Shape {
  @Override
  public void draw() {
      System.out.println("绘制圆形");
  }
}

// 矩形类
class Rectangle implements Shape {
  @Override
  public void draw() {
      System.out.println("绘制矩形");
  }
}
  1. 创建简单工厂类:
// 图形工厂类
class ShapeFactory {
    // 创建图形对象
    public static Shape createShape(String type) {
        if (type.equalsIgnoreCase("CIRCLE")) {
            return new Circle();
        } else if (type.equalsIgnoreCase("RECTANGLE")) {
            return new Rectangle();
        }
        return null;
    }
}

  1. 客户端使用:
// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建圆形
        Shape circle = ShapeFactory.createShape("CIRCLE");
        circle.draw();

        // 创建矩形
        Shape rectangle = ShapeFactory.createShape("RECTANGLE");
        rectangle.draw();
    }
}

分析

简单工厂模式虽然简单,但它也有一些缺点:

工厂方法模式

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法模式将对象的实例化推迟到子类中完成,符合开闭原则,即对扩展开放,对修改关闭。

结构
工厂方法模式包含四个角色:

  1. 抽象产品(Product): 定义了产品的规范,描述了产品的属性和功能。
  2. 具体产品(Concrete Product): 实现了抽象产品类的具体子类。
  3. 抽象工厂(Factory): 定义了创建产品对象的工厂接口,包含了创建产品的抽象方法。
  4. 具体工厂(Concrete Factory): 实现了抽象工厂接口,负责创建具体的产品对象。

示例
假设我们有一个简单的图形绘制程序,可以绘制圆形和矩形。我们使用工厂方法模式来创建不同的图形对象。

  1. 创建抽象产品类:
// 抽象图形类
interface Shape {
    void draw();
}

// 圆形类
class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("绘制圆形");
    }
}

// 矩形类
class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("绘制矩形");
    }
}

  1. 创建抽象工厂类:
// 图形工厂接口
interface ShapeFactory {
    Shape createShape();
}

// 圆形工厂类
class CircleFactory implements ShapeFactory {
    @Override
    public Shape createShape() {
        return new Circle();
    }
}

// 矩形工厂类
class RectangleFactory implements ShapeFactory {
    @Override
    public Shape createShape() {
        return new Rectangle();
    }
}

  1. 客户端使用:
// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建圆形工厂
        ShapeFactory circleFactory = new CircleFactory();
        // 使用圆形工厂创建圆形对象
        Shape circle = circleFactory.createShape();
        circle.draw();

        // 创建矩形工厂
        ShapeFactory rectangleFactory = new RectangleFactory();
        // 使用矩形工厂创建矩形对象
        Shape rectangle = rectangleFactory.createShape();
        rectangle.draw();
    }
}

分析
工厂方法模式与简单工厂模式相比,将工厂类进行了抽象,每个产品都有对应的工厂类,遵循了开闭原则,但也增加了代码量。

工厂方法模式更符合开闭原则,适用于产品种类较多且需要经常扩展的情况。

抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式通过引入抽象工厂接口和抽象产品接口,使得客户端可以使用抽象的方式创建一系列相关的产品对象,而无需关心具体的实现类。
结构
抽象工厂模式包含四个角色:

  1. 抽象工厂(Abstract Factory): 声明了一组用于创建一系列产品对象的方法,每一个方法对应一种产品。
  2. 具体工厂(Concrete Factory): 实现了抽象工厂接口,负责创建一系列具体的产品对象。
  3. 抽象产品(Abstract Product): 声明了产品对象的接口,是所有具体产品类的父类。
  4. 具体产品(Concrete Product): 实现了抽象产品接口,是被创建的对象。

示例

假设我们有一个简单的图形绘制程序,可以绘制不同风格的按钮和文本框。我们使用抽象工厂模式来创建不同风格的按钮和文本框对象。

  1. 创建抽象产品接口:
// 抽象按钮类
interface Button {
    void display();
}

// 抽象文本框类
interface TextField {
    void display();
}
  1. 创建具体产品类:
// Spring风格按钮类
class SpringButton implements Button {
    @Override
    public void display() {
        System.out.println("显示浅绿色按钮");
    }
}

// Spring风格文本框类
class SpringTextField implements TextField {
    @Override
    public void display() {
        System.out.println("显示浅绿色文本框");
    }
}

// Summer风格按钮类
class SummerButton implements Button {
    @Override
    public void display() {
        System.out.println("显示浅蓝色按钮");
    }
}

// Summer风格文本框类
class SummerTextField implements TextField {
    @Override
    public void display() {
        System.out.println("显示浅蓝色文本框");
    }
}

  1. 创建抽象工厂接口:
// 抽象工厂接口
interface SkinFactory {
    Button createButton(); // 创建按钮
    TextField createTextField(); // 创建文本框
}

  1. 创建具体工厂类:
// Spring风格工厂类
class SpringSkinFactory implements SkinFactory {
    @Override
    public Button createButton() {
        return new SpringButton();
    }

    @Override
    public TextField createTextField() {
        return new SpringTextField();
    }
}

// Summer风格工厂类
class SummerSkinFactory implements SkinFactory {
    @Override
    public Button createButton() {
        return new SummerButton();
    }

    @Override
    public TextField createTextField() {
        return new SummerTextField();
    }
}

  1. 客户端使用:
// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建Spring风格工厂
        SkinFactory springFactory = new SpringSkinFactory();
        // 创建Spring风格按钮
        Button springButton = springFactory.createButton();
        // 创建Spring风格文本框
        TextField springTextField = springFactory.createTextField();
        springButton.display();
        springTextField.display();

        // 创建Summer风格工厂
        SkinFactory summerFactory = new SummerSkinFactory();
        // 创建Summer风格按钮
        Button summerButton = summerFactory.createButton();
        // 创建Summer风格文本框
        TextField summerTextField = summerFactory.createTextField();
        summerButton.display();
        summerTextField.display();
    }
}

分析
抽象工厂模式将具体工厂类的创建抽象化,使得客户端可以使用抽象的方式创建一系列相关的产品对象,而无需关心具体的实现类。

建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,用于构建复杂对象。它将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
结构

建造者模式包含四个角色:

  1. 产品(Product): 定义了要创建的复杂对象。通常包含多个部件。
  2. 抽象建造者(Builder): 定义了创建产品各个部件的抽象方法,通常包含 buildPart1(), buildPart2() 等方法。
  3. 具体建造者(Concrete Builder): 实现了抽象建造者接口,负责构建和装配各个部件,实现具体的构建过程。
  4. 指挥者(Director): 负责调用具体建造者来创建产品对象,它并不知道具体的产品内容,只知道建造的步骤,根据传入的具体建造者对象完成产品的构建。

示例
假设我们要构建一份电脑,电脑包含CPU、内存、硬盘等组件。我们使用建造者模式来构建电脑对象。

  1. 创建产品类:
// 电脑产品类
class Computer {
    private String cpu;
    private String memory;
    private String hardDisk;

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public void setMemory(String memory) {
        this.memory = memory;
    }

    public void setHardDisk(String hardDisk) {
        this.hardDisk = hardDisk;
    }

    public void show() {
        System.out.println("电脑配置:");
        System.out.println("CPU:" + cpu);
        System.out.println("内存:" + memory);
        System.out.println("硬盘:" + hardDisk);
    }
}

  1. 创建抽象建造者接口:
// 抽象电脑建造者接口
interface ComputerBuilder {
    void buildCpu();
    void buildMemory();
    void buildHardDisk();
    Computer buildComputer();
}
  1. 创建具体建造者类:
// 具体电脑建造者类
class ConcreteComputerBuilder implements ComputerBuilder {
    private Computer computer = new Computer();

    @Override
    public void buildCpu() {
        computer.setCpu("Intel Core i7");
    }

    @Override
    public void buildMemory() {
        computer.setMemory("16GB DDR4");
    }

    @Override
    public void buildHardDisk() {
        computer.setHardDisk("1TB SSD");
    }

    @Override
    public Computer buildComputer() {
        return computer;
    }
}

  1. 创建指挥者类:
// 指挥者类
class Director {
    private ComputerBuilder builder;

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

    public Computer construct() {
        builder.buildCpu();
        builder.buildMemory();
        builder.buildHardDisk();
        return builder.buildComputer();
    }
}
  1. 客户端使用:
// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建具体建造者
        ConcreteComputerBuilder builder = new ConcreteComputerBuilder();
        // 创建指挥者
        Director director = new Director(builder);
        // 构建电脑对象
        Computer computer = director.construct();
        // 显示电脑配置
        computer.show();
    }
}

分析
建造者模式将一个复杂对象的构建过程与它的表现分离,使得相同的构建过程可以创建不同的表示。

  1. 建造者模式使得客户端不需要知道产品内部构建的细节,只需要知道产品的建造步骤和具体建造者即可。
  2. 当需要创建复杂对象,并且对象的各个部分需要按照一定的顺序构建时,建造者模式是一个很好的选择。
  3. 建造者模式可以很容易地改变产品的内部表示,也方便扩展新的具体建造者类。
原型模式

原型模式(Prototype Pattern)是一种创建型设计模式,用于创建对象的一种模式。原型模式通过复制现有对象的原型来创建新的对象,而不是通过实例化类来创建对象。这种方式可以提高对象创建的性能,并且隐藏对象的创建细节。

结构
原型模式包含以下角色:

  1. 原型(Prototype): 声明一个克隆自身的接口。
  2. 具体原型(Concrete Prototype):实现原型接口,实现克隆自身的操作。
  3. 客户端(Client): 使用原型对象的客户端。

示例
假设我们有一个简单的图形类,可以表示不同形状的图形。我们使用原型模式来复制图形对象。

  1. 创建原型接口:
// 原型接口
interface Shape extends Cloneable {
    Shape clone(); // 克隆方法
    void draw(); // 绘制方法
}
  1. 创建具体原型类:
// 圆形类
class Circle implements Shape {
    @Override
    public Shape clone() {
        Circle circle = null;
        try {
            circle = (Circle) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return circle;
    }

    @Override
    public void draw() {
        System.out.println("绘制圆形");
    }
}

// 正方形类
class Square implements Shape {
    @Override
    public Shape clone() {
        Square square = null;
        try {
            square = (Square) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return square;
    }

    @Override
    public void draw() {
        System.out.println("绘制正方形");
    }
}
  1. 客户端使用:
// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建原型对象
        Circle circle = new Circle();
        Square square = new Square();

        // 克隆对象
        Shape clonedCircle = circle.clone();
        Shape clonedSquare = square.clone();

        // 绘制图形
        clonedCircle.draw();
        clonedSquare.draw();
    }
}

分析
原型模式通过复制现有对象的原型来创建新的对象,避免了直接实例化类来创建对象的过程。原型模式适用于需要创建复杂对象,并且对象的创建过程比较耗时或者复杂的情况下。

结构型

代理模式

代理模式(Proxy Pattern)是一种结构型设计模式,它提供了一种代理来控制对其他对象的访问。

** 结构**
代理模式包含以下角色:

  1. 抽象主题(Subject):定义了真实主题和代理主题的共同接口,客户端通过这个接口访问真实主题和代理主题。
  2. 真实主题(Real Subject): 定义了真实对象的功能,是代理模式中的实际执行对象。
  3. 代理(Proxy): 包含了对真实主题的引用,在其内部实例化了真实主题对象,可以控制对真实主题对象的访问,并且可以在调用真实主题对象之前或之后执行一些额外的操作。

示例
假设我们有一个文件加载器接口 FileLoader,包含了加载文件和显示文件内容的方法。我们使用代理模式来控制对文件加载器的访问。

  1. 创建抽象主题接口:
// 抽象主题接口
interface FileLoader {
    void loadFile(String fileName);
    void displayFile();
}

  1. 创建真实主题类:
// 真实主题类
class RealFileLoader implements FileLoader {
    private String fileName;

    public RealFileLoader(String fileName) {
        this.fileName = fileName;
        loadFile(fileName);
    }

    @Override
    public void loadFile(String fileName) {
        System.out.println("加载文件:" + fileName);
    }

    @Override
    public void displayFile() {
        System.out.println("显示文件内容:" + fileName);
    }
}

  1. 创建代理类:
// 代理类
class FileLoaderProxy implements FileLoader {
    private RealFileLoader realFileLoader;
    private String fileName;

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

    @Override
    public void loadFile(String fileName) {
        if (realFileLoader == null) {
            realFileLoader = new RealFileLoader(fileName);
        }
    }

    @Override
    public void displayFile() {
        if (realFileLoader != null) {
            realFileLoader.displayFile();
        } else {
            System.out.println("请先加载文件");
        }
    }
}

  1. 客户端使用:
// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建代理对象
        FileLoader proxy = new FileLoaderProxy("example.txt");

        // 加载并显示文件内容
        proxy.loadFile("example.txt");
        proxy.displayFile();
    }
}

分析
代理模式通过引入代理对象来控制对真实对象的访问,可以在访问真实对象前后进行一些额外的操作,如记录日志、权限控制、缓存等。

在示例中,FileLoaderProxy 作为代理类,控制了对 RealFileLoader的访问,并在访问真实对象之前加载文件,访问真实对象之后显示文件内容。

适配器模式

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个类的接口转换成客户希望的另一个接口。适配器模式通常用于解决接口不兼容的问题,使得原本由于接口不匹配而无法一起工作的类可以协同工作。

特点:

优点:

缺点:

下面是一个简单的适配器模式的示例代码:

目标接口(Target):

// 目标接口
interface Target {
    void request();
}

适配者类(Adaptee):

// 适配者类
class Adaptee {
    void specificRequest() {
        System.out.println("适配者中的业务代码被调用!");
    }
}

类适配器(Class Adapter):

// 类适配器
class ClassAdapter extends Adaptee implements Target {
    @Override
    public void request() {
        specificRequest();
    }
}

对象适配器(Object Adapter):

// 对象适配器
class ObjectAdapter implements Target {
    private Adaptee adaptee;

    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

客户端代码:

public class AdapterPatternExample {
    public static void main(String[] args) {
        // 类适配器
        Target classAdapter = new ClassAdapter();
        classAdapter.request();

        // 对象适配器
        Adaptee adaptee = new Adaptee();
        Target objectAdapter = new ObjectAdapter(adaptee);
        objectAdapter.request();
    }
}

在上面的示例中,Adaptee 是适配者类,Target 是目标接口。ClassAdapterObjectAdapter 是适配器类,分别使用类适配器和对象适配器两种实现方式来实现适配器模式。通过适配器类,可以让 AdapteeTarget 协同工作。

装饰器模式

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向现有的对象添加新的功能,同时又不改变其结构。装饰器模式通过创建一个包装器(Wrapper)来包裹原始对象,然后在包装器中添加新的功能。

特点:

优点:

缺点:

适用场景:

抽象组件接口(Component):

// 抽象组件接口
interface Component {
    void operation();
}

具体组件(Concrete Component):

// 具体组件
class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("执行具体组件的操作!");
    }
}

抽象装饰器(Decorator):

// 抽象装饰器
abstract class Decorator implements Component {
    private Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        if (component != null) {
            component.operation();
        }
    }
}

具体装饰器(Concrete Decorator):

// 具体装饰器
class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        addedBehavior();
    }

    private void addedBehavior() {
        System.out.println("为具体组件添加额外的行为!");
    }
}

客户端代码:

public class DecoratorPatternExample {
    public static void main(String[] args) {
        // 创建具体组件对象
        Component component = new ConcreteComponent();

        // 创建装饰器对象,并传入具体组件对象
        Component decorator = new ConcreteDecorator(component);

        // 调用装饰器对象的方法,实际上会执行具体组件对象的方法,然后再添加额外的行为
        decorator.operation();
    }
}

在这个示例中,ConcreteComponent 是具体的组件,Decorator 是抽象装饰器,ConcreteDecorator 是具体的装饰器。通过装饰器模式,我们可以动态地给 ConcreteComponent 添加新的行为,而不需要修改 ConcreteComponent 的代码。

桥接模式

桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与其实现部分分离,使它们可以独立变化。桥接模式通过将抽象部分实现部分分离来实现解耦,从而提高了系统的灵活性和扩展性。

特点:

优点:

缺点:

适用场景:

下面是一个简单的桥接模式的示例代码:

抽象部分(Abstraction):

// 抽象部分
abstract class Abstraction {
    protected Implementor implementor;

    public Abstraction(Implementor implementor) {
        this.implementor = implementor;
    }

    abstract void operation();
}

具体抽象部分(Refined Abstraction):

// 具体抽象部分
class RefinedAbstraction extends Abstraction {
    public RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }

    @Override
    void operation() {
        System.out.println("RefinedAbstraction operation");
        implementor.operationImpl();
    }
}

实现部分(Implementor):

// 实现部分
interface Implementor {
    void operationImpl();
}

具体实现部分(Concrete Implementor):

// 具体实现部分
class ConcreteImplementorA implements Implementor {
    @Override
    public void operationImpl() {
        System.out.println("ConcreteImplementorA operationImpl");
    }
}

class ConcreteImplementorB implements Implementor {
    @Override
    public void operationImpl() {
        System.out.println("ConcreteImplementorB operationImpl");
    }
}

客户端代码:

public class BridgePatternExample {
    public static void main(String[] args) {
        // 创建具体的实现部分对象
        Implementor implementorA = new ConcreteImplementorA();
        Implementor implementorB = new ConcreteImplementorB();

        // 创建具体的抽象部分对象,并传入实现部分对象
        Abstraction abstractionA = new RefinedAbstraction(implementorA);
        Abstraction abstractionB = new RefinedAbstraction(implementorB);

        // 调用抽象部分对象的方法,实际上会调用实现部分对象的方法
        abstractionA.operation();
        abstractionB.operation();
    }
}

在这个示例中,Abstraction 是抽象部分,Implementor 是实现部分,RefinedAbstraction 是具体的抽象部分,ConcreteImplementorAConcreteImplementorB 是具体的实现部分。通过桥接模式,可以让抽象部分和实现部分可以独立变化,实现了抽象和实现的分离,提高了系统的灵活性和扩展性。

组合模式

组合模式(Composite Pattern)是一种结构型设计模式,它允许将对象组合成树形结构来表现“部分-整体”的层次结构。组合模式使得客户端可以统一对待单个对象和组合对象,从而简化了客户端的代码。

特点:

优点:

缺点:

适用场景:

下面是一个简单的组合模式的示例代码:

抽象组件(Component):

// 抽象组件
interface Component {
    void operation();
}

叶子组件(Leaf):

// 叶子组件
class Leaf implements Component {
    private String name;

    public Leaf(String name) {
        this.name = name;
    }

    @Override
    public void operation() {
        System.out.println("Leaf " + name + " operation");
    }
}

组合组件(Composite):

// 组合组件
class Composite implements Component {
    private List<Component> children = new ArrayList<>();

    public void add(Component component) {
        children.add(component);
    }

    public void remove(Component component) {
        children.remove(component);
    }

    @Override
    public void operation() {
        for (Component component : children) {
            component.operation();
        }
    }
}

客户端代码:

public class CompositePatternExample {
    public static void main(String[] args) {
        // 创建叶子组件对象
        Component leaf1 = new Leaf("1");
        Component leaf2 = new Leaf("2");
        Component leaf3 = new Leaf("3");

        // 创建组合组件对象,并添加叶子组件对象
        Composite composite = new Composite();
        composite.add(leaf1);
        composite.add(leaf2);

        // 调用组合组件对象的方法,实际上会递归调用叶子组件对象的方法
        composite.operation();

        // 添加叶子组件对象到另一个组合组件对象中
        Composite composite2 = new Composite();
        composite2.add(leaf3);
        composite2.add(composite);

        // 调用另一个组合组件对象的方法,实际上会递归调用两个叶子组件对象的方法
        composite2.operation();
    }
}

在这个示例中,Component 是抽象组件,Leaf 是叶子组件,Composite 是组合组件。通过组合模式,可以将多个对象组合成树形结构,使客户端可以统一处理单个对象和组合对象,从而简化了客户端的代码。

享元模式

享元模式(Flyweight Pattern)是一种结构型设计模式,它旨在通过共享对象来减少内存使用和提高性能。在享元模式中,共享对象通常是不可变的,因此可以安全地在多个环境中共享。

特点:

优点:

缺点:

适用场景:

下面是一个简单的享元模式的示例代码:

抽象享元角色(Flyweight):

// 抽象享元角色
interface Shape {
    void draw(String color);
}

具体享元角色(Concrete Flyweight):

// 具体享元角色
class Circle implements Shape {
    private String color;

    public Circle() {
        // 内部状态,不可共享
    }

    @Override
    public void draw(String color) {
        // 外部状态,可以共享
        this.color = color;
        System.out.println("绘制一个 " + color + " 的圆形");
    }
}

享元工厂角色(Flyweight Factory):

// 享元工厂角色
class ShapeFactory {
    private static final Map<String, Shape> shapes = new HashMap<>();

    public static Shape getCircle(String color) {
        Circle circle = (Circle) shapes.get(color);

        if (circle == null) {
            circle = new Circle();
            shapes.put(color, circle);
        }
        return circle;
    }
}

客户端代码:

public class FlyweightPatternExample {
    private static final String[] colors = {"红色", "绿色", "蓝色", "黄色", "黑色"};

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Shape circle = ShapeFactory.getCircle(getRandomColor());
            circle.draw(getRandomColor());
        }
    }

    private static String getRandomColor() {
        return colors[(int) (Math.random() * colors.length)];
    }
}

在这个示例中,Shape 是抽象享元角色,Circle 是具体享元角色,ShapeFactory 是享元工厂角色。通过享元模式,可以减少对象的创建数量,节约内存使用,提高系统性能。

外观模式

行为型

观察者模式
模板方法模式
命令模式
状态模式
职责链模式
结束其模式
中介模式
访问者模式
策略模式
备忘录模式
迭代器模式
上一篇下一篇

猜你喜欢

热点阅读