组合模式及单例模式
组合模式
将一组对象组织(Compose)成树形结构,以表示一种“部分 - 整体”的层次结构。
示例:文本打印
组合设计模式模拟窗口显示
Component.java
public interface Component{ public String getName(); public void print();}
Composite.java
import java.util.ArrayList;import java.util.List;public class Composite implements Component{ private String name; private List<Component> componentList = new ArrayList<Component>(); public Composite(String name){ this.name = name; } public String getName(){ return this.name; } public void add(Component component){ componentList.add(component); } public void print() { System.out.println(name); for (Component component : componentList) { component.print(); } }}
Leaf.java
public class Leaf implements Component { private String name; public Leaf(String name) { this.name = name; } public String getName() { return this.name; } public void print() { System.out.println(name); }}
Windows.java
public class Windows { public static void print(){ Composite winform = new Composite("WinForm(WINDOW窗口)"); Leaf picture = new Leaf("Picture(LOGO图片)"); Leaf loginbutton = new Leaf("Button(登录)"); Leaf registerbutton = new Leaf("Button(注册)"); winform.add(picture); winform.add(loginbutton); winform.add(registerbutton); Composite frame = new Composite("Frame(FRAME1)"); Leaf label = new Leaf("Lable(用户名)"); Leaf textbox = new Leaf("Text(文本框)"); Leaf password = new Leaf("PasswordBox(密码框)"); Leaf checkbox = new Leaf("CheckBox(复选框)"); Leaf textbox2 = new Leaf("TextBox(记住用户名)"); Leaf linklabel = new Leaf("Linkable(忘记密码)"); frame.add(label); frame.add(textbox); frame.add(password); frame.add(checkbox); frame.add(textbox2); frame.add(linklabel); winform.add(frame); winform.print(); } public static void main(String[] args) { print(); }}
示例:java swing图形打印
Button.java
import javax.swing.*;public class Button extends JButton { public void print() { System.out.println(getText()); } public Button(String text) { super(text, null); print(); }}
CheckBox.java
import javax.swing.*;public class CheckBox extends JCheckBox { public void print() { System.out.println(getText()); } public CheckBox (String text) { super(text, null, false); print(); }}
Frame.java
import javax.swing.*;public class Frame extends JPanel { private String name; public void print() { System.out.println(name); } public Frame(String text) { super(true); this.name = text; print(); }}
Label.java
import javax.swing.*;public class Lable extends JLabel { //private String name; public void print() { System.out.println(getText()); } public Lable(String text) { super(text, null, LEADING); //this.name = text; print(); }}
Linkable.java
import javax.swing.*;import java.awt.*;public class Linkable extends JLabel { public void print() { System.out.println(getText()); } public Linkable(String text) { super(text, null, LEADING); this.setForeground(Color.BLUE.darker()); this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); print(); }}
Picture.java
import javax.swing.*;import java.awt.*;public class Picture extends JLabel{ //private String name; public void print() { System.out.println(getText()); } public Picture(String text, String ImageName) { super(text, null, LEADING); Image image = new ImageIcon(ImageName).getImage(); setIcon(new ImageIcon(image)); //his.name = text; print(); }}
TextBox.java
import javax.swing.*;public class TextBox extends JTextField { //JTextComponent 有同名函数 public void printbox() { System.out.println(getText()); } public TextBox(String text) { super(null, text, 0); printbox(); }}
WinForm.java
import javax.swing.*;import java.awt.*;public class WinForm extends JFrame { //private String name; public WinForm(String title) throws HeadlessException { super(title); super.frameInit(); //this.name = title; print(); } public void print() { System.out.println(getTitle()); }}
Windows.java
import org.w3c.dom.Text;import javax.swing.*;import java.awt.*;public class Windows { public static void main(String args[]) { WinForm winForm = new WinForm("Window窗口"); winForm.setSize(600, 400); winForm.setLocationRelativeTo(null); winForm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Picture picture = new Picture("LOGO图片","d:/background.jpg"); picture.setBounds(200, 10, 160, 120); winForm.add(picture); Button loginButton = new Button("登录"); loginButton.setBounds(200, 300, 80, 25); winForm.add(loginButton); Button registerButton = new Button("注册"); registerButton.setBounds(300, 300, 80, 25); winForm.add(registerButton); Frame frame = new Frame("FRAME1"); frame.setLayout(null); //设置布局为 null winForm.add(frame); Lable userName = new Lable("用户名"); userName.setBounds(100, 160, 80, 25); frame.add(userName); TextBox userNameBox = new TextBox("用户名文本框"); userNameBox.setBounds(150, 160, 80, 25); frame.add(userNameBox); Lable passWord = new Lable("密码"); passWord.setBounds(100, 210, 80, 25); frame.add(passWord); TextBox passWordBox = new TextBox("用户名文本框"); passWordBox.setBounds(150, 210, 80, 25); frame.add(passWordBox); CheckBox rememberPwd = new CheckBox("记住户名"); rememberPwd.setBounds(100, 250, 80, 25); //rememberPwd.setSize(,200); frame.add(rememberPwd);/* Lable rememberPwdLabel = new Lable("记住用户名"); rememberPwdLabel.setBounds(180, 250, 80, 25); frame.add(rememberPwdLabel);*/ Linkable retrievePwd = new Linkable("忘记密码"); retrievePwd.setBounds(350, 250, 80, 25); frame.add(retrievePwd); winForm.setVisible(true); }}
输出结果:
单例模式
实现类只创建一个实例。
私有构造函数: 使得外部无法通过new创建实例,
静态方法:能通过类获取类实例
私有静态变量:使得类实例化创建惟一对象。
饿汉模式(推荐)
定义类时,单实例创建。
特点: 启动慢,引用快。
懒汉模式
获取实例的时创建,需要synchronized同步等待,防止并发处理异常。
特点: 启动快,引用慢。
2020/10/11 更新
根据助教老师的建议又看了下 double-checked locking 方式实现的单例
public class Singleton { private Singleton() {} private volatile static Singleton instance = null; public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; }}
对于 volatile, 查到网上帖子, 大多是是说由于编译器优化导致的指令重排可能导致new出来的对象的部分初始化问题, 我 查到的 比较早的资料 "Double-Checked Locking is Broken" Declaration
https://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html 提到 the Symantec JIT 会在构造函数前对申请对象的引用赋值。
最后一个解决方案来自Joshua Block的Effective Java(第3册),使用枚举.
public enum Singleton { INSTANCE; ...}
2020-10-28 更新参考老师讲义写了个一个单例的工厂方法。
SingletonFactory.java
import java.io.IOException;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Properties;public class SingletonFactory { private final static Properties IMPLS = loadImpls(); private static Properties loadImpls() { Properties defaultImpls = new Properties(); Properties impls = new Properties(defaultImpls); defaultImpls.setProperty("Singleton","Singleton"); try{ impls.load(SingletonFactory.class.getResourceAsStream("singleton.properties")); } catch (IOException e){ throw new RuntimeException(e); } return impls; } @SuppressWarnings("unchecked") public static <T> T getSingleton() { String implClassName = IMPLS.getProperty("Singleton"); try { Class implClass = Class.forName(implClassName); Method m = implClass.getMethod("getInstance"); return (T) m.invoke(null); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; }}
Singleton.java
public abstract class Singleton { public static Singleton getInstance(){ return null; };}
SingleNormal.java
public class SingletonNormal extends Singleton{ private SingletonNormal(){System.out.println("Normal Singleton");}; private static SingletonNormal instance = new SingletonNormal(); public static Singleton getInstance(){ return instance; }}
SingleDoubleCheck.java
public class SingletonDoubleCheck extends Singleton{ private SingletonDoubleCheck(){System.out.println("Double check Thread Safe Singleton");} private volatile static SingletonDoubleCheck instance = null; public static Singleton getInstance() { if (instance == null){ synchronized (SingletonDoubleCheck.class){ if (instance == null){ instance = new SingletonDoubleCheck(); } } } return instance; }}
SingletonLazy.java
public class SingletonLazy extends Singleton { private SingletonLazy() {System.out.println("Thread Safe Singleton");}; private volatile static SingletonLazy instance = null; public static synchronized Singleton getInstance(){ if (instance == null){ instance = new SingletonLazy(); } return instance; }}
Client.java
public class Client { public static void main(String[] args){ Singleton singleton1 = (Singleton) SingletonFactory.getSingleton(); Singleton singleton2 = (Singleton) SingletonFactory.getSingleton(); System.out.println(singleton1==singleton2); }}
singleton.properties
Singleton=SingletonNormal
验证输出:
Normal Singletontrue
可以通过修改配置文件 singleton.properties里 Singleton 指定不同的实现方式。
参考及引用
架构师训练营作业-李智慧老师相关讲义
Photo by Adrianna Calvo from Pexels
garlic
还未添加个人签名 2017.11.15 加入
还未添加个人简介
评论