侧边栏壁纸
博主头像
Z同学博主等级

工作磨平激情前,坚持技术的热忱。 欢迎光临Z同学的技术小站。 分享最新的互联网知识。

  • 累计撰写 274 篇文章
  • 累计创建 55 个标签
  • 累计收到 74 条评论

Java的各种常见设计模式介绍:单例,工厂,适配器,观察者,建造者等模式介绍。

Z同学
2022-02-17 / 0 评论 / 1 点赞 / 135 阅读 / 7,183 字
温馨提示:
本文最后更新于 2022-02-17,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

前言

本篇主要介绍一下Java中的一些常见设计模式,也就是我们开发中经常使用的几种模式。还有更多的使用比较少,就不做详细介绍了。

总体来说的设计模式分为三大类:

  • 创建型模式:工厂模式,抽象工厂模式,单例模式,建造者模式,原型模式。
  • 结构型模式:适配器模式,代理模式,装饰器模式,外观模式,桥接模式,组合模式,享元模式。
  • 行为型模式:观察者模式,策略模式,模板方法模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,解释器模式,中介者模式。

其实软件涉及模式并不是java 自己独有的。设计模式只是一种逻辑的总结归纳。其他的开发语言中也是一样可以实现的。

下面介绍一些常见,常用的几种设计模式。

工厂模式 Factory Pattern

通常我们说工厂模式,指的都是工厂方法模式。相较于它还有一个抽象工厂模式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

//创建一个对象的 基础接口。
public interface Sender {
    public void Send();
}

//创建一个 邮件发送子对象
public class MailSender implements Sender {
    @Override
    public void Send() {
        System.out.println("我是一个邮件发送者");
    }
}
//创建一个 短信发送子对象。
public class SmsSender implements Sender {
    @Override
    public void Send() {
        System.out.println("我是一个短信发送者");
    }
}
//创建一个 发送工厂。
public class SendFactory {
    //根据类型,获取相应的发送对象。 外界不需要关心是如何发送的,只是根据需求得到相应的实例对象。
    public Sender produce(String type) {
        if ("mail".equals(type)) {
            return new MailSender();
        } else if ("sms".equals(type)) {
            return new SmsSender();
        } else {
            return null;
        }
    }
}

我们如果不想传type 对象,我们也可以创建多个不同的实例。这样其他人只需要了解接口类Sender的使用就可以了。不用在意具体的实现。

public class SendFactory {
    //根据类型,获取相应的发送对象。 外界不需要关心是如何发送的,只是根据需求得到相应的实例对象。
    public Sender produceMail() {
            return new MailSender();
    }
    public Sender produceSms() {
            return new SmsSender();
    }
}

在上面的工厂对象调用时,我们需要创建一个SendFactory对象。然后再调用。我们如果给方法添加上static就是所谓的静态工厂方法模式。

实例:

public class SendFactory {

    public static Sender produceMail() {
            return new MailSender();
    }
    public static Sender produceSms() {
            return new SmsSender();
    }
}

抽象工厂模式 Abstract Factory Pattern

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

工厂方法模式有一个问题就是,类的创建依赖工厂类。如果想要拓展程序,必须对工厂类进行修改,而这种情况违背了闭包原则。

针对这种情况,就出来了抽象工厂模式。这样一旦需要增加新的功能,直接增加新的工厂类就可以了。

示例:

public interface Sender {
    public void Send();
}

public class MailSender implements Sender {
    @Override
    public void Send() {
        System.out.println("发送邮件");
    }
}

public class SmsSender implements Sender {
    @Override
    public void Send() {
        System.out.println("发送短信");
    }
}
//抽象接口
public interface Provider {
    public Sender produce();
}
//创建一个 短信发送工厂
public class SendSmsFactory  implements Provider{
    public Sender produce(String type) {
         return new SmsSender();

    }
}
//创建一个 邮件发送工厂
public class SendMailFactory  implements Provider{
    public Sender produce(String type) {
        return new MailSender();
    }
}

//上面示例使用接口实现的抽象,我们也可以使用抽象类来实现
public abstract class SendProvider{
    public abstract Sender produce();
}

单例模式 Singleton Pattern

可以说是最简单的一种设计模式了。它的要求是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。它不需要再额外创建实例化。

特性总结下就是:

  1. 只能有一个实例。(构造函数私有化 private)
  2. 必须由它自己创建自己的唯一实例。(自身初始化创建)
  3. 必须给所有其他对象提供访问该实例的方法。(静态全局函数获取实例)

它主要是为了减少类的频繁创建于销毁。当我们有个实例对象,在整个程序各种模块都要使用的时候,我们通过单例模式可以有效减少类的重复创建于销毁,减少内存的开销。

public class SingleObject {
 
   //自己创建 SingleObject 的静态对象
   private static SingleObject instance = new SingleObject();
 
   //让构造函数私有化,这样该类就不会被实例化
   private SingleObject(){}
 
   //给其他对象提供访问实例的静态方法。
   public static SingleObject getInstance(){
      return instance;
   }
}

上面的初始化逻辑叫做:饿汉式单例对象。

还有一种叫做懒汉式。

实例:

public class SingleObject {
 
   //自己创建 SingleObject 的静态对象
    private static Singleton instance;  
 
   //让构造函数私有化,这样该类就不会被实例化
   private SingleObject(){}
 
   //给其他对象提供访问实例的静态方法。
   public static Singleton getInstance() {  
      if (instance == null) {  
         instance = new Singleton();  
      }  
      return instance;  
    }  
}

还有更复杂的,线程安全处理,多线程状态下的验证等变种。

这里就不复杂拓展了,有感兴趣的可以通过 单例模式 | 菜鸟教程 (runoob.com)了解吧。

建造者模式 Builder Pattern

主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象, 所谓复合对象就是指某个类具有不同的属性。

public interface Sender {
    public void Send();
}

public class MailSender implements Sender {
    @Override
    public void Send() {
        System.out.println("发送邮件");
    }
}

public class SmsSender implements Sender {
    @Override
    public void Send() {
        System.out.println("发送短信");
    }
}

public class Builder {
    private List<Sender> list = new ArrayList<Sender>();
    public void produceMailSender(int count) {
        for (int i = 0; i < count; i++) {
            list.add(new MailSender());
        }
    }
    public void produceSmsSender(int count) {
        for (int i = 0; i < count; i++) {
            list.add(new SmsSender());
        }
    }
}

适配器模式 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) {    
 
      //播放 mp3 音乐文件的内置支持
      if(audioType.equalsIgnoreCase("mp3")){
         System.out.println("Playing mp3 file. Name: "+ fileName);         
      } 
      //mediaAdapter 提供了播放其他文件格式的支持
      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");
   }
}

观察者模式 Observer Pattern

观察者模式很好理解,类似于订阅和关注。

当我们在抖音或微博中,关注了博主后。博主之后发布新的消息,你就能够收到推送。

简单来讲就一句话:当一个对象变化时, 其它依赖该对象的对象都会收到通知,并且随着变化。对象之间是一种一对多的关系。我们可以观察多个对象,去接收它们的变化通知。

//观察者
public interface Observer {
    public void update();
}
//观察者A
public class ObserverA implements Observer {
    @Override
    public void update() {
        System.out.println("observerA 收到");
    }
}
//观察者B
public class ObserverB implements Observer {
    @Override
    public void update() {
        System.out.println("observerB 收到");
    }
}

public interface Subject {
    /*增加观察者*/
    public void add(Observer observer);
    /*删除观察者*/
    public void del(Observer observer)
    /*通知观察者*/
    public void notifyObservers();
    /*自己的业务处理*/
    public void myaction();
}
public abstract class AbstractSubject implements Subject {
    private Vector<Observer> vector = new Vector<Observer>();
    @Override
    public void add(Observer observer) {
        vector.add(observer);
    }
    @Override
    public void del(Observer observer) {
        vector.remove(observer);
    }
    @Override
    public void notifyObservers() {
        Enumeration<Observer> enumo = vector.elements();
        while (enumo.hasMoreElements()) {
            enumo.nextElement().update();
        }
    }
}
public class MySubject extends AbstractSubject {
    @Override
    public void myaction() {
        System.out.println("本身进行更新");
        notifyObservers();
    }
}
public class ObserverTest {
    public static void main(String[] args) {
        Subject sub = new MySubject();
        sub.add(new ObserverA());
        sub.add(new ObserverB());
        sub.operation();
    }
}

到这里,主要介绍了几种常见的。还有更多的设计模式大家可以深入了解一下。

设计模式是一个很有用的知识。当你弄明白了各种设计模式,你再去看各种源代码你将更能直观了解代码的作用。

否则阅读会磕磕碰碰。

1

评论区