角色
Context:环境角色:用于维护 State 实例,这个实例定义当前状态
State:抽象状态角色:聚合到Context环境角色中
ConcreteState :具体的状态角色 ConcreteStateA ConcreteStateB ConcreteStateC
UML类图
案例:抽奖活动项目设计
public class State {
// 当前的状态
private int state;
// 供抽奖的积分
private int score;
// 奖品的数量
private int count;
public State(int score, int count) {
this.score = score;
this.count = count;
}
public int getCount() {
return count;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
// 扣除积分
public void minus() {
// 只有一阶段可以扣积分
this.state = 1;
if (this.state == 1) {
if (this.score >= 50) {
if (this.count == 0) {
System.out.println("奖品领完....");
return;
}
this.score = this.score - 50;
System.out.println("========扣除50积分,当前积分还剩" + this.score + "========");
this.state = 2;
if (luckHit()) {
this.state = 3;
getPrize();
}
} else {
System.out.println("========积分不够,当前积分为" + this.score + "========");
}
}
}
// 十分之一抽中奖品的概率
public boolean luckHit() {
// 只有二阶段可以抽奖
return this.state == 2 ? (new Random().nextInt(10) == 6) : false;
}
public void getPrize() {
if (this.state == 3) {
if (this.count > 0) {
System.out.println("领取奖品....");
this.count = this.count - 1;
} else {
System.out.println("奖品领完....");
}
}
}
}
public class Client {
public static void main(String[] args) {
State state = new State(500,1);
// state.minus();
for (int i = 0; i < 300; i++) {
state.minus();
}
}
}
从上面的编码中,我们可以看出,完成该需求有很多的条件判断,非常不利于后续的维护;上面状态只有4个,代码已经比较复杂了;状态越多,代码嵌套就越复杂,维护成本就越高;
public abstract class State {
// 扣积分
abstract void minus();
// 抽奖
abstract boolean luckHit();
// 获取奖品
abstract void getPrize();
}
class ConcreteStateA extends State{
Context context;
public ConcreteStateA(Context context) {
this.context = context;
}
@Override
void minus() {
if(context.getScore()>=50){
context.setScore(context.getScore()-50);
System.out.println("========扣除50积分,当前积分还剩"+context.getScore()+"========");
context.setState(context.getStateB());
}else{
System.out.println("========积分不够,当前积分为"+context.getScore()+"========");
}
}
@Override
boolean luckHit() {
System.out.println("还在扣费环节,不能抽奖...");
return false;
}
@Override
void getPrize() {
System.out.println("还在扣费环节,不能领取奖品...");
}
}
class ConcreteStateB extends State{
Context context;
public ConcreteStateB(Context context) {
this.context = context;
}
@Override
void minus() {
System.out.println("已经在抽奖环节...");
}
@Override
boolean luckHit() {
boolean flag = new Random().nextInt(10) == 6;
if(flag){
context.setState(context.getStateC());
}else{
context.setState(context.getStateA());
}
return flag;
}
@Override
void getPrize() {
System.out.println("还在抽奖环节,不能领取奖品...");
}
}
class ConcreteStateC extends State{
Context context;
public ConcreteStateC(Context context) {
this.context = context;
}
@Override
void minus() {
System.out.println("已经在领取奖品环节...");
}
@Override
boolean luckHit() {
System.out.println("已经在领取奖品环节...");
return false;
}
@Override
void getPrize() {
if(context.getCount()>0){
System.out.println("领取奖品成功...");
context.setState(context.getStateA());
}else {
System.out.println("活动结束,领取奖品失败...");
context.setState(context.getStateD());
// 不继续抽奖
// System.exit(0);
}
}
}
class ConcreteStateD extends State{
Context context;
public ConcreteStateD(Context context) {
this.context = context;
}
@Override
void minus() {
System.out.println("已经在活动结束,奖品送完环节...");
}
@Override
boolean luckHit() {
System.out.println("已经在活动结束,奖品送完环节...");
return false;
}
@Override
void getPrize() {
System.out.println("已经在活动结束,奖品送完环节...");
}
}
public class Context {
// 当前的状态
private State state;
// 奖品数量
public int count;
// 用户积分
private int score;
// 表示同一个对象的四种状态
private ConcreteStateA stateA = new ConcreteStateA(this);
private ConcreteStateB stateB = new ConcreteStateB(this);
private ConcreteStateC stateC = new ConcreteStateC(this);
private ConcreteStateD stateD = new ConcreteStateD(this);
public Context(int score, int count) {
this.score = score;
this.count = count;
this.state = stateA;
}
// 扣积分
public void minus() {
state.minus();
}
// 抽奖
public void luckHit() {
if (state.luckHit()) {
state.getPrize();
}
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public int getCount() {
return count--;
}
public void setCount(int count) {
this.count = count;
}
public ConcreteStateA getStateA() {
return stateA;
}
public void setStateA(ConcreteStateA stateA) {
this.stateA = stateA;
}
public ConcreteStateB getStateB() {
return stateB;
}
public void setStateB(ConcreteStateB stateB) {
this.stateB = stateB;
}
public ConcreteStateC getStateC() {
return stateC;
}
public void setStateC(ConcreteStateC stateC) {
this.stateC = stateC;
}
public ConcreteStateD getStateD() {
return stateD;
}
public void setStateD(ConcreteStateD stateD) {
this.stateD = stateD;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
public class Client {
public static void main(String[] args) {
// 这次游戏积分500个,用完为止,总奖品数2
Context context = new Context(500,1);
// context.lunkHit();//还在扣费环节,不能抽奖...
for (int i = 0; i < 300; i++) {
context.minus();
context.luckHit();
}
System.out.println("------------------");
}
}
注意事项和细节
代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中
方便维护。将容易产生问题的 if-else 语句删除了
符合“开闭原则”。容易增删状态
缺点:会产生很多类。每个状态都要一个对应的类,当状态过多时会产生很多类,加大维护难度
应用场景:当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求有不同的行为的时候, 可以考虑使用状态模式
责任链模式(Chain of Responsibility)角色
Handler 抽象的处理者, 定义了一个处理请求的接口
ConcreteHandlerA , B 具体的处理者, 处理它自己负责的请求, 可以访问它的后继者(即下一个处理者)
Request 含义很多属性,表示一个请求
案例
需求:OA系统请假审批案例
学生请假1天:教员审批
学生请假2天:教学主管审批
学生请假3天:教学经理审批
学生请假5天:副校长审批
学生请假超过5天:校长审批
public class Request {
private String content;
private int day;
public Request(String content, int day) {
this.content = content;
this.day = day;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
}
public class Handler {
public void handle(Request request){
int day = request.getDay();
if(day <= 1){
System.out.println("教员处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
}else if(day <= 2){
System.out.println("教学主管处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
}else if(day <= 3){
System.out.println("教学经理处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
}else if(day <= 5){
System.out.println("副校长处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
}else {
System.out.println("校长处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
}
}
}
public class Client {
public static void main(String[] args) {
Handler handler = new Handler();
Request request1 = new Request("小感冒",1);
handler.handle(request1);
Request request2 = new Request("做检查",2);
handler.handle(request2);
Request request3 = new Request("打点滴",3);
handler.handle(request3);
Request request4 = new Request("住院",4);
handler.handle(request4);
Request request5 = new Request("在家调养",30);
handler.handle(request5);
}
}
运行结果为:
public class Request {
private String content;
private int day;
public Request(String content, int day) {
this.content = content;
this.day = day;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
}
public abstract class Handler {
Handler next;
String name;
public Handler(String name) {
this.name = name;
}
public Handler getNext() {
return next;
}
public void setNext(Handler next) {
this.next = next;
}
public abstract void handle(Request request);
}
class HandlerA extends Handler {
public HandlerA(String name) {
super(name);
}
public void handle(Request request) {
int day = request.getDay();
if (day <= 1) {
System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
} else {
next.handle(request);
}
}
}
class HandlerB extends Handler {
public HandlerB(String name) {
super(name);
}
public void handle(Request request) {
int day = request.getDay();
if (day <= 2) {
System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
} else {
next.handle(request);
}
}
}
class HandlerC extends Handler {
public HandlerC(String name) {
super(name);
}
public void handle(Request request) {
int day = request.getDay();
if (day <= 3) {
System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
} else {
next.handle(request);
}
}
}
class HandlerD extends Handler {
public HandlerD(String name) {
super(name);
}
public void handle(Request request) {
int day = request.getDay();
if (day <= 5) {
System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
} else {
next.handle(request);
}
}
}
class HandlerE extends Handler {
public HandlerE(String name) {
super(name);
}
public void handle(Request request) {
int day = request.getDay();
System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
}
}
public class Client {
public static void main(String[] args) {
HandlerA handlerA = new HandlerA("教员");
HandlerB handlerB = new HandlerB("教学主管");
HandlerC handlerC = new HandlerC("教学经理");
HandlerD handlerD = new HandlerD("副校长");
HandlerE handlerE = new HandlerE("校长");
handlerA.setNext(handlerB);
handlerB.setNext(handlerC);
handlerC.setNext(handlerD);
handlerD.setNext(handlerE);
Request request1 = new Request("小感冒",1);
handlerA.handle(request1);
Request request2 = new Request("做检查",2);
handlerA.handle(request2);
Request request3 = new Request("打点滴",3);
handlerA.handle(request3);
Request request4 = new Request("住院",4);
handlerA.handle(request4);
Request request5 = new Request("在家调养",30);
handlerA.handle(request5);
}
}
注意事项和细节
将请求和处理分开,实现解耦,提高系统的灵活性简化了对象,使对象不需要知道链的结构
注意:性能会受到影响,特别是在链比较长的时候,因此需控制链中最大节点数量,一般通过在 Handler 中设置一个最大节点数量,在 setNext()方法中判断是否已经超过阀值,超过则不允许该链建立,避免出现超长链无意识地破坏系统性能
应用
springmvc框架~HandlerExcutionChain类工作流框架绘图生成xml反射实例化,整个流程归档过程js中的原型链
观察者模式(Observer)-
角色
-
Observer观察者 百度 新浪 谷歌 Subject 气象局 WeatherData
UML类图
案例
需求:气象站数据更新推送问题
public class WeatherData {
double temperature;
double humidity;
public WeatherData(double temperature, double humidity) {
this.temperature = temperature;
this.humidity = humidity;
}
public void getWeatherInfo() {
System.out.println("当前温度:" + temperature + ",当前湿度:" + humidity);
}
public void change(double temperature, double humidity) {
this.temperature = temperature;
this.humidity = humidity;
}
}
public class Baidu {
private WeatherData weatherData;
public Baidu(WeatherData weatherData) {
this.weatherData = weatherData;
}
public void getWeatherInfo() {
System.out.print("百度网站温馨提示===>");
weatherData.getWeatherInfo();
}
}
class Sina {
private WeatherData weatherData;
public Sina(WeatherData weatherData) {
this.weatherData = weatherData;
}
public void getWeatherInfo() {
System.out.print("新浪网站温馨提示===>");
weatherData.getWeatherInfo();
}
}
public class Client {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData(30,20);
Baidu baidu = new Baidu(weatherData);
Sina sina = new Sina(weatherData);
baidu.getWeatherInfo();
sina.getWeatherInfo();
weatherData.change(10,10);
baidu.getWeatherInfo();
sina.getWeatherInfo();
}
}
运行结果为:
public interface Subject {
void addObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
class WeatherData implements Subject{
double temperature;
double humidity;
List Observers = new ArrayList<>();
public WeatherData(double temperature, double humidity) {
this.temperature = temperature;
this.humidity = humidity;
}
public void update(double temperature, double humidity) {
this.temperature = temperature;
this.humidity = humidity;
// 气象局数据一改变,马上通知接入的第三方/观察者
notifyObservers();
}
@Override
public void addObserver(Observer observer) {
Observers.add(observer);
observer.update(this.temperature,this.humidity);
}
@Override
public void removeObserver(Observer observer) {
Observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : Observers) {
observer.update(this.temperature,this.humidity);
}
}
}
public interface Observer {
void display();
void update(double temperature, double humidity);
}
class Baidu implements Observer{
double temperature;
double humidity;
@Override
public void display() {
System.out.println("百度温馨提示:当前温度:" + temperature + ",当前湿度:" + humidity);
}
@Override
public void update(double temperature, double humidity) {
this.temperature = temperature;
this.humidity = humidity;
this.display();
}
}
class Sina implements Observer{
double temperature;
double humidity;
@Override
public void display() {
System.out.println("新浪温馨提示:当前温度:" + temperature + ",当前湿度:" + humidity);
}
@Override
public void update(double temperature, double humidity) {
this.temperature = temperature;
this.humidity = humidity;
this.display();
}
}
public class Client {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData(30, 20);
Baidu baidu = new Baidu();
Sina sina = new Sina();
weatherData.addObserver(baidu);
weatherData.addObserver(sina);
weatherData.update(10, 10);
weatherData.removeObserver(baidu);
weatherData.update(12, 12);
}
}
由气象局主动通知第三方,天气数据发生了改变;并且,第三方的接入可以控制(增加、删除、通知);
- 注意事项和细节
集合的方式来管理用户(Observer),包括注册,移除和通知
策略模式(Strategy)
角色
Context 环境 Strategy 策略接口 ConcreteStrategyA ConcreteStrategyB Strategy2 策略接口 ConcreteStrategyC ConcreteStrategyD
案例
需求:学院共有专业需求
public class Major {
private String name;
public Major(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
Major major = (Major) obj;
return this.name.equals(major.name);
}
}
public class College {
String name;
public College(String name) {
this.name = name;
}
}
class CollegeA extends College{
List list = new ArrayList<>();
CollegeA(String name){
super(name);
this.list.add(new Major("JAVA"));
this.list.add(new Major("PHP"));
this.list.add(new Major("JavaScript"));
this.list.add(new Major("C语言"));
this.list.add(new Major("android"));
}
}
class CollegeB extends College{
List list = new ArrayList<>();
CollegeB(String name){
super(name);
this.list.add(new Major("iOS"));
this.list.add(new Major("PHP"));
this.list.add(new Major("JavaScript"));
this.list.add(new Major("C语言"));
this.list.add(new Major("嵌入式"));
}
}
public class StrategyA {
public List intersect(List a,List b){
List list = new ArrayList();
for (Major major : a) {
if(b.contains(major)){
list.add(major);
}
}
return list;
}
}
class StrategyB {
public List intersect(List a,List b){
// a.retainAll(b);
b.retainAll(a);
return b;
}
}
public class Client {
public static void main(String[] args) {
StrategyA strategyA = new StrategyA();
CollegeA a = new CollegeA("华东交通大学");
CollegeB b = new CollegeB("东华理工大学");
List intersect = strategyA.intersect(a.list, b.list);
System.out.println(a.name + "与" + b.name + "都有的专业");
for (Major major : intersect) {
System.out.println(major.getName());
}
StrategyB strategyB = new StrategyB();
List intersect2 = strategyB.intersect(a.list, b.list);
System.out.println(a.name + "与" + b.name + "都有的专业");
for (Major major : intersect2) {
System.out.println(major.getName());
}
}
}
运行结果为:
public class Major {
private String name;
public Major(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
Major major = (Major) obj;
return this.name.equals(major.name);
}
}
public class College {
String name;
public College(String name) {
this.name = name;
}
}
class CollegeA extends College {
List list = new ArrayList<>();
CollegeA(String name){
super(name);
this.list.add(new Major("JAVA"));
this.list.add(new Major("PHP"));
this.list.add(new Major("JavaScript"));
this.list.add(new Major("C语言"));
this.list.add(new Major("android"));
}
}
class CollegeB extends College {
List list = new ArrayList<>();
CollegeB(String name){
super(name);
this.list.add(new Major("iOS"));
this.list.add(new Major("PHP"));
this.list.add(new Major("JavaScript"));
this.list.add(new Major("C语言"));
this.list.add(new Major("嵌入式"));
}
}
public interface Strategy {
List intersect(List a, List b);
}
public class StrategyA implements Strategy{
public List intersect(List a,List b){
List list = new ArrayList();
for (Major major : a) {
if(b.contains(major)){
list.add(major);
}
}
return list;
}
}
public class Context {
public List intersect(List a, List b,Strategy strategy){
return strategy.intersect(a,b);
}
}
public class Client {
public static void main(String[] args) {
CollegeA a = new CollegeA("华东交通大学");
CollegeB b = new CollegeB("东华理工大学");
Context context = new Context();
List intersect = context.intersect(a.list, b.list, new StrategyA());
System.out.println(a.name + "与" + b.name + "都有的专业");
for (Major major : intersect) {
System.out.println(major.getName());
}
// 可以随意定制策略
List intersect2 = context.intersect(a.list, b.list, new Strategy() {
@Override
public List intersect(List a, List b) {
a.retainAll(b);
return a;
}
});
System.out.println(a.name + "与" + b.name + "都有的专业========");
for (Major major : intersect2) {
System.out.println(major.getName());
}
}
}
注意事项和细节
分析项目中变化部分与不变部分
体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为) 即可
策略模式将算法封装在独立的 Strategy 类中使得你可以独立于其 Context 改变它,使它易于切换、易于理解、易于扩展
注意:在很多场景中,策略接口会作为内部接口体现
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)