一,空对象模式(Null Object Pattern)
在空对象模式(Null Object Pattern)中,用一个空对象代替null, 可以减少空指针出现的机会, 空对象也可以执行一些默认的操作.
案例:
定义一个抽象类, 有判断是否为空的方法
public abstract class Human {
private String name;
abstract boolean isNull();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2个实现类, 一个是真实存在的类, 一个是空对象类
public class User extends Human {
public User(String name) {
setName(name);
}
@Override
boolean isNull() {
return false;
}
}
public class NullObj extends Human {
public NullObj() {
setName("这是一个空对象");
}
@Override
boolean isNull() {
return true;
}
}
定义工厂类
public class UserFactory {
public static Human queryUser(int id) {
Human human = null;
switch (id) {
case 1:
human = new User("张三");
break;
case 2:
human = new User("李四");
break;
default:
human = new NullObj();
break;
}
return human;
}
}
Demo, 如果其他用户忘记做空值判断, 也不会报空指针.
public static void main(String[] args) {
Human human = UserFactory.queryUser(3);
System.out.println(human.getName());
}
二,策略模式(Strategy Pattern)
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
策略模式和状态模式的区别是, 策略模式是在多个策略中, 选择执行一个, 并不涉及到策略之间的跳转, 所以每个策略不用维护修改context本身. 状态模式涉及到多个状态之间的跳转, 需要修改context的状态变量.
例如, 订单的支付, 可以是微信支付, 也可以是支付宝支付
定义一个支付的接口
public interface Pay {
void doPay(double money);
}
2种支付方式
public class AliPay implements Pay {
@Override
public void doPay(double money) {
System.out.println("支付宝支付:" + money + "元");
}
}
public class WechatPay implements Pay {
@Override
public void doPay(double money) {
System.out.println("微信支付:" + money + "元");
}
}
订单
public class Order {
private Pay pay;
private double money;
public void finishPay(){
pay.doPay(money);
}
... Getter/Setter方法 ...
}
Demo
public static void main(String[] args) {
Order order = new Order();
order.setMoney(105.5);
// 选择支付宝付款
order.setPay(new AliPay());
// 支付订单
order.finishPay();
}
三,模板模式(Template Pattern)
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。即执行的流程都是相同的, 各不同子类可以根据需要个性化过程的参数.
例如: 简单的一个比赛流程, 分为入场-开始-结束,
抽象类
public abstract class Game {
abstract void admission();
abstract void begin();
abstract void end();
// 模板, 按照特定的顺序进行比赛
public void start(){
admission(); // 入场
begin(); // 开始
end(); // 结束
}
}
实现类
public class FootballGame extends Game {
@Override
void admission() {
System.out.println("足球明星,甲乙丙丁 -- 入场");
}
@Override
void begin() {
System.out.println("足球比赛,谁与争锋 -- 开始");
}
@Override
void end() {
System.out.println("各回各家,各找各妈 -- 结束");
}
}
Demo
public static void main(String[] args) {
FootballGame game = new FootballGame();
game.start();
}
足球明星,甲乙丙丁 -- 入场
足球比赛,谁与争锋 -- 开始
各回各家,各找各妈 -- 结束
四,访问者模式(Visitor Pattern)
访问者模式主要分为访问者和被访问者, 同一访问者,访问不同被访问者, 会有不同的操作, 同样, 不同访问者关心的是被访问者不同的属性/行为.
案例: 公司需要考核的对象(被访问者)为程序员和销售, 考核者(访问者)为hr和boss, hr需要考核程序员的加班和销售的迟到, boss需要考核程序员的代码完成量和销售的销售业绩.
员工接口, 提供被考核的功能接口
public interface Employee {
void accept(Check check);
String getName();
}
程序员类, 有代码量和加班时间变量
public class Programmer implements Employee {
private int codeLines;
private int overTimeHours;
private String name;
public Programmer(int codeLines, int overTimeHours, String name) {
this.codeLines = codeLines;
this.overTimeHours = overTimeHours;
this.name = name;
}
@Override
public void accept(Check check) {
check.checkEmp(this);
}
@Override
public String getName() {
return name;
}
public int getCodeLines() {
return codeLines;
}
public int getOverTimeHours() {
return overTimeHours;
}
}
销售类, 有销售额和迟到次数变量
public class Sale implements Employee {
private int salesVolume;
private int laterTimes;
private String name;
public Sale(int salesVolume, int laterTimes, String name) {
this.salesVolume = salesVolume;
this.laterTimes = laterTimes;
this.name = name;
}
@Override
public void accept(Check check) {
check.checkEmp(this);
}
@Override
public String getName() {
return name;
}
public int getSalesVolume() {
return salesVolume;
}
public int getLaterTimes() {
return laterTimes;
}
}
考核接口, 提供考核的入口, 对不同的被考核对象, 提供不同的入口
public interface Check {
void checkEmp(Programmer employee);
void checkEmp(Sale employee);
}
hr和boss
public class HrCheck implements Check {
@Override
public void checkEmp(Programmer employee) {
System.out.println("Hr检查员工:" + employee.getName() + "的考勤结果:加班" + employee.getOverTimeHours() + "小时");
}
@Override
public void checkEmp(Sale employee) {
System.out.println("Hr检查员工:" + employee.getName() + "的考勤结果:迟到" + employee.getLaterTimes() + "次");
}
}
public class Boss implements Check {
@Override
public void checkEmp(Programmer employee) {
System.out.println("老板检查员工" + employee.getName() + "的业绩: 代码完成" + employee.getCodeLines() + "行.");
}
@Override
public void checkEmp(Sale employee) {
System.out.println("老板检查员工" + employee.getName() + "的业绩: 完成销售额" + employee.getSalesVolume() + "元.");
}
}
工具类
public class CheckUtil {
private List<Employee> employees = new ArrayList<>();
public void addEmp(Employee employee){
employees.add(employee);
}
public void checkEmp(Check check){
for (Employee employee : employees) {
employee.accept(check);
}
}
}
Demo
public static void main(String[] args) {
CheckUtil checkUtil = new CheckUtil();
checkUtil.addEmp(new Programmer(500, 20, "程序员张三"));
checkUtil.addEmp(new Programmer(555, 30, "程序员李四"));
checkUtil.addEmp(new Sale(555, 30, "销售员王五"));
checkUtil.addEmp(new Sale(1, 29, "销售员赵六"));
System.out.println("------HR考核------");
HrCheck hrCheck = new HrCheck();
checkUtil.checkEmp(hrCheck);
System.out.println("------BOSS考核------");
Boss boss = new Boss();
checkUtil.checkEmp(boss);
}
结果:
------HR考核------
Hr检查员工:程序员张三的考勤结果:加班20小时
Hr检查员工:程序员李四的考勤结果:加班30小时
Hr检查员工:销售员王五的考勤结果:迟到30次
Hr检查员工:销售员赵六的考勤结果:迟到29次
------BOSS考核------
老板检查员工程序员张三的业绩: 代码完成500行.
老板检查员工程序员李四的业绩: 代码完成555行.
老板检查员工销售员王五的业绩: 完成销售额555元.
老板检查员工销售员赵六的业绩: 完成销售额1元.