Software design pattern and architecture experiment——2.3-1 Application of single-column pattern

1. Experimental purpose

  1. Master the characteristics of single-column mode
  2. Analyze specific problems and use single-column mode for design.

2. Experimental content

[Assignment 2.3-1] In Example 2.6, in the software design of a unit’s Internet connection problem, the single-column mode part adopts the standard single-column mode. Now it is required to change its design and use the thread-safe single-column mode. Redesign and write code to address this internet connectivity issue. For specific requirements and code implementation, refer to the corresponding job part of the CD.

3. Schema UML Diagram

insert image description here
The design class diagram of the design program of this topic, and other diagrams:
insert image description here

4. Mode add code (JAVA language implementation)

(1) Standard implementation method of single-column mode

(1) President class

package com.glut.xusheng;

public class President {
    
    
    private static President instance;
    private String presidentName = null;
    //1.单列模式的标准实现方法
    private President(String name){
    
    
        presidentName = name;
    }
    public static President getInstance(String name){
    
    
        if (instance == null && !name.equals(null)){
    
    
            instance = new President(name);
        }
        return instance;
    }
    public void makeSpeech(){
    
    
        System.out.println("My name is" + presidentName);
        System.out.println("I am the president of the United States");
    }
}

(2) Test class TestSignleton

public class TestSignleton {
    
    
    public static void main(String[] args) {
    
    
        President president1 = President.getInstance("Bill Clinton");
        president1.makeSpeech();
        President president2 = President.getInstance("Bill Gates");
        president2.makeSpeech();
        President president3 = President.getInstance("Barack Obama");
        president3.makeSpeech();
    }
}

(3) Class diagram
insert image description here

(4) Run the screenshot
insert image description here

(2) Design using linear safe single-column mode

(1) President class

public class President {
    
    
    private static President instance;
    private String presidentName = null;
       //2.使用线性安全单列模式设计
    private President(String p){
    
    
        presidentName = p;
    }
    public static synchronized President getInstance(String p){
    
    
        if (instance == null && !p.equals(null)){
    
    
            instance = new President(p);
        }
        return instance;
    }
    public void makeSpeech(){
    
    
        System.out.println("My name is" + presidentName);
        System.out.println("I am the president of the US in the term 3001 - 3004");
    }
}

(2) Run the screenshot
insert image description here

(3) Double synchronization lock (derivative version of lazy mode) single-column mode

(1) President class

public class President {
    
    
    private static President instance;
    private String presidentName = null;
        //3.单例模式---双重同步锁(懒汉模式衍生版本)
    private President(String name){
    
    
        presidentName = name;
    }
    public static President getInstance(String name){
    
    
    //这里前面如果不加volatile,那么后面的双重判断将会出现"误判",导致线程不安全,所以加了保证安全
    //第一重检查锁定
        if (instance == null) {
    
    
        synchronized (President.class) {
    
    
            //第二重检查锁定
            if (instance == null) {
    
    
                synchronized (President.class) {
    
    
                    //注意:非原子操作
                    instance = new President(name);
                }
            }
        }
    }
        return instance;
    }
    public void makeSpeech(){
    
    
        System.out.println("My name is" + presidentName);
        System.out.println("I am the president of the US 2022");
    }
}

(2) Run the screenshot
insert image description here

(4) Static inner class single-column mode

(1) President class

public class President {
    
    
      //4.单例模式---静态内部类(饿汉模式衍生版本)
    //优点:线程安全,并且实现了延时加载(调用效率高)
    //1:初始化对象(使用的静态内部类方式)
    //private static President instance;
    private String presidentName = null;
    private static class SingletonClassInstance {
    
    
        private static final President INSTANCE = new President(null);
    }

    //2:构造器私有化
    private President(String name){
    
    
        presidentName = name;
    }
    //3:提供获取单实例方法
    public static President getInstance(String name){
    
    
        return SingletonClassInstance.INSTANCE;
    }
    public void makeSpeech(){
    
    
        System.out.println("My name is" + presidentName);
        System.out.println("I am the president of the US 2233");
    }
}

(2) Run the screenshot
insert image description here

(5) Prevent reflection and anti-sequence single-column mode

(1) President class

 //6.单例模式---防止反射和反序列化漏
    public class President {
    
    

    //1:初始化对象
    //优点:这个是线程最安全,抗并发能力最强的
    // * 缺点:没有延时加载
    private static President instance;
    private String presidentName = null;
    //1:类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)
        //2:私有化构造器
    private President(String name){
    
    
        if (instance != null){
    
    
            throw new RuntimeException();
        }
        presidentName = name;
    }
    //3:提供一个单实例方法,方法同步,调用效率低
    public static synchronized President getInstance(String name){
    
    
            if (instance == null ){
    
    
                instance = new President(name);
            }
            return instance;
        }
        public void makeSpeech(){
    
    
        System.out.println("My name is " + presidentName);
        System.out.println("I am the president of the United States2022");
    }
}

(2) Run the screenshot
insert image description here

(6) Enumerate single-column mode

(1) President class

//7.单例模式---枚举模式
    public class President {
    
    
        /**
         * 推荐使用
         * 优点:线程最安全
         */
        private static President singleton;
        //private static President instance;
        private String presidentName = null;
        //1.单列模式的标准实现方法
        private enum Singleton{
    
    
            INSTANCE;
            private President singleton;
            Singleton(){
    
    
                singleton = new President(name());
            }
            public President getInstance(){
    
    
                if (singleton == null ){
    
    
                    singleton = new President(getInstance().presidentName);
                }
                return singleton;
            }
        }
        private President(String name){
    
    
        presidentName = name;
    }
    public static President getInstance(String name){
    
    
        return Singleton.INSTANCE.singleton;
    }
    public void makeSpeech(){
    
    
        System.out.println("My name is " + presidentName);
        System.out.println("I am the president of the CHINA 2202");
    }

}

5. Overall code

(1) Client UI category

package com.glut.xusheng;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ClientUI extends JFrame{
    
    
   private static final String CONNECT = "Create Connection";
   private static final String EXIT = "Exit";
   private JTextField txtInstruction;
   private SingleLogonGUI  objLogon = null;

   public ClientUI() {
    
    
      super("ClientUI - Singleton Pattern");
      JButton btnConnect = new JButton(CONNECT);
      JButton btnExit = new JButton(EXIT);
      btnConnect.setMnemonic(KeyEvent.VK_S);
      btnExit.setMnemonic(KeyEvent.VK_X);

      ButtonHandler vf = new ButtonHandler();
      btnConnect.addActionListener(vf);
      btnExit.addActionListener(vf);
      JPanel buttonPanel = new JPanel();
      buttonPanel.setBackground(Color.green);
      buttonPanel.add(btnConnect);
      buttonPanel.add(btnExit);

      txtInstruction = new JTextField("Click to get a connection");
      txtInstruction.setBackground(Color.green);
      Container contentPane = getContentPane();
      contentPane.setLayout(new BorderLayout());
      contentPane.add(buttonPanel, "South");
      contentPane.add(txtInstruction, "Center");
      setSize(320, 120);
      setVisible(true);
   }
   private void issueWarning(){
    
    
       txtInstruction.setText("Error. You cannot start a second connection.");
	}
   class ButtonHandler implements ActionListener {
    
    
      public void actionPerformed(ActionEvent e) {
    
    
         if (e.getActionCommand().equals(EXIT)) {
    
    
            System.exit(1);
         }
         else if (e.getActionCommand().equals(CONNECT)) {
    
    
			 if(objLogon == null)
			      objLogon = SingleLogonGUI.getInstance();
			 else
			 	  issueWarning();
      }
    }
  }
  public static void main(String[]  args) {
    
    
	     ClientUI connection = new  ClientUI();
  }
}// end of class

(2) President1 class

package com.glut.xusheng;


/**
 * SingletonDemo1
 * 测试饿汉式单例模式 优点:调用效率高  缺点:不具备延时加载
 * @author
 * @version 1.0
 */
public class President1 {
    
    
    /**
     * 1 类初始化时,立即加载这个对象(没有延时加载的优势)。加载类时,天然的是线程安全的.这里使用的private封装对象(主要是安全层面的访
     *   问修饰符,和一般的属性封装为private是一样的,没有什么特别的意思)
     *   static修饰是为了实例化对象的时候的方便使用类名.方法名的方式得到这个类的单例对象
     */
    private static President1 instance=new President1();

    /**
     * 2 私有构造器(在本类的如果要继续new对象可以,private,public修饰构造器没有区别,但是外部调用该类,必须使用private修饰以防止外部
     * new出新对象,所以这里必须是private修饰构造器)
     */
    private President1() {
    
    
    }
    /**
     * 3 公开调用方法,方法没有同步,调用效率高!(必须要提供给外部一个方法创建这个类的单例(唯一)对象的方法,因为第一步static修饰类属性的
     * (就是一个对象),所以这里也必须使用static修饰返回的对象)
     */
    public static President1 getInstance(){
    
    
        return instance;
    }

    /**
     * 这是在本类测试,所以上面的化构造器即使是private修饰为私有的,但是在本类仍然可以使用构造器new对象,所以我这里写的main方法主要是为了
     * 加深对构造器为什么要私有化的理解二特意在这里的,
     * 当然,要测试单例,应该在另一个类中写个main方法测试(或者junit测试)
     * @param args
     */

    public static void main(String[] args) {
    
    
        President1 instance = President1.getInstance();
        System.out.println(instance);
        President1 instance1 = President1.getInstance();
        System.out.println(instance1);
        /**
         * 构造器私有化了,为什么仍然可以new的原因是因为这个main方法写在了单例类的内部,当然可以使用构造器(故意写在这里的)
         */
        President1 singletonDemo1=new President1();
        President1 singletonDemo2=new President1();
        System.out.println(singletonDemo1);
        System.out.println(singletonDemo2);
        /**
         * 说明:instance和instance1肯定是一个对象,但是singletonDemo1和singletonDemo2不是一个对象了
         */
    }

}

(3) SingleLogonGUI class

package com.glut.xusheng;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/*==================================================*/
// This is a sigleton class, only one instance of the class can be created.
// To use this class, you cannot use constructor because it has been
// claimed private. You can only use the static method getInstance(),
// which, in case if the instance doesent exist, will create and return an
// instance of LogonGUI to the client class. otherwise, if an instance of
// LogonGUI has already been created before, this method will just
// return that instance to the client class.
/*==================================================*/
public class SingleLogonGUI extends JFrame {
    
    
   public static final String LOGON = "Log On";
   public static final String EXIT = "Exit";
   private String USERNM="mikesun";
   private String PASSWD = "opensesame";
   private JTextField txtUser;
   private JTextField txtPassWord;
   private static SingleLogonGUI instance = null;
   private JTextField txtInstruction;

   private SingleLogonGUI() {
    
    
	    super("SingleLogonGUI - Singleton");
	    initializeGUI();
    }
    public static SingleLogonGUI getInstance() {
    
    
	      if (instance == null)
		      instance = new SingleLogonGUI();
		  return instance;
    }
   public void initializeGUI()  {
    
    
      JLabel lblUsrName = new JLabel("User Name");
      JLabel lblPassWord = new JLabel("Password");
      txtUser = new JTextField(USERNM);
      txtPassWord = new JTextField(PASSWD);
      JButton btnLogon = new JButton(LOGON);
      btnLogon.setMnemonic(KeyEvent.VK_S);
      JButton btnExit = new JButton(EXIT);
      btnExit.setMnemonic(KeyEvent.VK_X);
      ButtonHandler vf = new ButtonHandler();
      btnLogon.addActionListener(vf);
      btnExit.addActionListener(vf);
      JPanel buttonPanel = new JPanel();
      GridBagLayout gridbag = new GridBagLayout();
      buttonPanel.setLayout(gridbag);
      GridBagConstraints gbc = new GridBagConstraints();

      buttonPanel.add(lblUsrName);
      buttonPanel.add(txtUser);
      buttonPanel.add(lblPassWord);
      buttonPanel.add(txtPassWord);
      buttonPanel.add(btnLogon);
      buttonPanel.add(btnExit);
      gbc.insets.top = 5;
      gbc.insets.bottom = 5;
      gbc.insets.left = 5;
      gbc.insets.right = 5;
      gbc.gridx = 0;
      gbc.gridy = 0;
      gridbag.setConstraints(lblUsrName, gbc);
      gbc.anchor = GridBagConstraints.WEST;
      gbc.gridx = 1;
      gbc.gridy = 0;
      gridbag.setConstraints(txtUser, gbc);
      gbc.gridx = 0;
	  gbc.gridy = 1;
	  gridbag.setConstraints(lblPassWord, gbc);
	  gbc.anchor = GridBagConstraints.WEST;
	  gbc.gridx = 1;
	  gbc.gridy = 1;
      gridbag.setConstraints(txtPassWord, gbc);
      gbc.anchor = GridBagConstraints.EAST;
      gbc.insets.left = 2;
      gbc.insets.right = 2;
      gbc.insets.top = 40;
      gbc.gridx = 0;
      gbc.gridy = 6;
      gridbag.setConstraints(btnLogon, gbc);
      gbc.anchor = GridBagConstraints.WEST;
      gbc.gridx = 1;
      gbc.gridy = 6;
      gridbag.setConstraints(btnExit, gbc);

      Container contentPane = getContentPane();
      contentPane.add(buttonPanel, BorderLayout.CENTER);
      txtInstruction = new JTextField();
      txtInstruction.setBackground(Color.pink);

      contentPane.add( txtInstruction, BorderLayout.NORTH);
      setSize(320, 200);
      setVisible(true);
   }
   public boolean isValideCustomer() {
    
    
	  String usr = txtUser.getText();
	  String pwd = txtPassWord.getText();
	  if(usr.equals(USERNM) && pwd.equals(PASSWD))
            return true;
      else
      	    return false;
   }
   private void issueWarning(){
    
    
         txtInstruction.setText("Invalide user name or password.");
	}
   private void issueSuccess(){
    
    
	     txtInstruction.setText("You have been successfully connected to the web.");
	}
   class ButtonHandler implements ActionListener  {
    
    
      public void actionPerformed(ActionEvent e) {
    
    
         if (e.getActionCommand().equals(EXIT)) {
    
    
            System.exit(1);
         }
         if (e.getActionCommand().equals(LOGON)) {
    
    
			 boolean isValideCus = isValideCustomer();
             if(isValideCus == false){
    
     //logon failed
                 issueWarning();
			 }
             else{
    
     //logon successfully
				 issueSuccess();
		     }
      }
    }
  }
}// end of class


(4) TestSignleton class

package com.glut.xusheng;

public class TestSignleton {
    
    
    public static void main(String[] args) {
    
    
        President president1 = President.getInstance("Bill Clinton");
        president1.makeSpeech();
        President president2 = President.getInstance("Bill Gates");
        president2.makeSpeech();
        President president3 = President.getInstance("Barack Obama");
        president3.makeSpeech();
    }
}

6. Run the screenshot

insert image description here
insert image description here
insert image description here

7. Experiment summary

The concept of singleton mode and its advantages and disadvantages:
(1) Definition:
It is required that a class can only generate one object, and all objects have the same dependence on it.
(2) Advantages:
There is only one instance, reducing memory overhead. The application reduces the performance overhead of the system on a frequently accessed object. When the application starts, a singleton object is directly generated and permanently resident in memory.
To avoid multiple occupation of resources, global access points can be set in the system to optimize and share resource access.
(3) Disadvantages:
1. Generally, there is no interface, and it is difficult to expand. Reason: The interface has no meaning for the singleton pattern; it requires "self-instantiating" and provides a single instance, and the interface or abstract class cannot be instantiated. (Of course, the singleton mode can implement the interface and be inherited, but it needs to be judged according to the system development environment)
2. The singleton mode is not good for testing. If the singleton mode is not completed, it cannot be tested.
3. The singleton pattern conflicts with the single responsibility principle. Reason: A class should only implement one logic, regardless of whether it is a singleton or not. Whether it needs a singleton depends on the environment; the singleton pattern integrates "singleton" and business logic into one class.
(4) Usage scenarios:
1. It is required to generate a unique serialized environment

2. A shared access point or shared data point required by the project.
3. Creating an object requires excessive resource consumption. Such as: to access resources such as IO and database.
4. An environment that needs to define a large number of static constants and static methods (such as tool classes). You can use the singleton mode or directly declare static.
(5) Precautions:
1. Other methods in the class should be static as much as possible
. 2. Pay attention to the garbage collection mechanism of the JVM.
If a singleton object is not used for a long time in memory, the JVM considers the object to be a garbage. So if some state values ​​are recycled, the application will fail.
3. There are two methods of using the singleton mode to record the class of the state value:
(1) The life cycle of the singleton is managed by the container. The Java EE container or framework-level container manages the life cycle of objects by itself.
(2) The status is recorded at any time. Asynchronously record or use the observer mode to record state changes to ensure that reinitialization can also obtain data before destruction from the resource environment.

Guess you like

Origin blog.csdn.net/m0_52435951/article/details/125063646