单例模式
简述:设计一个类,只能创建一个实例
- 设计模式是在实践中总结和理论化后优选的代码结构、编程风格、以及解决问题的思考方式。
- 设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考和摸索。
饿汉式
- 返回true,说明指向同一块内存空间(即单个实例)
- 不允许外部创建,只能内部创建
- 为了体现封装性,将属性私有化,提供公共的方法来调用
- 静态方法只能调用静态变量,所以类的实例也为static
懒汉式
- 第一次调用,创建对象,再返回对象
- 第二次调用,已经创建完成,直接返回对象
- 不管怎么样,都new了且仅一次,且都return instance
区分
- 对象一个开始已创建完毕,一个开始未创建
- 饿汉式典型应用:Runtime类
- 懒汉式
- 好处:没调用创建方法时,没有该类的实例
- 坏处:线程安全问题
线程安全问题解释
- 一个进程有多个线程
- 第一个线程执行到横向箭头处sleep(),转而第二个线程执行,创建对象并返回
第一个线程接着执行,又创建了个不同的对象并返回,问题就出现了
单例模式练习(bank项目)
Bank类
主要修改Bank类为单例模式
package banking6.domain;
public class Bank {
private Customer[] customers;
private int numberOfCustomer;
private Bank(){
customers = new Customer[5];
}
private static Bank bank = new Bank();
public static Bank getBanking(){return bank; }
public void addCustomer(String f,String l){
Customer cust = new Customer(f,l);
customers[numberOfCustomer] = cust;
numberOfCustomer++;
}
public int getNumOfCustomers() {
return numberOfCustomer;
}
public Customer getCustomer(int index){
return customers[index];
}
}
##CustomerReport类
封装打印报表功能
package banking6.reports;
import java.text.NumberFormat;
import banking6.domain.*;
public class CustomerReport {
private Customer customer;//下文为引用赋值,不用担心NULL异常
private Bank bank = Bank.getBanking();
public void generateReport(){
NumberFormat currency_format = NumberFormat.getCurrencyInstance();
// Generate a report
System.out.println("\t\t\tCUSTOMERS REPORT");
System.out.println("\t\t\t================");
for ( int cust_idx = 0; cust_idx < bank.getNumOfCustomers(); cust_idx++ ) {
customer = bank.getCustomer(cust_idx);
System.out.println();
System.out.println("Customer: "
+ customer.getLastName() + ", "
+ customer.getFirstName());
for ( int acct_idx = 0; acct_idx < customer.getNumOfAccounts(); acct_idx++ ) {
Account account = customer.getAccount(acct_idx);
String account_type = "";
// Determine the account type
/*** Step 1:
**** Use the instanceof operator to test what type of account
**** we have and set account_type to an appropriate value, such
**** as "Savings Account" or "Checking Account".
***/
if(account instanceof SavingAccount){
account_type = "SavingAccount";
}
if(account instanceof CheckAccount){
account_type = "CheckAccount";
}
// Print the current balance of the account
/*** Step 2:
**** Print out the type of account and the balance.
**** Feel free to use the currency_format formatter
**** to generate a "currency string" for the balance.
***/
System.out.println(account_type+ ": current balance is "+currency_format.format(account.getBalance()));
}
}
}
}
测试类
package TestBanking;
/*
* This class creates the program to test the banking classes.
* It creates a set of customers, with a few accounts each,
* and generates a report of current account balances.
*/
import banking6.domain.*;
import banking6.reports.CustomerReport;
public class TestBanking6 {
public static void main(String[] args) {
Bank bank = Bank.getBanking();
Customer customer;
CustomerReport report = new CustomerReport();
// Create several customers and their accounts
bank.addCustomer("Jane", "Simms");
customer = bank.getCustomer(0);
customer.addAccount(new SavingAccount(500.00, 0.05));
customer.addAccount(new CheckAccount(200.00, 400.00));
bank.addCustomer("Owen", "Bryant");
customer = bank.getCustomer(1);
customer.addAccount(new CheckAccount(200.00));
bank.addCustomer("Tim", "Soley");
customer = bank.getCustomer(2);
customer.addAccount(new SavingAccount(1500.00, 0.05));
customer.addAccount(new CheckAccount(200.00));
bank.addCustomer("Maria", "Soley");
customer = bank.getCustomer(3);
// Maria and Tim have a shared checking account
customer.addAccount(bank.getCustomer(2).getAccount(1));
customer.addAccount(new SavingAccount(150.00, 0.05));
// Generate a report
report.generateReport();
}
}
main方法
static表示生命周期,随类创建而创建
- 主方法有形参,可传入值,进行输出等,特殊的方法,可直接调用参数(在main方法里调用args)
通过该方式(传入形参)和程序交互,而不是scanner类
通过命令行方式交互
- 上方main()方法调用下方main()一般方法(静态方法)
- 下方main()方法作为一般方法执行(遍历并赋值)
总结,既可作为程序入口,又可作为一般方法