责任链模式
目的:以满足单一职责和开闭原则的方式实现需求的处理调用
优点:
1. 低耦合:请求 发送者 和 处理者 解耦,发送者 只需要将请求发送到责任链即可。
2. 扩展性强:满足开闭原则,根据请求,可以加入新的处理类。
3. 灵活性强:可以动态改变责任链的成员处理方式,或者在职责链的位置。
缺点:
1. 不能保证请求一定被处理,最好在末端还不能处理时进行提示
2. 职责链过程会影响系统性能
3. 增加了客户端的复杂性
代码模拟:
1. 定义一个处理成员的超类
public abstract class Approver {
Approver approver;//下一个处理者
String name;
public Approver(String name) {
this.name = name;
}
public void setApprover(Approver approver) {
this.approver = approver;
}
//处理请求的方法
public abstract void processRequest(PurchaseRequest purchaseRequest);
}
2.定义三个处理者对象继承超类
public class DepartmentApprover extends Approver{
public DepartmentApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if(purchaseRequest.getPrice() <= 5000){
System.out.println("请求编号id = " + purchaseRequest.getId() + " " + this.name);
}else{
approver.processRequest(purchaseRequest);
}
}
public class CollegeApprover extends Approver {
public CollegeApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getPrice() > 5000 && purchaseRequest.getPrice() <= 10000) {
System.out.println("请求编号id = " + purchaseRequest.getId() + " " + this.name);
} else {
approver.processRequest(purchaseRequest);
}
}
}
public class SchoolMasterApprover extends Approver{
public SchoolMasterApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if(purchaseRequest.getPrice() > 10000){
System.out.println("请求编号id = " + purchaseRequest.getId() + " " + this.name);
}else{
approver.processRequest(purchaseRequest);
}
}
}
3. 定义请求类,模拟一种请求
public class PurchaseRequest {
private int type = 0;
private float price = 0.0f;
private int id = 0;
public PurchaseRequest(int type, float price, int id) {
this.type = type;
this.price = price;
this.id = id;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
4.客户端构建职责链,确保请求一定能被处理,并将三个处理者类形成闭环,这样随便调用一个处理者都可以实现请求的处理
public class Client {
public static void main(String[] args) {
PurchaseRequest purchaseRequest = new PurchaseRequest(1, 6000, 1);
DepartmentApprover rosmontiss = new DepartmentApprover("Rosmontiss");
CollegeApprover goldenGlow = new CollegeApprover("GoldenGlow");
SchoolMasterApprover amiya = new SchoolMasterApprover("Amiya");
rosmontiss.setApprover(goldenGlow);
goldenGlow.setApprover(amiya);
amiya.setApprover(rosmontiss);
amiya.processRequest(purchaseRequest);
}
}
命令模式
目的:将拥有一类职责的对象封装成类,命令对象的唯一职责就是通过execute ()去调用方法,方法调用的·封装,使得我们能更好地对调用进行排队、撤销、处理
优点:
1. 请求者 和 实现者 解耦
2. 拓展性强,增删命令方便
3. 灵活性强,可以实现宏命令
缺点:
1. 系统复杂性高
代码模拟:
组成:
Invoker: 调用者角色
Command: 命令角色,所有命令均在此申明,可以是接口或者抽象类
Receiver: 接收者,处理如何执行一个请求相关操作
ConcreteCommand: 接收一个Receiver和一个动作,调用Receiver对应操作,实现execute
编写命令接口,子类应实现该命令
public interface Cammand { public void execute(); public void undo(); }
编写子类具体命令的实现,在命令中聚合子类对象
public class LightOnCommand implements Cammand{ LightRecevier light; public LightOnCommand(LightRecevier light) { this.light = light; } @Override public void execute() { light.on(); } @Override public void undo() { light.off(); } }
public class LightOffCommand implements Cammand{ LightRecevier light; public LightOffCommand(LightRecevier light) { this.light = light; } @Override public void execute() { light.off(); } @Override public void undo() { light.on(); } }
子类将作为Receiver: 接收者,处理如何执行一个请求相关操作
public class LightRecevier { public void on(){ System.out.println("电灯打开了..."); } public void off(){ System.out.println("电灯关闭了..."); } }
编写一个空命令的实现,这样初始化不许判断命令是否为空✅✅
//空执行用于初始化每个按钮,当调用空命令时,对象什么都不做,这种设计模式可以省去对空命令的判断 public class NoCommand implements Cammand{ @Override public void execute() { } @Override public void undo() { } }
编写控制类,聚合各种命令,也是客户端要操作的核心类
public class RemoteController { Cammand[] onCommands; Cammand[] offCommands; //执行撤销的命令 Cammand undoCommand; public RemoteController(){ onCommands = new Cammand[5]; offCommands = new Cammand[5]; for (int i = 0; i < 5; i++) { onCommands[i] = new NoCommand(); offCommands[i] = new NoCommand(); } } public void setCommand(int num,Cammand onCommand,Cammand offCommand){ onCommands[num] = onCommand; offCommands[num] = offCommand; } public void onButtonWasPushed(int num){ onCommands[num].execute(); undoCommand = onCommands[num]; } public void offButtonWasPushed(int num){ offCommands[num].execute(); undoCommand = onCommands[num]; } public void undoButtonWasPushed(){ undoCommand.undo(); } }
测试
public class Client { public static void main(String[] args) { RemoteController remoteController = new RemoteController(); LightRecevier light = new LightRecevier(); remoteController.setCommand(0,new LightOnCommand(light),new LightOffCommand(light)); remoteController.onButtonWasPushed(0); remoteController.undoButtonWasPushed(); } }
解释器模式
在解释器模式中,我们将不可拆分的最小单元称之为终结表达式,可以被拆分的表达式称之为非终结表达式。
该模式地完整过程十分复杂,实际开发中也几乎无需自定义解释器的情况,我们常见的正则表达式就是解释器模式的一种实现,这里不做过多赘述。
迭代器模式
目的:提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。(引用自设计模式一书)
优点:
1. 不要暴露内部细节,即可访问各个元素,可以有效防止外部对数据进行篡改
缺点:
1. 需要实现Iterator接口方法,并编写对应逻辑
代码模拟:
1. 创建学院超类,专业系。
public interface College {
public String getName();
public void addDepartment(String name,String des);
public Iterator createIterator();
}
public class Department {
private String name;
private String des;
public Department(String name, String des) {
this.name = name;
this.des = des;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
@Override
public String toString() {
return "Department{" +
"name='" + name + '\'' +
", des='" + des + '\'' +
'}';
}
}
2.创建具体学院实现类,并提供数组,聚合各个专业系,这里为了方便测试。直接在构造器进行的专业初始化。
public class ComputerCollege implements College{
Department[] departments;
int numOfDepartment = 5 ;//保存当前数组对象个数
public ComputerCollege() {
this.departments = new Department[5];
addDepartment("java1","java1");
addDepartment("java2","java2");
addDepartment("java3","java3");
addDepartment("java4","java4");
addDepartment("java5","java5");
}
@Override
public String getName() {
return "计算机学院";
}
@Override
public void addDepartment(String name, String des) {
Department department = new Department(name, des);
departments[numOfDepartment] = department;
numOfDepartment += 1;
}
@Override
public Iterator createIterator() {
return new ComputerCollegeIterator(departments);
}
}
3.创建该学院对应的构造器,实现Iterator接口,聚合需要遍历的属性,并每次对开始遍历的序号置零,即position=0。
public class ComputerCollegeIterator implements Iterator {
Department[] departments;
int position = 0;//遍历的位置
public ComputerCollegeIterator(Department[] departments) {
this.departments = departments;
}
//判断是否还有下一个元素
@Override
public boolean hasNext() {
if(position >= departments.length || departments[position] == null){
return false;
}
return true;
}
@Override
public Object next() {
Department department = departments[position];
position += 1;
return department;
}
@Override
public void remove() {
}
}
4.测试,创建实例,获取迭代器,通过迭代器进行遍历即可。
public class Client {
public static void main(String[] args) {
ComputerCollege computerCollege = new ComputerCollege();
Iterator iterator = computerCollege.createIterator();
while (iterator.hasNext()){
String s = iterator.next().toString();
System.out.println(s);
}
}
}
中介者模式
目的:将对象之间的操作交给中介对象进行代理执行,简单来说,就是将多对多的关系,简化为多对一,一对多的关系。设计模式种时这样描述的:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。
优点:
1. 无需关心多个对象的交互,只需要交给中介类进行处理即可
缺点:
1.随着关系增多,中介类由于是对所有类进行协调处理,可能会导致其变成超级类
代码模拟
1.建造抽象中介类,并编写实体类具体实现
public abstract class Mediator {
public abstract void Register(Emp emp);
public abstract void GetMessage(String empName,int doNum);
}
public class ConcreteMediator extends Mediator{
Map<String,Emp> emps = new HashMap<>();
public ConcreteMediator(Map<String, Emp> emps) {
this.emps = emps;
}
public ConcreteMediator() {
}
@Override
public void Register(Emp emp) {
emps.put(emp.getName(),emp);
}
@Override
public void GetMessage(String name, int doNum) {
Emp emp = emps.get(name);
switch (doNum){
case 1:
emp.Work1();
break;
case 2:
emp.Work2();
break;
default:
System.out.println("Do nothing...");
}
}
}
2.创建需要经由中介代理的抽象类,并实现两个具体的实现类
public abstract class Emp {
private int id;
private String name;
public Emp(int id, String name) {
this.id = id;
this.name = name;
}
public abstract void Work1();
public abstract void Work2();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class GoldenGlow extends Emp{
public GoldenGlow() {
super(2, "GoldenGlow");
}
@Override
public void Work1() {
System.out.println(this.getName() + "在制造间");
}
@Override
public void Work2() {
System.out.println(this.getName() + "在休息室");
}
}
public class Rosmontiss extends Emp{
public Rosmontiss() {
super(1,"Rosmontiss");
}
@Override
public void Work1() {
System.out.println(this.getName() + "在制造间");
}
@Override
public void Work2() {
System.out.println(this.getName() + "在休息室");
}
}
3.客户端向中介发送信息,中介即可对对应类下达指令
public class Client {
public static void main(String[] args) {
Rosmontiss rosmontiss = new Rosmontiss();
GoldenGlow goldenGlow = new GoldenGlow();
Mediator mediator = new ConcreteMediator();
mediator.Register(goldenGlow);
mediator.Register(rosmontiss);
mediator.GetMessage("Rosmontiss",1);
mediator.GetMessage("GoldenGlow",2);
}
}
备忘录模式
目的:备份某一状态,便于之后的恢复
优点:
1. 提供了一种状态恢复机制
2. 实现了信息封装,用户无需关系保存细节,只需调用方法
缺点:
1. 消耗资源,成员变量过多会消耗相当一部分内存
代码模拟:
1. 创建目标对象,有攻击力和防御力两个属性
public class GameRole {
private int vit;
private int def;
public GameRole(int vit, int def) {
this.vit = vit;
this.def = def;
}
public Memento createMemento() {
return new Memento(vit, def);
}
public void recoverGameRoleFromMemento(Memento memento) {
this.vit = memento.getVit();
this.def = memento.getDef();
}
public void dsiplay() {
System.out.println(vit + " " + def);
}
public int getVit() {
return vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getDef() {
return def;
}
public void setDef(int def) {
this.def = def;
}
}
2.创建备份对象,该对象会记录目标对象某一时刻的属性
public class Memento {
private int vit;
private int def;
public Memento(int vit, int def) {
this.vit = vit;
this.def = def;
}
public int getVit() {
return vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getDef() {
return def;
}
public void setDef(int def) {
this.def = def;
}
}
3.创建守护者对象,守护者对象用于保存备份对象,方便恢复状态,这里只模拟保存一次的状态,如果需要多次保存,则应该使用链表,Map数组等结构。
//守护者对象
public class Caretaker {
//只需要保存一次则无需使用数组,若需要对多个保存,则使用hashmap即可
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
4.用户备份数据和恢复
public class Client {
public static void main(String[] args) {
//创建对象
GameRole gameRole = new GameRole(100, 50);
//创建守护者对象
Caretaker caretaker = new Caretaker();
//将备份对象放入守护对象中
caretaker.setMemento(gameRole.createMemento());
//改变对象数值
gameRole.setVit(30);
gameRole.setDef(20);
//恢复对象数值
gameRole.recoverGameRoleFromMemento(caretaker.getMemento());
gameRole.dsiplay();
}
}
观察者模式(应用较为广泛)
目的:处理一对多的依赖关系,一个对象发送某个事件之后,逐一通知每个观察者
代码模拟:
1. 编写需要观测的数据类,该类为核心类,会用ArrayList聚合观察者对象,并提供注册观察者,删除观察者,提醒方法(当然根据业务需求可以编写更多)
首先是抽象类,指定所有观测数据类都需要实现的基本方法
public interface Subject {
public void registerObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObserver();
}
其次是实体类,也是核心类
public class WeatherData implements Subject{
private float temperature;
private float pressure;
private float humidity;
private ArrayList<Observer> observers;
public WeatherData(){
observers = new ArrayList<Observer>();
}
public void updateData(float temperature, float pressure, float humidity){
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
this.notifyObserver();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
if(observers.contains(observer)){
observers.remove(observer);
}
}
@Override
public void notifyObserver() {
for (int i = 0; i < observers.size(); i++) {
observers.get(i).update(this.temperature,this.pressure,this.humidity);
}
}
}
2.编写观察者对象接口,以及实体类,观察者类编写跟新方法方便气候数据类在通知时同时进行数据同步。
public interface Observer {
public void update(float temperature,float pressure,float humidity);
}
//观察者
public class CurrentConditionsOne implements Observer{
private float temperature;
private float pressure;
private float humidity;
public void update(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
public void display(){
System.out.println("1温度*********" + temperature + "*********");
System.out.println("1气压*********" + pressure + "*********");
System.out.println("1湿度*********" + humidity + "*********");
}
}
public class CurrentConditionsTwo implements Observer{
private float temperature;
private float pressure;
private float humidity;
public void update(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
public void display(){
System.out.println("2温度*********" + temperature + "*********");
System.out.println("2气压*********" + pressure + "*********");
System.out.println("2湿度*********" + humidity + "*********");
}
}
3.客户端调用
public class Client {
public static void main(String[] args) {
//创建气象数据对象
WeatherData weatherData = new WeatherData();
//模拟两个观察者
CurrentConditionsOne currentConditionsOne = new CurrentConditionsOne();
CurrentConditionsTwo currentConditionsTwo = new CurrentConditionsTwo();
//将观察者注册到该天气对象中
weatherData.registerObserver(currentConditionsOne);
weatherData.registerObserver(currentConditionsTwo);
//更新数据并提醒所有观察者,提醒方法在跟新方法内部被调用
weatherData.updateData(1,2,3);
}
}
状态模式(是一种有关多态的设计模式)
目的:减少if-else语句的使用,而是通过不同的状态类进行转换调用。
代码模拟:抽奖系统
四个状态: 可抽奖 不可抽奖 发送奖品 奖品以及发送完毕
1. 定义状态超类,并指定每种状态都需要实现的方法
public abstract class State {
//扣除积分
public abstract void deductMoney();
//是否中奖
public abstract boolean raffle();
//发放奖品
public abstract void dispensePrize();
}
2.不能抽奖状态,最总要的是扣分方法,并在该方法实现状态转换,扣除后即为可抽奖状态,扣除前检测奖品剩余数量,不够则立刻将状态设置为奖品已无
public class NoRaffleState extends State {
RaffleActivity activity;
public NoRaffleState(RaffleActivity activity) {
this.activity = activity;
}
@Override
public void deductMoney() {
if(activity.getCount() == 0){
activity.setState(activity.getDispenseOutState());
}
System.out.println("扣分50成功");
activity.setState(activity.getCanRaffleState());
}
@Override
public boolean raffle() {
System.out.println("需要扣分才能抽奖");
return false;
}
@Override
public void dispensePrize() {
System.out.println("当前状态不能发放奖品");
}
}
3.可抽奖状态,通过random进行模拟抽奖,抽中则通过聚合的抽奖活动主类进行状态转换为发放奖品状态返回true,否则返回false。
public class CanRaffleState extends State{
RaffleActivity activity;
public CanRaffleState(RaffleActivity activity) {
this.activity = activity;
}
@Override
public void deductMoney() {
System.out.println("已经扣除积分");
}
@Override
public boolean raffle() {
System.out.println("抽奖中...");
Random random = new Random();
int num = random.nextInt(2);
if(num == 0){
activity.setState(activity.getDispenseState());
return true;
}else {
System.out.println("很遗憾,未抽中奖品...");
activity.setState(activity.getNoRaffleState());
return false;
}
}
@Override
public void dispensePrize() {
System.out.println("未中奖,不能发放奖品");
}
}
4.发放奖品状态
public class DispenseState extends State{
RaffleActivity activity;
public DispenseState(RaffleActivity activity) {
this.activity = activity;
}
@Override
public void deductMoney() {
System.out.println("不能扣除积分");
}
@Override
public boolean raffle() {
System.out.println("不能抽奖");
return false;
}
@Override
public void dispensePrize() {
if(activity.getCount() > 0){
System.out.println("恭喜中奖!");
activity.setCount(activity.getCount() - 1);
activity.setState(activity.getNoRaffleState());
}else {
System.out.println("很遗憾,奖品发放完毕");
activity.setState(activity.getDispenseOutState());
}
}
}
4.奖品无库存状态
public class DispenseOutState extends State{
RaffleActivity activity;
public DispenseOutState(RaffleActivity activity) {
this.activity = activity;
}
@Override
public void deductMoney() {
System.out.println("奖品已无,下次参加");
}
@Override
public boolean raffle() {
System.out.println("奖品已无,下次参加");
return false;
}
@Override
public void dispensePrize() {
System.out.println("奖品已无,下次参加");
}
}
5.抽奖系统主题类,构造器用于初始化奖品数量,并设置初始状态为不能抽奖状态
public class RaffleActivity {
//状态情况
State state = null;
//奖品数量
int count = 0;
State noRaffleState = new NoRaffleState(this);
State canRaffleState = new CanRaffleState(this);
State dispenseState = new DispenseState(this);
State dispenseOutState = new DispenseOutState(this);
public RaffleActivity(int count) {
this.state = noRaffleState;//初始就是不能抽奖状态
this.count = count;
}
//扣分
public void debuctMoney(){
state.deductMoney();
}
//抽奖
public void raffle(){
if(state.raffle()){
state.dispensePrize();
}
}
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 State getNoRaffleState() {
return noRaffleState;
}
public void setNoRaffleState(State noRaffleState) {
this.noRaffleState = noRaffleState;
}
public State getCanRaffleState() {
return canRaffleState;
}
public void setCanRaffleState(State canRaffleState) {
this.canRaffleState = canRaffleState;
}
public State getDispenseState() {
return dispenseState;
}
public void setDispenseState(State dispenseState) {
this.dispenseState = dispenseState;
}
public State getDispenseOutState() {
return dispenseOutState;
}
public void setDispenseOutState(State dispenseOutState) {
this.dispenseOutState = dispenseOutState;
}
}
6.客户端进行调用
public class Cilent {
public static void main(String[] args) {
RaffleActivity raffleActivity = new RaffleActivity(2);
for (int i = 0; i < 5; i++) {
System.out.println("******"+ i + "********");
raffleActivity.debuctMoney();
raffleActivity.raffle();
}
}
}
模板方法模式
目的:继承一个父类作为模板,某些具体的实现延迟到子类进行
什么是钩子方法?
父类可以定义一个方法,进行默认实现(不进行任何操作,或者返回一个布尔值,控制某个方法不进行实现),子类可以视情况看要不要覆盖它。
1. 创建豆浆制作超类,确定基本模板流程,部分细节创建构造方法延迟给子类使用
public abstract class SolkMaker {
public void MakeAction(){
work1();
if(hookMethod()){
work2();
}
work3();
}
public void work1(){
System.out.println("磨豆子");
}
public abstract void work2();
public boolean hookMethod(){
return true;
}
public void work3(){
System.out.println("制作豆浆");
}
}
2.创建不同豆浆种类继承豆浆超类
public class CommonSolk extends SolkMaker {
@Override
public void work2() {
}
@Override
public boolean hookMethod() {
return false;
}
}
public class BlackSolk extends SolkMaker{
@Override
public void work2() {
System.out.println("加入了黑豆");
}
}
3.客户端使用
public class Client{
public static void main(String[] args) {
SolkMaker commonSolk = new CommonSolk();
commonSolk.MakeAction();
SolkMaker blackSolk = new BlackSolk();
blackSolk.MakeAction();
}
}
策略模式
目的:将多种相同功能代码进行封装,并提供选择策略给用户,让用户能够根据实际情况自由选择使用哪种模式。
策略模式和状态模式:
1. 策略模式只需要程序选择某种策略完成某件事,强调的是殊途同归
2. 状态模式需要程序在不同状态进行反复切换才能完成某件事,每个状态只能完成整个程序的一部分,需要结合在一起才能完成整件事,强调随势而动。
代码模拟:借助leetcode中策略模式的实现,十分清晰
1.编写枚举类指定不同策略,这样用户可以自由选择
enum SortStrategy {
BUBBLE_SORT,
SELECTION_SORT,
INSERT_SORT
}
2.编写各种实现排序的方法,这里不赘述了,每种方法应该对应枚举类中的内容
3.编写排序接口,使用简单工厂模式编写具体实现类,通过构造器让用户确定使用什么方法进行排序,再调用排序方法进行返回即可实现目标。
interface ISort {
void sort(int[] arr);
}
class Sort implements ISort {
private ISort sort;
Sort(SortStrategy strategy) {
setStrategy(strategy);
}
@Override
public void sort(int[] arr) {
sort.sort(arr);
}
// 客户端通过此方法设置不同的策略
public void setStrategy(SortStrategy strategy) {
switch (strategy) {
case BUBBLE_SORT:
sort = new BubbleSort();
break;
case SELECTION_SORT:
sort = new SelectionSort();
break;
case INSERT_SORT:
sort = new InsertSort();
break;
default:
throw new IllegalArgumentException("There's no such strategy yet.");
}
}
}
4.测试
public class Client {
@Test
public void test() {
int[] arr = new int[]{6, 1, 2, 3, 5, 4};
Sort sort = new Sort(SortStrategy.BUBBLE_SORT);
// 可以通过选择不同的策略完成排序
// sort.setStrategy(SortStrategy.SELECTION_SORT);
// sort.setStrategy(SortStrategy.INSERT_SORT);
sort.sort(arr);
// 输出 [1, 2, 3, 4, 5, 6]
System.out.println(Arrays.toString(arr));
}
}
链接:https://leetcode.cn/leetbook/read/design-patterns/9e2v65/
来源:力扣(LeetCode)
访问者模式
目的:将数据结构和数据操作进行分离
什么是双分派:
在选择一个方法的时候,不仅仅要根据消息接收者(receiver) 的运行时型别(Run time type),还要根据参数的运行时型别(Run time type)
代码模拟
1.编写行为超类
public abstract class Action {
public abstract void getManResult(Man man);
public abstract void getWomanResult(Woman woman);
}
2.编写成功和失败两种行为评论
public class Faild extends Action{
@Override
public void getManResult(Man man) {
System.out.println("男人评价失败");
}
@Override
public void getWomanResult(Woman woman) {
System.out.println("女人评价失败");
}
}
public class Success extends Action{
@Override
public void getManResult(Man man) {
System.out.println("男人评价成功");
}
@Override
public void getWomanResult(Woman woman) {
System.out.println("女人评价成功");
}
}
3.编写评价人超类
public abstract class Person {
public abstract void accept(Action action);
}
4.编写不同类型的群体,并接收行为类
public class Man extends Person{
@Override
public void accept(Action action) {
action.getManResult(this);
}
}
//双分派
public class Woman extends Person{
@Override
public void accept(Action action) {
action.getWomanResult(this);
}
}
5.编写数据结构,来操作不同群体的评价内容
//数据结构,管理了很多人
public class ObjectStructure {
private List<Person> persons = new LinkedList<>();
public void attach(Person person){
persons.add(person);
}
public void detach(Person person){
persons.remove(person);
}
public void display(Action action){
for (Person person:persons){
person.accept(action);
}
}
}
6.客户端调用
public class Client {
public static void main(String[] args) {
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.attach(new Man());
objectStructure.attach(new Woman());
Success success = new Success();
objectStructure.display(success);
}
}