23种设计模式简单记录

23种设计模式主要分为三大类:创建型模式、结构型模式和行为型模式。下面是这些设计模式的概览:

创建型模式(Creational Patterns)

  1. 单例模式(Singleton):确保一个类只有一个实例,并提供一个全局访问点。
  2. 工厂方法模式(Factory Method):定义一个用于创建对象的接口,但让子类决定实例化哪一个类。
  3. 抽象工厂模式(Abstract Factory):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
  4. 建造者模式(Builder):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
  5. 原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象。

结构型模式(Structural Patterns)

  1. 适配器模式(Adapter):将一个类的接口转换成客户希望的另一个接口。
    1. MusicPlayerAdapter 类作为适配器,它实现了 PlayMusicV2 接口,并在内部持有一个 PlayMusicV1 对象的引用。当客户端调用 play 方法时,适配器会根据传入的参数调用旧接口的 playMp3 方法,从而实现了接口的转换,让旧的音频播放器库能够适应新的应用程序接口。例子:
      // 原有的接口
      interface PlayMusicV1 {
          void playMp3(String filename);
      }
      
      // 新的接口
      interface PlayMusicV2 {
          void play(String audioType, String filename);
      }
      
      // 第三方库的实现类
      class OldMusicPlayer implements PlayMusicV1 {
          @Override
          public void playMp3(String filename) {
              System.out.println("Playing MP3 file: " + filename);
          }
      }
      
      // 适配器类
      class MusicPlayerAdapter implements PlayMusicV2 {
          private final PlayMusicV1 player;
      
          public MusicPlayerAdapter(PlayMusicV1 player) {
              this.player = player;
          }
      
          @Override
          public void play(String audioType, String filename) {
              if ("mp3".equalsIgnoreCase(audioType)) {
                  player.playMp3(filename);
              } else {
                  System.out.println("Unsupported audio type: " + audioType);
              }
          }
      }
      
      // 客户端代码
      public class Client {
          public static void main(String[] args) {
              PlayMusicV1 oldPlayer = new OldMusicPlayer();
              PlayMusicV2 adapter = new MusicPlayerAdapter(oldPlayer);
              
              // 使用新接口播放MP3
              adapter.play("mp3", "favorite_song.mp3");
          }
      }

  2. 桥接模式(Bridge):将抽象部分与它的实现部分分离,使它们都可以独立地变化。
  3. 组合模式(Composite):允许你将对象组合成树形结构来表示整体/部分层次结构。
  4. 装饰器模式(Decorator):动态地给一个对象添加一些额外的职责。
  5. 外观模式(Facade):为子系统中的一组接口提供一个一致的界面,简化接口。
  6. 享元模式(Flyweight):运用共享技术有效支持大量细粒度的对象。
  7. 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。
    1. 代理模式通过提供一个代理对象来控制对真实对象的访问,这个代理对象可以在访问真实对象前进行一些预处理操作,或者在访问后进行一些后续处理。下面是一个简单的Java代理模式示例,我们以租房为例,说明静态代理和动态代理的实现。

      静态代理示例

      首先定义一个租房服务的接口:

      1public interface RentHouse {
      2    void rent();
      3}

      接着实现这个接口的真实对象(房东):

      1public class RealEstate implements RentHouse {
      2    @Override
      3    public void rent() {
      4        System.out.println("房东出租房子");
      5    }
      6}

      然后创建一个静态代理类,也实现相同的接口:

      1public class HouseAgency implements RentHouse {
      2    private RealEstate realEstate;
      3
      4    public HouseAgency(RealEstate realEstate) {
      5        this.realEstate = realEstate;
      6    }
      7
      8    @Override
      9    public void rent() {
      10        preProcess();
      11        realEstate.rent();
      12        postProcess();
      13    }
      14
      15    private void preProcess() {
      16        System.out.println("中介进行房源展示、咨询等前期工作");
      17    }
      18
      19    private void postProcess() {
      20        System.out.println("中介完成合同签订等后续工作");
      21    }
      22}

      最后是客户端代码,使用代理来租房:

      1public class Client {
      2    public static void main(String[] args) {
      3        RealEstate realEstate = new RealEstate();
      4        RentHouse proxy = new HouseAgency(realEstate);
      5        proxy.rent();
      6    }
      7}

      动态代理示例

      动态代理通常使用Java的java.lang.reflect.Proxy类来创建代理对象,这里使用JDK动态代理为例:

      首先,保持RentHouse接口和RealEstate类不变。

      动态代理类如下:

      1import java.lang.reflect.InvocationHandler;
      2import java.lang.reflect.Method;
      3import java.lang.reflect.Proxy;
      4
      5public class DynamicProxy implements InvocationHandler {
      6    private Object target;
      7
      8    public Object bind(Object target) {
      9        this.target = target;
      10        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
      11                target.getClass().getInterfaces(), this);
      12    }
      13
      14    @Override
      15    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      16        preProcess();
      17        Object result = method.invoke(target, args);
      18        postProcess();
      19        return result;
      20    }
      21
      22    private void preProcess() {
      23        System.out.println("动态代理:中介进行房源展示、咨询等前期工作");
      24    }
      25
      26    private void postProcess() {
      27        System.out.println("动态代理:中介完成合同签订等后续工作");
      28    }
      29}

      客户端代码调整为:

      1public class Client {
      2    public static void main(String[] args) {
      3        RealEstate realEstate = new RealEstate();
      4        DynamicProxy dynamicProxy = new DynamicProxy();
      5        RentHouse proxy = (RentHouse) dynamicProxy.bind(realEstate);
      6        proxy.rent();
      7    }
      8}

      在这个例子中,无论是静态代理还是动态代理,代理对象都在真实对象执行租房操作前后增加了额外的行为,如房源展示、合同签订等,体现了代理模式的价值。动态代理相比静态代理更加灵活,可以在运行时动态创建代理对象,无需为每个真实对象都手动创建一个代理类。

行为型模式(Behavioral Patterns)

  1. 责任链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
  2. 命令模式(Command):将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。
  3. 解释器模式(Interpreter):给定一种语言,定义它的文法和一个解释器,该解释器使用该语法来解释语言中的句子。
  4. 迭代器模式(Iterator):提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示。
  5. 中介者模式(Mediator):用一个中介者对象来封装一系列的对象交互。
  6. 备忘录模式(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
  7. 观察者模式(Observer):定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。 
    1. 观察者模式解决了什么问题?
      1. 对象间一对多的依赖关系:在软件系统中,当一个对象的状态发生变化时,其他依赖于它的对象也都需要得到通知并被自动更新。这种情况下,如果采用传统的直接调用方式,对象间的耦合度会非常高,不利于代码的维护和扩展。观察者模式通过引入“主题”和“观察者”的概念,使得对象间的依赖关系变得清晰且灵活。

      2. 解耦:通过将依赖关系抽象为主题和观察者之间的订阅/发布关系,观察者模式降低了对象之间的耦合度。这使得代码更加易于维护和扩展,因为你可以在不修改主题对象代码的情况下,增加或删除观察者对象。

      3. 异步通信:观察者模式支持异步通信,即主题对象在状态改变时,可以立即通知观察者,而观察者可以在稍后的时间处理这个通知。这种异步通信的方式可以提高系统的响应速度,减少不必要的等待时间。

      4. 广播通知:当主题对象的状态发生变化时,它可以通过调用notifyObservers()方法一次性通知所有注册的观察者对象,而不需要分别调用每个观察者的更新方法。这种广播通知的方式大大提高了代码的效率和可维护性。

      5. 支持动态关联:观察者模式允许在运行时动态地建立或断开对象之间的依赖关系。这意味着你可以在程序运行的任何时刻,通过调用registerObserver()removeObserver()方法来添加或删除观察者对象。

      6. 事件驱动:观察者模式是一种典型的事件驱动编程模式。在这种模式下,程序的执行流程不是由调用顺序来控制的,而是由事件来驱动的。当某个事件发生时(例如主题对象的状态变化),与该事件相关的所有代码(即观察者的更新方法)都会被自动执行。这种编程方式使得代码更加清晰、易于理解和维护。

    2. 代码案例:

      1. // 主题接口  
        interface Subject {  
            void registerObserver(Observer o);  
            void removeObserver(Observer o);  
            void notifyObservers();  
            // 假设这里有一个状态值  
            void setState(String state);  
            String getState();  
        }  
          
        // 观察者接口  
        interface Observer {  
            void update(String state);  
        }  
          
        // 具体主题类  
        class ConcreteSubject implements Subject {  
            private List<Observer> observers;  
            private String state;  
          
            public ConcreteSubject() {  
                observers = new ArrayList<>();  
            }  
          
            @Override  
            public void registerObserver(Observer o) {  
                observers.add(o);  
            }  
          
            @Override  
            public void removeObserver(Observer o) {  
                int i = observers.indexOf(o);  
                if (i >= 0) {  
                    observers.remove(i);  
                }  
            }  
          
            @Override  
            public void notifyObservers() {  
                for (Observer observer : observers) {  
                    observer.update(state);  
                }  
            }  
          
            @Override  
            public void setState(String state) {  
                this.state = state;  
                // 每当状态变化,就通知所有的观察者  
                notifyObservers();  
            }  
          
            @Override  
            public String getState() {  
                return state;  
            }  
        }  
          
        // 具体观察者类  
        class ConcreteObserver implements Observer {  
            private String name;  
            private Subject subject;  
          
            public ConcreteObserver(String name, Subject subject) {  
                this.name = name;  
                this.subject = subject;  
                // 初始化时注册自己为观察者  
                this.subject.registerObserver(this);  
            }  
          
            @Override  
            public void update(String state) {  
                System.out.println(name + " observed state change to: " + state);  
            }  
        }  
          
        // 使用示例  
        public class ObserverPatternDemo {  
            public static void main(String[] args) {  
                Subject subject = new ConcreteSubject();  
          
                Observer observer1 = new ConcreteObserver("Observer 1", subject);  
                Observer observer2 = new ConcreteObserver("Observer 2", subject);  
          
                // 改变主题状态  
                subject.setState("New state");  
          
                // 移除一个观察者  
                subject.removeObserver(observer1);  
          
                // 再次改变主题状态  
                subject.setState("Another new state");  
            }  
        }

      2. 或者我们可以用Rxjava框架来写:

        1. import com.sun.media.jfxmediaimpl.MediaDisposer;
          import io.reactivex.rxjava3.annotations.NonNull;
          import io.reactivex.rxjava3.core.Observable;
          import io.reactivex.rxjava3.core.Observer;
          import io.reactivex.rxjava3.disposables.Disposable;
          
          
          public class ResultTest {
              public static void main(String[] args) {
                  // 创建一个Observable(被观察者),它发射从1到5的整数序列
                  Observable<Integer> observable = Observable.just(1, 2, 3, 4, 5);
          
                  // 创建一个Observer(观察者),它订阅Observable并处理接收到的数据
                  Observer<Integer> observer = new Observer<Integer>() {
          
                      @Override
                      public void onSubscribe(@NonNull Disposable d) {
                          System.out.println("开始订阅数据...");
                      }
          
                      @Override
                      public void onNext(Integer value) {
                          System.out.println("接收到数据:" + value);
                      }
          
                      @Override
                      public void onError(Throwable e) {
                          System.out.println("数据接收出错:" + e.getMessage());
                      }
          
                      @Override
                      public void onComplete() {
                          System.out.println("数据接收完毕!");
                      }
                  };
          
                  // Observer订阅Observable
                  observable.subscribe(observer);
              }
          }
          

  8. 状态模式(State):允许一个对象在其内部状态改变时改变它的行为。
  9. 策略模式(Strategy):定义一系列算法,把它们一个个封装起来,并使它们可以相互替换。
  10. 模板方法模式(Template Method):定义一个操作中的算法骨架,而将一些步骤延迟到子类中实现。
  11. 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值