一:概念说明
面向对象
面向对象是一种软件开发的方法论和编程范式,它将现实世界中的事物抽象为对象,并通过对象之间的交互来实现系统的设计和开发。
面向对象的核心思想是将系统看作是一组相互作用的对象的集合。每个对象都有自己的属性(数据)和行为(方法),并且能够与其他对象进行交互。对象之间通过消息传递来进行通信和协作,每个对象根据接收到的消息来执行相应的操作。
二:背景介绍
米老师需要开办公室的门,需要进入办公室进行工作。这时候需要何老师来进行开门的操作。
三:思路&方案
1.面向过程
何老师管理钥匙,米老师需要开门,何老师把钥匙方法一个位置上。米老师到壹佰之后去拿钥匙 自己去执行开门的操作。
2.面向对象(依赖)
米老师到达公司之后,米老师喊一下何老师打开办公室的门,何老师听到消息之后就过来开门了。
3.C#事件与委托
C#事件与委托是借助于大话设计模式中的猫和老鼠的例子来实现的,这个例子达到的效果是猫一叫老鼠就跑,但是事先猫和老鼠并不认识这时候就需要有一个委托人来使猫和老鼠有这种依赖关系。
4.面向对象(反射)
米老师到达公司之后,米老师喊了一下给我开一下办公室的门,听到米老师消息的任意一个老师都可以过来开门。
5.面向对象(Java事件与委托)
借助于C#版本的时间与委托,来实现米老师需要一个老师来开门,最终是哪个老师来开门是程序运行的时候才确定的。减少了米老师和其他老师之间的耦合。
四:实现过程
1.面向过程:原本何老师的作用交给我了米老师来完成。
代码实现
public class Client { public static void main(String[] args) { System.out.println("米老师:我需要开门"); System.out.println("何老师:米老师,钥匙放在前台了,您开一下吧"); System.out.println("米老师:去前台拿钥匙自己去开门了"); } }
效果展示
2.面向对象:把开门的方法完全交个何老师,米老师不需要有开门的操作
代码实现
客户端
public class Client { public static void main(String[] args) { Notice notice=new Notice(); notice.notice(); } }
业务封装类
public class Notice { private void TeahcerMiDependTeacherHeBusiness(){ ReceiveMsg receiveMsgTeacherHe=new ReceiveMsg(); receiveMsgTeacherHe.receiveMsg(new SendMsg()); } public void notice(){ this.TeahcerMiDependTeacherHeBusiness(); } }
发消息类
public class SendMsg { public void sendMsg(){ System.out.println("米老师:我需要开一下门"); } }
收消息类
public class ReceiveMsg { private void open(){ System.out.println("何老师:开门中。。。。。。门已打开"); } public void receiveMsg(SendMsg sendMsgTeacherMi){ sendMsgTeacherMi.sendMsg(); this.open(); } }
效果展示
3.C#事件与委托:猫叫老鼠跑,猫和老鼠互不认识
代码实现
客户端
static void Main(string[] args) { //实例化对象 Cat cat = new Cat("Tom"); Mouse mouse1 = new Mouse("Jerry"); Mouse mouse2 = new Mouse("Jake"); //事件和方案进行绑定,执行事件时调用绑定的方法 cat.CatShout += new Cat.CatShoutEventHandler(mouse1.Run); cat.CatShout += new Cat.CatShoutEventHandler(mouse2.Run); cat.Shout(); Console.Read(); }
猫类
namespace 委托与事件 { internal class Cat { private string name; public Cat(string name) { this.name = name; } //声明委托 public delegate void CatShoutEventHandler(); //声明事件,事件的类型为委托类型。 public event CatShoutEventHandler CatShout; public void Shout() { Console.WriteLine("喵,我是{0}",name); //判断是否拥有CatShout事件 if (CatShout != null) { CatShout(); } } } }
老鼠类
namespace 委托与事件 { internal class Mouse { private string name; public Mouse(string name) { this.name = name; } public void Run() { Console.WriteLine("老猫来了,{0}快跑!",name); } } }
效果展示
4.面向对象(反射):米老师不仅仅可以叫何老师来开门,也可以叫其他老师开门
代码实现
客户端
public class Client { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { Notice notice=new Notice(); notice.notice(); } }
业务封装类
public class Notice { private void MiAndHeBusiness() throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException, IOException { TeacherHe teacherHe = new TeacherHe(); teacherHe.acceptMessage(); } public void notice() throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException { this.MiAndHeBusiness(); } }
发送消息类
public class TeacherMi { public void sendMsg(){ System.out.println("我需要开一下门"); } public void sendMsgAndKey(String room,String key){ System.out.println("这是"+room+"以后"+key+"由你来保管,快开门吧"); } public static void sendMessage(){ System.out.println("帮我开一下办公室的门"); } }
接收消息类
public class TeacherHe { public void acceptMessage() throws IOException, ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException { this.acceptMsg(); } private void acceptMsg() throws IllegalAccessException, InvocationTargetException, ClassNotFoundException, NoSuchMethodException, InstantiationException, IOException { BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); System.out.println("请输入要依赖的类路径"); String className=br.readLine(); System.out.println("请输入要执行的方法"); String methodName=br.readLine(); System.out.println("请输入方法要传入的第一个参数"); String roomName=br.readLine(); System.out.println("请输入方法要传入的第一个参数"); String keyName=br.readLine(); br.close(); Class sendMsgClass=Class.forName(className); Method sendMsgMethod= sendMsgClass.getMethod(methodName,String.class,String.class); Object sender = sendMsgClass.newInstance(); sendMsgMethod.invoke(sender,roomName,keyName); System.out.println("收到了,我来开门了"); this.open(); } private void open(){ System.out.println("正在开门中。。。。。。。。。。。 门开了"); } }
效果展示
5.面向对象(Java事件与委托)
类图展示
代码实现
客户端
public class Client { public static void main(String[] args) throws Exception { Notice notice=new Notice(); notice.notice(); } }
notice类
public class Notice { /** * @Author:Wuzilong * @Description:写基本的逻辑,如何实现的方法 * @CreateTime: 2023/6/28 8:14 * @param: * @return: **/ private void compositeBusiness() throws Exception { GetParam getParam=new GetParam(); List<String> param = getParam.getParam(); BusinessMethod businessMethod=new BusinessMethod(); if(param.size()==2){ businessMethod.businessMethod(param.get(0),param.get(1)); }else{ businessMethod.businessMethod(param.get(0),param.get(1),param.get(2)); } } public void notice() throws Exception { this.compositeBusiness(); } /** * @Author:Wuzilong * @Description: 获取控制台传入的参数 * @CreateTime: 2023/6/28 8:15 * @param: * @return: **/ class GetParam{ private List<String> getParam() throws Exception{ Scanner scanner=new Scanner(System.in); System.out.println("请输入send的对象名.方法,例如:OpenDoorMHListenerConfigV2.SendMessager.sendMessage"); String sendCNAMN=scanner.nextLine(); System.out.println("请输入receive的对象名.方法,例如:OpenDoorMHListenerConfigV2.TeacherHe.receiveMessage"); String receiveFirst=scanner.nextLine(); System.out.println("现在还可以设置一个receive对象是否需要,回复y则为继续输入"); List<String> paramList=new ArrayList<>(); paramList.add(sendCNAMN); paramList.add(receiveFirst); if(scanner.nextLine().equals("y")){ System.out.println("请输入第二个receive对象的对象名.方法,例如:OpenDoorMHListenerConfigV2.TeacherLiang.receiveMessage"); String receiveSecond = scanner.nextLine(); paramList.add(receiveSecond); return paramList; } return paramList; } } class BusinessMethod{ private void businessMethod(String sendCNameAndMName,String receiveCNameAndMName) throws Exception { Listener listener = new Listener(); listener.addSender(sendCNameAndMName); listener.addReceiver(receiveCNameAndMName); listener.start(); } private void businessMethod(String sendCNameAndMName,String receiveFirst,String receiveSecond) throws Exception { Listener listener = new Listener(); listener.addSender(sendCNameAndMName); listener.addReceiver(receiveFirst); listener.addReceiver(receiveSecond); listener.start(); } } }
委托类
public class Delegate { //用来存储发消息人匹配的事件对象 private List<Delegate> receiveMessagerList=new ArrayList<>(); //用来存储注册进来的对象信息包括 对象本身、要执行的方法和方法的入参 private List<Triple<Person,Method,Object[]>> personMethodList=new ArrayList<>(); public Delegate(){} public void invoke(){ this.startMethod(); for (Delegate delegate:receiveMessagerList){ delegate.startMethod(); } } private void startMethod(){ for (Triple<Person, Method, Object[]> personMethodTriple : personMethodList) { try { personMethodTriple.getMiddle().invoke(personMethodTriple.getLeft(),personMethodTriple.getRight()); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } } public void addReceiveDelegate(Delegate delegate){ this.receiveMessagerList.add(delegate); } public void addPerson(String classNameAndMethodName, Object...methodParameter ){ String className = classNameAndMethodName.substring(0,classNameAndMethodName.lastIndexOf(".")); String methodName = classNameAndMethodName.substring(classNameAndMethodName.lastIndexOf(".")+1); int len=methodParameter.length; Class[] methodType = new Class[len]; for(int i=0;i<len;i++){ methodType[i]=methodParameter[i].getClass(); } Person tmpPerson=null; Method tmpMethod=null; try { tmpPerson = (Person)Class.forName(className).newInstance(); tmpMethod=tmpPerson.getClass().getMethod(methodName,methodType); } catch (Exception e) { throw new RuntimeException(e); } this.personMethodList.add(new ImmutableTriple<>(tmpPerson,tmpMethod,methodParameter)); } public static Delegate getInstance(String className){ Delegate delegate=null; try { delegate= (Delegate)Class.forName(className).newInstance(); } catch (Exception e) { System.out.println(e.getMessage()); System.out.println("创建对象失败"); } return delegate; } }
事件类
public class TeacherHeEvent extends Delegate { }
监控类
1 public class Listener { 2 private Map delegateReceiveMap=new HashMap<>(); 3 private Map delegateSendMap=new HashMap<>(); 4 DelegateRelation delegateRelation=new DelegateRelation(); 5 public void addSender(String sendCNameAndMName) throws Exception { 6 delegateRelation.addDelegate(sendCNameAndMName,delegateSendMap); 7 } 8 public void addReceiver(String receiveCNameAndMName)throws Exception { 9 delegateRelation.addDelegate(receiveCNameAndMName,delegateReceiveMap); 10 } 11 public void start(){ 12 this.matching(); 13 this.execute(); 14 } 15 /** 16 * @description: 匹配发消息和收消息人员 17 * @author: wuzilong 18 * @date: 2023/6/24 15:47 19 * @param: [] 20 * @return: void 21 **/ 22 public void matching(){ 23 delegateRelation.delegateRelation(delegateSendMap,delegateReceiveMap); 24 } 25 /** 26 * @description: 执行匹配后的发消息委托 27 * @author: wuzilong 28 * @date: 2023/6/24 15:47 29 * @param: [] 30 * @return: void 31 **/ 32 public void execute(){ 33 Set keySet = delegateSendMap.keySet(); 34 for (String key:keySet){ 35 delegateSendMap.get(key).invoke(); 36 } 37 } 38 class DelegateRelation{ 39 public void addDelegate(String personName,Map delegateMap)throws Exception{ 40 String className = personName.substring(0,personName.lastIndexOf(".")); 41 if(delegateMap.get(className)==null){ 42 delegateMap.put(className, Delegate.getInstance(new ConfigUtil().get(className))); 43 } 44 delegateMap.get(className).addPerson(personName); 45 } 46 public void delegateRelation(Map delegateSendMap, Map delegateReceiveMap){ 47 Set receivekeySet = delegateReceiveMap.keySet(); 48 Set sendKeySet = delegateSendMap.keySet(); 49 for (String sendKey:sendKeySet){ 50 for (String receiveKey:receivekeySet){ 51 delegateSendMap.get(sendKey).addReceiveDelegate(delegateReceiveMap.get(receiveKey)); 52 } 53 } 54 } 55 } 56 }
抽象类:具体的业务对象直接继承Person然后重写方法即可。通过里式替换的方式使用对象
public class Person { public void sendMessage(){ } public void receiveMessage(){ } }
效果展示
五:总结提升
面向过程和面向对象没有好坏之分,只是应用的场景不同。我们之所以要用面向对象的思想是因为我们要为后期的维护考虑,这样我们就需要写出来的代码容易扩展,复用性强。在面向对象的基础上使用反射,使我们的系统更加的灵活,在运行的过程中我们可以让给来开门都可以。