一、简介
软件设计模式(Software Design Pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。其目的是为了提高代码的可重用性、代码的可读性和代码的可靠性。
参考学习:设计模式学习网站
二、几个常用设计模式
1. 单例模式
描述:类、对象、实例的关系,在JVM中的堆区存着Java对象的实例,传统创建对象(new className())则会创建一个实例,但在特定的场景只需要一个特定的实例即可,而不需要创建多个实例(不同实例可以构造参数一样,但是实质不一样的),如任务管理器的打开为了避免资源的浪费就只需要创建一个实例即可。
应用场景:
1、统计当前在线人数(网站计数器):用一个全局对象来记录。
2、打印机(设备管理器):当有两台打印机,在输出同一个文件的时候只一台打印机进行输出。
3、数据库连接池(控制资源):一般是采用单例模式,因为数据库连接是一种连接数据库资源,不易频繁创建和销毁。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率 的损耗还是非常昂贵的,因此用单例模式来维护,就可以大大降低这种损耗。
4、应用程序的日志(资源共享):一般日志内容是共享操作,需要在后面不断写入内容所以通常单例设计。
实现方式:饿汉式和懒汉式,实现代码如下
/**
* @AUTHOR LYF
* @DATE 2021/5/1
* @VERSION 1.0
* @DESC
*
* 1.关于static的生命周期
* 结论:想要用static存一个变量,使得下次程序运行时还能使用上次的值是不可行的。
* 因为静态变量生命周期虽然长(就是类的生命周期),但是当程序执行完,也就是该
* 类的所有对象都已经被回收,或者加载类的ClassLoader已经被回收,那么该类就会从jvm的方法区卸载,即生命期终止
* https://www.cnblogs.com/hf-cherish/p/4970267.html
*/
class LazySingleton{
private volatile static LazySingleton lazySingleton =null;//运行时加载
private LazySingleton(){
}
public static synchronized LazySingleton getInstance(){
if(lazySingleton==null){
System.out.println("未构造..");
lazySingleton = new LazySingleton();
}else{
System.out.println("已构造..");
}
return lazySingleton;
}
public void method(){
System.out.println("call method..");
}
}
class HungrySingleton{
private final static HungrySingleton hungrySingleton = new HungrySingleton();
private HungrySingleton(){
}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
public void method(){
System.out.println("call method....");
}
}
public class SingletonModel {
public static void main(String[]args){
// 第一次构造
LazySingleton lazySingleton = LazySingleton.getInstance();// Calendar就采用该模式
lazySingleton.method();
// 第二次构造 ,,static的生命周期》??
LazySingleton lazySingleton2 = LazySingleton.getInstance();
lazySingleton2.method();
// 饿汉单例模式
HungrySingleton hungrySingleton = HungrySingleton.getInstance();
hungrySingleton.method();
if(lazySingleton==lazySingleton2){
System.out.println("相同");
}else {
System.out.println("不同");
}
// for(int i =0;i<200;i++){
// LazySingleton.getInstance().method();
// try {
// Thread.sleep(2000);
// }catch (Exception e){
// e.printStackTrace();
// }
// }
}
}
简单的应用
/**
* @AUTHOR LYF
* @DATE 2021/5/1
* @VERSION 1.0
* @DESC
* 应用
*/
class Win extends JPanel{
private static Win instance = new Win();
private Win(){
JLabel l1 = new JLabel(new ImageIcon("E:\\IdeaProjects\\java-base\\src\\main\\resources\\test.png"));
this.add(l1);
}
public static Win getInstance(){
return instance;
}
}
class WinPanel extends JPanel{
public WinPanel(){
JLabel l1 = new JLabel(new ImageIcon("E:\\IdeaProjects\\java-base\\src\\main\\resources\\test.png"));
this.add(l1);
}
}
public class SingletonApplication {
public static void main(String[]args){
// 框架
JFrame jf = new JFrame("饿汉单例模式");
// 设置布局
jf.setLayout(new GridLayout(1,2));
// 容器
Container containerPane = jf.getContentPane();
// 设置面板
Win win1 = Win.getInstance();
Win win2 = Win.getInstance();
// 不同实例
WinPanel panel1 = new WinPanel();
WinPanel panel2 = new WinPanel();
containerPane.add(panel1);
containerPane.add(panel2);
//---------------------------------------
containerPane.add(win1);
containerPane.add(win2);
if(win1==win2){
System.out.println("是同一个");
}else {
System.out.println("不是同一个");
}
jf.pack();
jf.setLocation(500,300);
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
2.原型设计模式
描述:为了减少构造的开销,直接进行克隆复制已有对象生成新的实例。适用于构造参数过多的。
应用场景:
类初始化消耗资源较多
new 产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
构造函数比较复杂
循环体中生产大量对象时
参考:关于克隆方面的知识
/**
* @AUTHOR LYF
* @DATE 2021/5/1
* @VERSION 1.0
* @DESC
* 原型模式,克隆复制
*/
class ProtoModel implements Cloneable{
public ProtoModel(){
System.out.println("构造ProtoModel");
}
@Override
protected Object clone() throws CloneNotSupportedException {
System.out.println("复制ProtoModel");
return (ProtoModel)super.clone();
}
}
public class ProtoTypeModel {
public static void main(String[]args) throws CloneNotSupportedException {
ProtoModel protoModel1= new ProtoModel();
ProtoModel protoModel2=(ProtoModel)protoModel1.clone();
if(protoModel1==protoModel2){
System.out.println("相同");
}else {
System.out.println("不同");
}
}
}
3.观察者模式
描述:多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
应用:多用于实现订阅功能的场景,例如微博的订阅,当我们订阅了某个人的微博账号,当这个人发布了新的消息,就会通知我们。
/**
* @AUTHOR LYF
* @DATE 2021/5/2
* @VERSION 1.0
* @DESC
*/
abstract class Subject{
//private
protected List<Observer> observerList = new ArrayList<>();
protected List<String> msgList =new ArrayList<>();
void addObserver(Observer observer){
observerList.add(observer);
}
void remove(Observer observer){
observerList.remove(observer);
}
void publicMsg(String msg)
{
msgList.add(new Date()+":"+msg);
}
abstract void notifyObserver();
}
class concreteSubject extends Subject{
@Override
void notifyObserver() {
System.out.println("收到新消息,通知所有观察者(订阅者)");
for(Observer observer:observerList){
observer.response(msgList.get(msgList.size()-1));
}
}
}
// 为什么是接口而不是抽象类?,是满足该规则,并非拓展或者实现部分
interface Observer{
void response(String receiveMsg);
}
class Observer1 implements Observer{
@Override
public void response(String receiveMsg) {
System.out.println("Observer1观察到目标改变,收到信息--"+receiveMsg);
}
}
class Observer2 implements Observer{
@Override
public void response(String receiveMsg) {
System.out.println("Observer2观察到目标改变,收到信息--"+receiveMsg);
}
}
public class ObserverModel {
public static void main(String[]args){
Subject subject = new concreteSubject();
Observer observer1 = new Observer1();
Observer observer2 = new Observer2();
subject.addObserver(observer1);
subject.addObserver(observer2);
// 当发布消息才触发通知
subject.publicMsg("hello,this is a test!!");
subject.notifyObserver();
subject.remove(observer1);
subject.publicMsg("hello,the notice ! observer1 has been removed!");
subject.notifyObserver();
}
}
4.代理模式
描述:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
应用场景:在业务系统中一些非功能性需求,比如:监控、统计、鉴权、事务、日志等。我们将这些附加功能与业务功能解耦,放到代理类中统一处理,这样可以与业务解耦并且做到职责明确划分。
要访问的远程对象比较大(如视频或大图像等),其下载要花很多时间。还有因为安全原因需要屏蔽客户端直接访问真实对象,如某单位的内部数据库等。
// 抽象主题
interface Subject{
void request();
}
class RealSubject implements Subject{
//private String name;
@Override
public void request() {
System.out.println("真实实现主题....");
}
}
class SubjectProxy{
private Subject subject = null;
public SubjectProxy(){
if(subject==null){
subject = new RealSubject();//生成代理的服务
}
}
public void request(){
System.out.println("进入请求");
preRequest();
subject.request();
afterRequest();
}
private void preRequest(){
System.out.println("进行对subject的预处理");
}
private void afterRequest(){
System.out.println("进行对subject的事后处理");
}
}
public class ProxyTest {
public static void main(String[]args){
SubjectProxy subjectProxy = new SubjectProxy();
subjectProxy.request();;
}
}