zoukankan      html  css  js  c++  java
  • 实现简单的IOC容器(ByName)

    实现功能:小黄开奥迪上班/下班
    要求:可维护,可复用,可扩展,灵活性好
    第一版
    Audi
     1 public class Audi {
     2 
     3     public void start() {
     4         System.out.println("启动奥迪");
     5     }
     6 
     7     public void shutDown() {
     8         System.out.println("启动奥迪");
     9     }
    10 
    11     public void turnLeft() {
    12         System.out.println("奥迪左转");
    13     }
    14 
    15     public void turnRight() {
    16         System.out.println("奥迪右转");
    17     }
    18 }

    人类

     1 public class Person {
     2 
     3     void goHome() {
     4         Audi audi = new Audi();
     5         audi.start();
     6         audi.turnLeft();
     7         audi.turnRight();
     8         audi.shutDown();
     9     }
    10 
    11     void goWork() {
    12         Audi audi = new Audi();
    13         audi.start();
    14         audi.turnRight();
    15         audi.turnLeft();
    16         audi.shutDown();
    17     }
    18 
    19     void aNormalDay()
    20     {
    21         System.out.println("新的一天开始啦");
    22         System.out.println("------------");
    23         System.out.println("去工作");
    24         goWork();
    25         System.out.println("------------");
    26         System.out.println("回家");
    27         goHome();
    28         System.out.println("------------");
    29         System.out.println("一天结束啦");
    30     }
    31 }

    测试代码

    1 public static void main(String[] args) {
    2         Person xiaoHuang=new Person();
    3         xiaoHuang.aNormalDay();
    4     }
    缺点:
    1.是人类对象创建的奥迪车
    (1)不是每个人都有车(考虑将有车的人继承与普通人/或者把回家,工作的行为抽象成接口,由不同的人来实现)
    (2)不是每个人有车的人都是奥迪(考虑将汽车抽象出来)
    2.小黄如果要换车的话,需要修改代码过多
    3.小黄new了两次奥迪车,其实应该是同一辆奥迪车(考虑把局部变量,变为类的私有属性)

    违反 单一职责原则(人类创建车)
    开闭原则(需要修改代码)
    面向接口(都是实现类,没有使用接口)


    第二版

    汽车抽象类
    1 public abstract class Car {
    2     public abstract void start();
    3 
    4     public abstract void shutDown();
    5 
    6     public abstract void turnLeft();
    7 
    8     public abstract void turnRight();
    9 }
    Audi
     1 // 奥迪车世界上有很多辆
     2 // 所以应该是类,每个奥迪车应该是对象
     3 // 人这不一样,每个人都是一个单独的对象
     4 // 所以判断该成对象还是类的时候可以想象是单数还是复数
     5 // 单数则是对象,复数则是类
     6 public class Audi extends Car{
     7     @Override
     8     public void start() {
     9         System.out.println("启动奥迪");
    10     }
    11 
    12     @Override
    13     public void shutDown() {
    14         System.out.println("启动奥迪");
    15     }
    16 
    17     @Override
    18     public void turnLeft() {
    19         System.out.println("奥迪左转");
    20     }
    21 
    22     @Override
    23     public void turnRight() {
    24         System.out.println("奥迪右转");
    25     }
    26 }
    BMW
     1 public class BMW extends Car{
     2     @Override
     3     public void start() {
     4         System.out.println("启动宝马");
     5     }
     6 
     7     @Override
     8     public void shutDown() {
     9         System.out.println("启动宝马");
    10     }
    11 
    12     @Override
    13     public void turnLeft() {
    14         System.out.println("启动宝马");
    15     }
    16 
    17     @Override
    18     public void turnRight() {
    19         System.out.println("启动宝马");
    20     }
    21 }

    抽象人类

     1 public abstract class Person {
     2     abstract void goHome();
     3     abstract void goWork();
     4     //设计模式:模板模式
     5     public void aNormalDay()
     6     {
     7         System.out.println("新的一天开始啦");
     8         System.out.println("------------");
     9         System.out.println("去工作");
    10         goWork();
    11         System.out.println("------------");
    12         System.out.println("回家");
    13         goHome();
    14         System.out.println("------------");
    15         System.out.println("一天结束啦");
    16     }
    17 }

    有车一族

     1 public class PersonWithCar extends Person{
     2     //优点
     3     //1这个car不应该有人类创建,而是通过传入指定的car
     4     //2回家,工作使用的是同一辆车
     5     //3换车不需要修改代码,遵守开放闭合原则
     6     private Car car;
     7 
     8     public PersonWithCar(Car car) {
     9         this.car = car;
    10     }
    11 
    12 
    13     @Override
    14     void goHome() {
    15         car.start();
    16         car.turnRight();
    17         car.turnLeft();
    18         car.shutDown();
    19     }
    20 
    21     @Override
    22     void goWork() {
    23         car.start();
    24         car.turnRight();
    25         car.turnLeft();
    26         car.shutDown();
    27     }
    28 }
    小黄开奥迪上班/下班
    小张开宝马上班/下班
    模板模式
    优点
    1这个car不应该有人类创建,而是通过传入指定的car
    2回家,工作使用的是同一辆车
    3换车不需要修改代码,遵守开放闭合原则
    4.设置每个人的一天(上班,回家)的抽象,通过对不同交通工具的人来具体实现(模板模式)

    IOC容器版
     1 public class MyIocContainer {
     2 
     3     //保证只被初始化一次
     4     //跟随类的初始化而初始化
     5     private static Map<String, Object> container = new ConcurrentHashMap<>();
     6 
     7     public Object getBean(String id) {
     8         return container.get(id);
     9     }
    10 
    11     public void setBean(Class<?> clazz, String beanId, String... paramBeanId) {
    12         //通过id获取所有在bean容器的实例
    13         Object[] objects = new Object[paramBeanId.length];
    14         for (int i = 0; i < paramBeanId.length; i++) {
    15             objects[i] = getBean(paramBeanId[i]);
    16         }
    17 
    18         //使用不同的构造函数构造,最终只有一个能够成功
    19         Object bean = null;
    20         for (Constructor constructor : clazz.getConstructors()) {
    21             try {
    22                 bean = constructor.newInstance(objects);
    23             } catch (InstantiationException e) {
    24             } catch (IllegalAccessException e) {
    25             } catch (InvocationTargetException e) {
    26             }
    27         }
    28         if (bean == null)
    29             throw new RuntimeException("实例化失败");
    30         container.put(beanId, bean);
    31     }
    32 }
    很明显这次的IOC容器使用的模式是使用ByName,名字匹配类型(查阅资料发现ByName效率的确比ByType高,所有对使用@resource的byName)
    写了这个demo后对倚赖注入,反转控制有了更深的理解
    倚赖注入是目标:通过从容器注入bean,对象间的聚合和合成关系,是一种弱耦合的关系
    反转控制是手段:通过bean容器来控制bean的生命周期

       在容器中对象的创建只会创建一次(singleton模式下),如果name指定不对,就会出现bean注入失败的错误(我经常犯的错QAQ)

    1.控制bean的生命周期指的不是类加载,指的是控制对象bean的生命周期
    原来:客户端管理车的生产,现在由容器管理
    优点:大大解耦类与类的倚赖
    2.所有的对象都由容器管理
    优点:解耦,每个类只关注自己的业务逻辑

    代码地址:https://gitee.com/gang_bryant/DesignMode/tree/master/src/MyIoc


     
  • 相关阅读:
    使用java实现面向对象 第一章
    深入.NET平台和C#编程笔记 第九章 文件操作
    MySQL_第七章
    MySQL_第八章
    MySQL_第五章
    MySQL_第四章
    MySQL_第三章
    MySQL_第二章
    MySQL_第一章
    S2_OOP第二章
  • 原文地址:https://www.cnblogs.com/Gang-Bryant/p/10896440.html
Copyright © 2011-2022 走看看