極客大學架構師訓練營 框架開發 第三次作業

1. 請在草稿紙上手寫一個單例模式的實現代碼,拍照提交作業。

說明:筆者拍照實現餓漢式單例類,也就是應用一啓動,就會把單例對象加載到內存。
在這裏插入圖片描述

問什麼要試用 Singleton

Singleton 模式保證產生單一實例,就是說一個類只產生一個實例。試用 Singleton 有兩個原因

  • 是因爲只有一個實例,可以減少實例頻繁創建和銷燬帶來的資源消耗。
  • 是當多個用戶試用這個實例的時候,便於進行統一控制(比如打印機對象)。

前者是性能需求,後者是功能需求。

餓漢式 Singleton

public class HungrySingleton {
	private static HungrySingleton instance = new HungrySingleton();
	private HungrySingleton() {
	}
	public static HungrySingleton getInstance() {
		return instance;
	}
}

注意:一定要有私有的構造函數,保證實例只能通過getInstance() 方法獲得。

儘量使用餓漢式構造單實例。單例中的成員變量是多線程重用的,可能會產生意想不到的結果,因此儘量將單例設計爲無狀態對象(只提供服務,不保存狀態)。

餓漢式 Singleton 的問題是,應用一啓動就加載對象進內存,就算從來未被用過。

懶漢式 Singleton

publci class LazySingleton {
	private static LazySingleton instance = null;
	private LazySingleton() {
	
	}

	public static synchronized LazySingleton getInstance() {
		if (instance == null) {
			instance = new LazySingleton();
		}

		return instance;
	}
}

注意: getInstance() 的修飾符 synchronized 一定要加上,否則可能會產生多重實例。

懶漢式Singleton解決了餓漢式Singleton,當調用的時候纔去加載對象到內存。但是引發了另外一個性能問題,每次訪問對象都要加鎖。

提升性能的 懶漢式 Singleton

publci class LazySingleton {
	private static LazySingleton instance = null;
	private LazySingleton() {
	
	}

	public static LazySingleton getInstance() {
		if (instance == null) {
			instance = LazySingleton.buildInstance();
		}

		return instance;
	}

	private static synchronized LazySingleton buildInstance() {
		if (instance == null) {
			instance = new LazySingleton();
		}
		
		return instance;
	}
}

只有當對象爲null的時候,纔去加鎖創建對象。

2. 請用組合設計模式編寫程序

打印輸出圖 1 的窗口,窗口組件的樹結構如圖 2 所示,打印輸出示例參考圖 3。

在這裏插入圖片描述

組合模式的類圖:

在這裏插入圖片描述

package structure;

import java.util.ArrayList;
import java.util.List;

interface Item {
  void print();
  String getName();
  void setName(String name);
  List<Item> getChilds();
  int addChild(Item item);
}

abstract class Component implements Item {
  private List<Item> childs = new ArrayList<>();
  private String name;

  @Override
  public String getName() {
    return name;
  }

  @Override
  public void setName(String name) {
    this.name = name;
  }

  @Override
  public List<Item> getChilds() {
    return childs;
  }

  @Override
  public void print() {
    String className = this.getClass().getSimpleName();
    System.out.println("print " + className + "(" + getName() + ")");
    List<Item> childs = getChilds();

    for (Item item: childs) {
      item.print();
    }
  }

  @Override
  public int addChild(Item item) {
    List<Item> childs = getChilds();
    if (childs == null) {
      return 0;
    }
    if (item != null) {
      childs.add(item);
    }

    return childs.size();
  }
}


class WinForm extends Component { }
class Button extends Component { }
class CheckBox extends Component { }
class Frame extends Component { }
class Label extends Component { }
class LinkLabel extends Component { }
class PasswordBox extends Component { }
class Picture extends Component { }
class TextBox extends Component { }


public class Composition {

  public static void main(String[] args) throws IllegalAccessException, InstantiationException {
    Item mainForm = createChild("WINDOW窗口", WinForm.class);

    addChilds(mainForm);

    mainForm.print();
  }

  static <T> Item createChild(String name, Class<T> clazz) throws IllegalAccessException, InstantiationException {
    Item child = (Item)clazz.newInstance();
    child.setName(name);
    return child;
  }

  static void addChilds(Item mainForm) throws InstantiationException, IllegalAccessException {
    mainForm.addChild(createChild("LOGO圖片", Picture.class));
    mainForm.addChild(createChild("登錄", Button.class));
    mainForm.addChild(createChild("註冊", Button.class));
    Item frame = createChild("FRAME1", Frame.class);
    mainForm.addChild(frame);
    frame.addChild(createChild("用戶名", Label.class));
    frame.addChild(createChild("文本框", TextBox.class));
    frame.addChild(createChild("密碼", Label.class));
    frame.addChild(createChild("密碼框", PasswordBox.class));
    frame.addChild(createChild("複選框", CheckBox.class));
    frame.addChild(createChild("記住用戶名", TextBox.class));
    frame.addChild(createChild("忘記密碼", LinkLabel.class));
  }
}

輸出結果

print WinForm(WINDOW窗口)
print Picture(LOGO圖片)
print Button(登錄)
print Button(註冊)
print Frame(FRAME1)
print Label(用戶名)
print TextBox(文本框)
print Label(密碼)
print PasswordBox(密碼框)
print CheckBox(複選框)
print TextBox(記住用戶名)
print LinkLabel(忘記密碼)

第二題助教老師提供的參考答案(Java實現)

https://github.com/kim118000/geek-code

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章