薪水支付案例

一.需求

開發(fā)一個薪水支付系統(tǒng)牲尺,為公司每個雇員支付薪水宪卿,系統(tǒng)必須按照規(guī)定的方法準時地給雇員支付正確數(shù)目的薪水,同時望众,必須從雇員的薪水中減去各種扣款匪补。

雇員的種類:

  • 鐘點工,按小時付費烂翰,當工作時間超過8小時時夯缺,按超過的部分按1.5倍收費。雇員信息中會給出每小時的酬金甘耿,每周五支付踊兜。
  • 月薪雇員,在每個月的最后一天發(fā)放工資佳恬,雇員信息中會給出月薪的酬金捏境。
  • 帶薪雇員,固定的工資+銷售提成毁葱,提成根據(jù)銷售情況來算垫言,雇員會提交銷售憑條,里面包含了銷售日期和數(shù)量倾剿,雇員信息中含有固定工資字段和提成酬金字段筷频,每隔一周的周五支付。

支付方式:

  • 將支付支票郵寄到指定的郵政地址
  • 將支付支票存到稅務人員那里隨時支取
  • 將薪水直接打到銀行賬戶中

扣款項:

  • 雇員加入?yún)f(xié)會,協(xié)會每周會收取費用凛捏,另外協(xié)會會不定時的收取其他服務費用担忧,費用直接從薪水中扣除。

運行方式:

可以輸入指定日期或直接取當天日期葵袭,并發(fā)放該日期的薪水涵妥,可以運行一次或多次。

二.用例

image.png
image.png
image.png

三.初步分析

首先坡锡,雇員的種類有三種蓬网,第一時間可能會想到通過Employee來派生三個子類,但是鹉勒,用例中有更改雇員類型的操作帆锋,鐘點工和帶薪雇員是可以轉(zhuǎn)換的,這意味著禽额,派生子類的設計不能在這里使用锯厢。我們可以使用策略模式,將雇員類型抽象為策略類脯倒,每個策略類中包含表示該類型雇員的特有字段实辑,雇員的支付方式同理。最后是處理協(xié)會這個扣費項藻丢,采用組合的方式剪撬,使每個Employee對象包含一個協(xié)會對象Affiliation,當然這是個基類悠反,因為雇員可以選擇加入?yún)f(xié)會残黑,也可以不選擇,這需要兩個子類來表示斋否,一個是包含服務酬金的UnionAffiliation梨水,表示加入?yún)f(xié)會,另一個是NoAffiliation茵臭,表示沒有加入任何協(xié)會疫诽。

四.初步設計

image.png

五.設計背后的思考

在上述UML圖中,我們并沒有看到雇員支付薪水的方法旦委,它的設計將被推遲到PaymentClassifiction類中奇徒,該類保存了計算薪水所需要的數(shù)據(jù)。另外社证,每種雇員他們支付薪水的時間點是完全不同的,但是UML圖中并沒有考慮到這點评凝,我們很容易的想到使用策略模式追葡,即將每個具體支付時間點抽象為策略類,具體設計如下。

image.png

六.具體實現(xiàn)

  • 數(shù)據(jù)庫對象

package cn.zzf.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author GaoFeng2017
 * @date 2018-06-06 14:48:36
 **/

public class EmpDB {

    private Map<Integer,Employee> employees = new HashMap<>(16);
    private Map<Integer,Employee> members = new HashMap<>(16);

    private static EmpDB db = new EmpDB();

    private EmpDB() {
    }

    public Employee getEmployee(Integer employeeId) {
        return employees.get(employeeId);
    }

    public List<Employee> getAll() {
        return new ArrayList<>(employees.values());
    }

    public boolean removeEmployee(Integer employeeId) {
        return employees.remove(employeeId) != null;
    }

    public void addEmployee(Employee employee) {
        employees.put(employee.getEmployeeId(),employee);
    }

    public void clear() {
        employees.clear();
    }

    public Employee getMember(Integer memberIds) {
        return members.get(memberIds);
    }

    public void addUnionAffiliation(Integer memberId,Employee employee) {
        members.put(memberId,employee);
    }

    public void removeUnionAffiliation(Integer memberId) {
        members.remove(memberId);
    }

    public static EmpDB getDB() {
        return db;
    }
}

  • 增加雇員

image.png

package cn.zzf.impl;

/**
 * @author GaoFeng2017
 * @date 2018-06-06 14:38:11
 **/

public abstract class AddEmployeeTransaction implements Transaction {

    private EmpDB db = EmpDB.getDB();

    /** 雇員姓名 */
    private String name;

    /** 雇員住址 */
    private String address;

    /** 雇員Id */
    private Integer EmpId;

    public AddEmployeeTransaction(String name, String address, Integer empId) {
        this.name = name;
        this.address = address;
        EmpId = empId;
    }

    @Override
    public void execute() {
        Employee e = new Employee(this.name,this.address,this.EmpId);
        PaymentMethod method = new HoldMethod();
        e.setPaymentClassification(getPaymentClassification());
        e.setPaymentSchedule(getPaymentSchedule());
        e.setPaymentMethod(new HoldMethod());
        e.setAffiliation(new NoAffiliation());
        db.addEmployee(e);
    }

    /**
     * 獲取雇員支付策略
     * @author: GaoFeng2017
     * @date: 2018/6/6 15:54
     * @param:
     * @return:
     *
     */
    public abstract PaymentClassification getPaymentClassification();

    /**
     * 獲取支付時間表
     * @author: GaoFeng2017
     * @date: 2018/6/7 11:33
     * @param:
     * @return:
     *
     */
    public abstract PaymentSchedule getPaymentSchedule();

    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Integer getEmpId() {
        return EmpId;
    }

    public void setEmpId(Integer empId) {
        EmpId = empId;
    }
}

package cn.zzf.impl;

/**
 * @author GaoFeng2017
 * @date 2018-06-06 16:05:17
 **/

public class AddCommissionedTransaction extends AddEmployeeTransaction {

    private double monthSalary;
    private double commissionRate;

    public AddCommissionedTransaction(String name, String address, Integer empId, double monthSalary, double commissionRate) {
        super(name, address, empId);
        this.monthSalary = monthSalary;
        this.commissionRate = commissionRate;
    }

    @Override
    public PaymentClassification getPaymentClassification() {
        return new CommissionedClassification(monthSalary,commissionRate);
    }

    @Override
    public PaymentSchedule getPaymentSchedule() {
        return new BiWeeklySchedule();
    }
}

AddEmployeeTransaction類使用了模板方法模式宜肉,每個addTransaction添加的步驟是一樣的匀钧,只是雇員類型和支付薪水時間表不同而已,該操作被封裝成了模板方法谬返,子類只需實現(xiàn)getClassification之斯,getSchedule兩個抽象方法。這里只給出Commission雇員類型的實現(xiàn)遣铝,需要完整代碼的可以在github上下載佑刷,下面的代碼也將省略掉一些“重復“實現(xiàn)。

  • 刪除雇員

package cn.zzf.impl;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 11:42:42
 **/

public class DeleteEmployeeTransaction implements Transaction{

    private Integer empId;
    private EmpDB db = EmpDB.getDB();

    public DeleteEmployeeTransaction(Integer empId) {
        this.empId = empId;
    }

    @Override
    public void execute() {
        db.removeEmployee(empId);
    }
}

  • 時間卡酿炸,銷售憑條以及服務費用

image.png
image.png
image.png
package cn.zzf.impl;

import java.util.Objects;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 11:55:10
 **/

public class TimeCardTransaction implements Transaction {
    private Integer empId;
    private TimeCard timeCard;
    private EmpDB db = EmpDB.getDB();

    public TimeCardTransaction() {

    }

    public TimeCardTransaction(Integer empId, TimeCard timeCard) {
        this.empId = empId;
        this.timeCard = timeCard;
    }

    @Override
    public void execute() {
        Employee employee = db.getEmployee(empId);
        PaymentClassification paymentClassification = employee.getPaymentClassification();

        if (!Objects.equals(paymentClassification.getClass(),HourlyClassification.class)) {
            throw new RuntimeException("關聯(lián)失敗瘫絮,雇員不是鐘點工");
        }
        HourlyClassification classification = (HourlyClassification) employee.getPaymentClassification();
        classification.getTimeCards().add(timeCard);
    }
}

package cn.zzf.impl;

import java.util.Date;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 10:37:51
 **/

public class TimeCard {
    private Date date;
    private int hours;

    public TimeCard() {
    }

    public TimeCard(Date date, int hours) {
        this.date = date;
        this.hours = hours;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public int getHours() {
        return hours;
    }

    public void setHours(int hours) {
        this.hours = hours;
    }
}

package cn.zzf.impl;

import java.util.Date;
import java.util.LinkedList;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 13:40:22
 **/

public class ServiceChargeTransaction implements Transaction {

    private Integer memberId;
    private Date date;
    private Double amount;
    private EmpDB db  = EmpDB.getDB();


    public ServiceChargeTransaction() {
    }

    public ServiceChargeTransaction(Integer memberId, Date date, Double amount) {
        this.memberId = memberId;
        this.date = date;
        this.amount = amount;
    }

    @Override
    public void execute() {
        Employee employee = db.getMember(memberId);
        UnionAffiliation unionAffiliation = (UnionAffiliation) employee.getAffiliation();
        unionAffiliation.getServiceCharges().add(new ServiceCharge(date,amount));
    }
}

package cn.zzf.impl;

import java.util.Date;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 11:16:15
 **/

public class ServiceCharge {

    private Date date;
    private Double amount;

    public ServiceCharge() {
    }

    public ServiceCharge(Date date, Double amount) {
        this.date = date;
        this.amount = amount;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public Double getAmount() {
        return amount;
    }

    public void setAmount(Double amount) {
        this.amount = amount;
    }
}

  • 更改雇員屬性

image.png
image.png
package cn.zzf.impl;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 15:37:12
 **/

public abstract class ChangeEmployeeTransaction implements Transaction{
    private Integer empId;
    private EmpDB db = EmpDB.getDB();

    public ChangeEmployeeTransaction(Integer empId) {
        this.empId = empId;
    }

    public ChangeEmployeeTransaction() {
    }

    @Override
    public void execute() {
        Employee e = db.getEmployee(empId);
        if (e != null) {
            change(e);
        }
    }

    /** 改變雇員屬性 */
    public abstract void change(Employee employee);
}

package cn.zzf.impl;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 15:44:39
 **/

public class ChangeNameTransaction extends ChangeEmployeeTransaction {

    private String name;

    public ChangeNameTransaction(Integer empId, String name) {
        super(empId);
        this.name = name;
    }

    @Override
    public void change(Employee employee) {
        employee.setName(name);
    }
}

package cn.zzf.impl;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 15:49:35
 *
 **/

public abstract class ChangeClassificationTransaction extends ChangeEmployeeTransaction {

    public ChangeClassificationTransaction(Integer empId) {
        super(empId);
    }

    @Override
    public void change(Employee employee) {
        employee.setPaymentClassification(getPaymentClassification());
        employee.setPaymentSchedule(getPaymentSchedule());
    }

    /**
     * 獲取雇員要更改的支付策略
     * @author: GaoFeng2017
     * @date: 2018/6/7 16:00
     * @param:
     * @return:
     *
     */
    public abstract PaymentClassification getPaymentClassification();

    /**
     * 獲取雇員要更改的薪水支付時間表
     * @author: GaoFeng2017
     * @date: 2018/6/7 16:00
     * @param:
     * @return:
     *
     */
    public abstract PaymentSchedule getPaymentSchedule();
}

package cn.zzf.impl;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 16:05:16
 **/

public class ChangeHourlyTransaction extends ChangeClassificationTransaction {

    private Double hourlyRate;

    public ChangeHourlyTransaction(Integer empId, Double hourlyRate) {
        super(empId);
        this.hourlyRate = hourlyRate;
    }

    @Override
    public PaymentClassification getPaymentClassification() {
        return new HourlyClassification(hourlyRate);
    }

    @Override
    public PaymentSchedule getPaymentSchedule() {
        return new WeeklySchedule();
    }
}

package cn.zzf.impl;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 16:39:10
 **/

public abstract class ChangeAffiliationTransaction extends ChangeEmployeeTransaction {

    public ChangeAffiliationTransaction(Integer empId) {
        super(empId);
    }

    @Override
    public void change(Employee employee) {
        recordMembership(employee);
        employee.setAffiliation(getAffiliation());
    }

    /**
     * 獲取雇員要修改的會員
     *
     * @author: GaoFeng2017
     * @date: 2018/6/7 16:42
     * @param:
     * @return:
     *
     */
    public abstract Affiliation getAffiliation();


    /**
     * 確定當前雇員關系
     * @author GaoFeng2017
     * @date 2018/6/7 18:11
     * @param employee 雇員對象
     * @return
     *
     */
    public abstract void recordMembership(Employee employee);
}

package cn.zzf.impl;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 16:49:04
 **/

public class ChangeMemberTransaction extends ChangeAffiliationTransaction {

    private Double dus;
    private Integer memberId;
    private EmpDB db = EmpDB.getDB();

    public ChangeMemberTransaction(Integer empId, Double dus, Integer memberId) {
        super(empId);
        this.dus = dus;
        this.memberId = memberId;
    }

    @Override
    public Affiliation getAffiliation() {
        return new UnionAffiliation(memberId,dus);
    }

    @Override
    public void recordMembership(Employee employee) {
        db.addUnionAffiliation(memberId,employee);
    }

}

package cn.zzf.impl;

import java.util.Objects;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 16:52:27
 **/

public class ChangeNoMemberTransaction extends ChangeAffiliationTransaction {

    private EmpDB db = EmpDB.getDB();

    public ChangeNoMemberTransaction(Integer empId) {
        super(empId);
    }

//    private

    @Override
    public Affiliation getAffiliation() {
        return new NoAffiliation();
    }

    @Override
    public void recordMembership(Employee employee) {
        Affiliation affiliation = employee.getAffiliation();

        if (Objects.equals(affiliation.getClass(),NoAffiliation.class)) {
            return;
        }

        UnionAffiliation unionAffiliation = (UnionAffiliation) affiliation;

        db.removeUnionAffiliation(unionAffiliation.getMemberId());
    }


}

package cn.zzf.impl;

import java.util.Date;
import java.util.LinkedList;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 10:59:57
 **/

public class UnionAffiliation implements Affiliation {

    private Integer memberId;
    private double dues;
    private LinkedList<ServiceCharge> serviceCharges = new LinkedList<>();

    public UnionAffiliation() {

    }


    public UnionAffiliation(Integer memberId, double dues) {
        this.memberId = memberId;
        this.dues = dues;
    }

    public double getDues() {
        return dues;
    }

    public void setDues(double dues) {
        this.dues = dues;
    }

    public LinkedList<ServiceCharge> getServiceCharges() {
        return serviceCharges;
    }

    public Integer getMemberId() {
        return memberId;
    }

    public void setMemberId(Integer memberId) {
        this.memberId = memberId;
    }

    @Override
    public Double calculateDeductions(PayCheck payCheck) {
        Date aDate = payCheck.getPayStartTime();
        Date bDate = payCheck.getPayDate();
        int count = DateUtil.getFridayCount(aDate,bDate);
        Double sum = dues * count;
        for (ServiceCharge serviceCharge : serviceCharges) {
            if (DateUtil.isBetweenDate(serviceCharge.getDate(),aDate,bDate)) {
                sum += serviceCharge.getAmount();
            }
        }
        return sum;
    }
}

package cn.zzf.impl;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 19:19:56
 **/

public class NoAffiliation implements Affiliation {
    @Override
    public Double calculateDeductions(PayCheck payCheck) {
        return 0.0;
    }
}

值得注意的是,這里的ChangeAffiliationTransaction多了一個名為recordMembership的抽象方法填硕,它將會檢測雇員是否加入過協(xié)會麦萤,并且解除已經(jīng)加入的協(xié)會關系。

七.支付薪水

package cn.zzf.impl;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * @author GaoFeng2017
 * @date 2018-06-06 14:48:51
 *
 **/

public class Employee {

    private String name;
    private String address;
    private Integer employeeId;
    private PaymentClassification paymentClassification;
    private PaymentMethod paymentMethod;
    private PaymentSchedule paymentSchedule;
    private Affiliation affiliation;

    public Employee(String name, String address, Integer employeeId) {
        this.name = name;
        this.address = address;
        this.employeeId = employeeId;
    }

    public Affiliation getAffiliation() {
        return affiliation;
    }

    public void setAffiliation(Affiliation affiliation) {
        this.affiliation = affiliation;
    }

    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Integer getEmployeeId() {
        return employeeId;
    }

    public void setEmployeeId(Integer employeeId) {
        this.employeeId = employeeId;
    }

    public PaymentClassification getPaymentClassification() {
        return paymentClassification;
    }

    public void setPaymentClassification(PaymentClassification paymentClassification) {
        this.paymentClassification = paymentClassification;
    }

    public PaymentMethod getPaymentMethod() {
        return paymentMethod;
    }

    public void setPaymentMethod(PaymentMethod paymentMethod) {
        this.paymentMethod = paymentMethod;
    }

    public PaymentSchedule getPaymentSchedule() {
        return paymentSchedule;
    }

    public void setPaymentSchedule(PaymentSchedule paymentSchedule) {
        this.paymentSchedule = paymentSchedule;
    }

    public Date getStartPayDate(Date date) {
        return paymentSchedule.getStartPayDate(date);
    }

    public void PayDay(PayCheck payCheck) {
        Double grossPay = paymentClassification.calculatePay(payCheck);
        Double deductions = affiliation.calculateDeductions(payCheck);
        Double netPay = grossPay - deductions;
        payCheck.setDeductions(deductions);
        payCheck.setGrossPay(grossPay);
        payCheck.setNetPay(netPay);
        paymentMethod.pay(payCheck);
    }

}

package cn.zzf.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author GaoFeng2017
 * @date 2018-06-07 20:31:48
 **/

public class PaydayTransaction implements Transaction {

    private Date date;
    private EmpDB db = EmpDB.getDB();
    public static  Map<Integer,PayCheck> map = new HashMap<>(16);

    public PaydayTransaction(Date date) {
        this.date = date;
    }

    @Override
    public void execute() {
        List<Employee> employees = db.getAll();
        for (Employee employee : employees) {
            System.out.println(employee.getPaymentSchedule().isPayDay(date));
            if (employee.getPaymentSchedule().isPayDay(date)) {
                PayCheck payCheck = new PayCheck(employee.getStartPayDate(date),date);
                employee.PayDay(payCheck);
                map.put(employee.getEmployeeId(),payCheck);
            }
        }
    }
}

測試程序?qū)懙谋容^混亂扁眯,就不貼上去了壮莹。
當execute被調(diào)用執(zhí)行時,將會遍歷每一個雇員對象姻檀,并且和給定的支付日期匹配命满,如果當前雇員的支付日期為給定日期,就發(fā)放薪水施敢。不過周荐,這里需要依靠payCheck對象來檢測是否重復發(fā)放薪水。
完整代碼 https://github.com/ZGAOF/oop-design/tree/master/salary-pay/src/main/java/cn/zzf/impl

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末僵娃,一起剝皮案震驚了整個濱河市概作,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌默怨,老刑警劉巖讯榕,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異匙睹,居然都是意外死亡愚屁,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門痕檬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來霎槐,“玉大人,你說我怎么就攤上這事梦谜∏鸬” “怎么了袭景?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長闭树。 經(jīng)常有香客問我耸棒,道長,這世上最難降的妖魔是什么报辱? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任与殃,我火速辦了婚禮,結(jié)果婚禮上碍现,老公的妹妹穿的比我還像新娘幅疼。我一直安慰自己,他們只是感情好鸵赫,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布衣屏。 她就那樣靜靜地躺著,像睡著了一般辩棒。 火紅的嫁衣襯著肌膚如雪狼忱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天一睁,我揣著相機與錄音钻弄,去河邊找鬼。 笑死者吁,一個胖子當著我的面吹牛窘俺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播复凳,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瘤泪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了育八?” 一聲冷哼從身側(cè)響起对途,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎髓棋,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膳犹,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡须床,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年余赢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扛拨。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡耘分,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绑警,到底是詐尸還是另有隱情求泰,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布计盒,位于F島的核電站渴频,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏北启。R本人自食惡果不足惜卜朗,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望场钉。 院中可真熱鬧,春花似錦逛万、人聲如沸批钠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽指郁。三九已至,卻和暖如春踩窖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背箫柳。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工涮毫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留艘虎,地道東北人。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓绽昼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親停做。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 我們在項目開發(fā)中河咽,設計模式和理念決定了你做事的效率忘蟹,如果你想讓你的大腦存儲一些重要的設計模式,好在關鍵的時候拿來就...
    tery007閱讀 4,783評論 7 47
  • NSArray NSArray實例可以保存一組指向其他對象的指針搁凸。 17.1創(chuàng)建數(shù)組 NSArry實例一旦被創(chuàng)建后...
    帽子和五朵玫瑰閱讀 145評論 0 0
  • 夢涼青青媚值,燈火碎影。 簫歌遙遙护糖,不聞升平褥芒。 ...
    憶夕笑雪閱讀 157評論 0 0
  • 人生最重要的理財是打理自己的習慣,人生最重要的投資是投資自己的思想嫡良。 李笑來專欄不是教我們?nèi)绾钨嶅X锰扶,而是教我們?nèi)绾?..
    寓凡閱讀 578評論 0 0
  • 前言: 蝴蝶如要在百花園里得到飛舞的歡樂坷牛,那首先得忍受與蛹決裂的痛苦 ----------------------...
    z_j_r閱讀 290評論 0 0