面向对象的设计模式

"万丈高楼平地起,7种模式打地基",模式是一种规范,我们应该站在巨人的肩膀上越看越远,接下来,让我们去仔细了解了解面向对象的7种设计模式

7种设计模式

设计原则的核心思想

  • 找出应用中可能需要变化之处,独立出来,不要和不需要变化的代码混在一起

  • 针对接口编程,而坏是针对实现编程

  • 为了交互对象的耦合性而设计

  • 为了使程序高内聚,低耦合

  • 单一职责低耦合,高内聚

每一个类负责的任务很明确,降低代码之间的耦合度,如果代码耦合度较高,动一点则要动全身,当变化发生时设计或遭受到意想不到的破坏

public class Run {
  
     public  void run(){
          System.out.println("跑步");
     }
}

在Run类中只负责了Run()的功能,不负责其他的功能,在设计改变类的时候对整体的影响不大

  • 开闭原则适应性和灵活性 稳定性和延续性 可复用性和可维护性

在软件开发的过程中,随着版本的更替,软件的需求会越来越多,如果是修改的内容的话,会很费时,但是我们换个思路,如果在设计模式的时候,我们可以先评估出最容易发生的类,然后对其进行抽象化设计,当变化发生时,只需要增加新的具体类来实现新的业务功能

未使用开/闭原则:

/*
  开闭原则引入案例
 */
public class CarDemo {

    public static void main(String[] args) {
        new CarFactory().createCar(1);
        new CarFactory().createCar(2);
        new CarFactory().createCar(3);
     //后期如果需要添加车型,CarFactory需要修改代码
        //new CarFactory().createCar(4);
        //new CarFactory().createCar(5);
    }

}

/*
   汽车工程类,专门负责造汽车
 */
class CarFactory{

    /*
       违反了开闭原则,后期如果添加新的汽车类,则需要修改代码
     */
    public void createCar(int type){
          if(type==1){
              System.out.println("造宝马汽车"+new Car("宝马汽车"));
          }else if(type==2){
              System.out.println("造奥迪汽车"+new Car("奥迪汽车"));
          }else{
              System.out.println("造大众汽车"+new Car("大众汽车"));
          }
    }

}

/*
Car类
*/
class Car{
    String name;//定义了一个成员变量

    public Car(String name) {//有参构造函数
        this.name = name;
    }
}

使用开/闭原则:

/*
开闭原则案例
 */
class CarDemo{

    public static void main(String[] args) {
           new CarFactory().carfactory(new BMW());
           new CarFactory().carfactory(new Aodi());
           new CarFactory().carfactory(new DaZhong());

    }

}

//创建一个CarFactory类
class CarFactory{
         //创建一个车辆工厂的方法

      void   carfactory(Car car){
          car.createCar();
      }
}

   //创建一个抽象类Car
abstract  class Car{
   //创建一个创建车辆的抽象方法
   public abstract   void createCar();
}

/*
如果想添加车辆型号的话,只需要创建一个类继承Car类并实现createCar()方法,不用修改代码
*/

//继承并重写Car里的方法
class BMW extends Car{

    @Override
    public void createCar() {
        System.out.println("造宝马汽车");
    }
}

//继承并重写Car里的方法
class Aodi extends Car{
    @Override
    public void createCar() {
        System.out.println("造奥迪汽车");
    }
}

//继承并重写Car里的方法
class DaZhong extends Car{
    @Override
    public void createCar() {
        System.out.println("造大众汽车");
    }
}

//继承并重写Car里的方法
class BC extends Car{
    @Override
    public void createCar() {
        System.out.println("造奔驰汽车");

        Calendar.getInstance();
        new GregorianCalendar();
    }
}
  • 里氏替换原则(提高代码的复用性、提高代码的可扩展性 | 继承是具有侵入性的 增大了耦合性 )

基本概念继承必须确保超类锁拥有的性质在子类中仍然成立(子类继承父类后,尽量不要重写父类的方法,可以新增扩展其他的功能.保证子类功能的正确性. 不能让功能修改后,导致程序出错)

主要作用

  1. 里氏替换原则是实现开闭原则的重要方式之一

  1. 克服了继承中重写父类方法造成的可复用性变差的缺点

  1. 功能正确的保证

  1. 加强了程序的健壮性,提高了程序的维护性降低需求变更时引入的风险

代码演练:

/*
  里氏替换原则演示案例
  计算器父类
*/

public class CalculatorDemo{
    public static void main(String[] args) {
        System.out.println(new SuperCalculator().sum(5,5,5));
    }

}
//计算器 基类
class Calculator {
        //加法
        public int add(int a,int b){
            return a+b;
        }
       //减法
        public int sub(int a,int b){
            return a-b;
        }
}
/*
     超级计算器子类
*/
class SuperCalculator extends Calculator{

        //重写了父类加法
        @Override
        public int add(int a, int b) {
            return a+b+5;
        }

        //求和方法 子类新增的功能
        public int sum(int a,int b,int c){
            //调用add(),但是子类重写了父类方法,此处调用的子类方法发生了变化
            int result = this.add(a,b);
            return result+c;
        }
}

没有重写父类方法时,输出还是正确结果15,但是重写之后却改变了值,输出了错误的结果20

  • 依赖倒置(都依赖于抽象)

让程序面向抽象类编程、面向接口编程(依赖于抽象接口,对抽象进行编程)

/*
  依赖倒置引入案例
 */
public class WorkerDemo{
    public static void main(String[] args) {
        new Worker().getMessage(new DingDing());
        new Worker().getMessage(new WeChat());
        //每创建一个信息都要进行修改代码
    }
}

 class Worker {

    public void getMessage(DingDing ding){
        System.out.println(ding.sendMessage());
    }
    public void getMessage(WeChat weChat){
         System.out.println(weChat.sendMessage());
    }
    //每添加一个信息都要进行修改代码
}

//钉钉消息
class DingDing{
    public String sendMessage(){
           return "钉钉消息";
    }
}

//微信消息
class WeChat{
    public String sendMessage(){
        return "微信消息";
    }
}
/*
   依赖倒置案例演示
 */
public class WorkerDemo{

    public static void main(String[] args) {
        new Worker().getMessage(new WeChat());//具有可变性,有较高的适用性
    }

}

class Worker {

    public void getMessage(Message message){
        System.out.println(message.sendMessage());
    }

}

interface Message{
    public String sendMessage();
}

//添加一个信息需要创建一个类实现Message接口
class WeChat implements Message{
    @Override
    public String sendMessage() {
        return "微信消息";
    }
}
class DingDing implements Message{

    @Override
    public String sendMessage() {
        return "钉钉消息";
    }
}
  • 接口隔离

使用多个接口,不使用单一的总接口(这个最好理解,在这里就不解释了)

  • 迪米特原则

一个对象应该对其他对象有最少的了解(在一个类中,应尽量少的使用与其没有直接关系的类)

直接关系

  1. 类中的成员属性

  1. 在类中的方法作为参数使用

  1. 在类中的方法作为返回值类型

注意事项

  1. 核心是降低类之间的耦合

  1. 从被依赖折者的角度来看,尽量将逻辑封装在类的内部,对外除了提供的public方法,不泄露任何信息

  1. 从依赖者的角度来说,只依赖应该依赖的对象

  1. 切记不要为了用而用

代码实现:

public class Demeter {

    public static void main(String[] args) {
             new SchoolManger().printAllEmployee(new CollegeManger());
    }
}

/*
  学校员工类
 */
class SchoolEmployee{
    private String id;
    public void setId(String id){
        this.id = id;
    }
    public String getId(){
        return id;
    }
}

/*
 学院员工类
 */
class CollegeEmployee{
    private String id;
    public void setId(String id){
        this.id = id;
    }
    public String getId(){
        return id;
    }
}

//学院员工管理管理类
class CollegeManger{
    //生成学院所有的员工
    public List<CollegeEmployee> getCollegeEmployee(){
        ArrayList<CollegeEmployee> collegeEmployeeArrayList = new ArrayList<>();
        for (int i = 0; i <10 ; i++) {
            CollegeEmployee collegeEmployee = new CollegeEmployee();
            collegeEmployee.setId("学院员工的id="+i); //添加学院员工
            collegeEmployeeArrayList.add(collegeEmployee);
        }
        return collegeEmployeeArrayList;
    }

}
//学校员工管理类
class SchoolManger {
    //生成学校的员工
    public List<SchoolEmployee> getSchoolEmployee() {
        ArrayList<SchoolEmployee> employeeArrayList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            SchoolEmployee employee = new SchoolEmployee();
            employee.setId("学校的员工id=" + i);
            employeeArrayList.add(employee);
        }
        return employeeArrayList;
    }

    //输出学校员工和学院员工信息
    public void printAllEmployee(CollegeManger collegeManger) {
        //获取到学校员工
        List<SchoolEmployee> employeeArrayList = this.getSchoolEmployee();
        System.out.println("--------学校员工--------");
        for (SchoolEmployee employee1 : employeeArrayList) {
            System.out.println(employee1.getId());
        }

        System.out.println("--------学院员工--------");
        List<CollegeEmployee> collegeEmployees = collegeManger.getCollegeEmployee();
        //此处学校管理类中出现CollegeEmployee,此类与SchoolManger并非直接朋友,不合理
        for (CollegeEmployee collegeEmployee : collegeEmployees) {
            System.out.println(collegeEmployee.getId());
        }

    }
}
public class Demeter {

    public static void main(String[] args) {
             new SchoolManger().printAllEmployee(new CollegeManger());
    }
}

/*
  学校员工类
 */
class SchoolEmployee{
    private String id;
    public void setId(String id){
        this.id = id;
    }
    public String getId(){
        return id;
    }
}

/*
 学员员工类
 */
class CollegeEmployee{
    private String id;
    public void setId(String id){
        this.id = id;
    }
    public String getId(){
        return id;
    }
}

//学院员工管理管理类
class CollegeManger{
    //生成学员所有的员工
    public List<CollegeEmployee> getCollegeEmployee(){
        ArrayList<CollegeEmployee> collegeEmployeeArrayList = new ArrayList<>();
        for (int i = 0; i <10 ; i++) {
            CollegeEmployee collegeEmployee = new CollegeEmployee();
            collegeEmployee.setId("学院员工的id="+i); //添加学院员工
            collegeEmployeeArrayList.add(collegeEmployee);
        }
        return collegeEmployeeArrayList;
    }

    public void printCollegeEmployee(){
        List<CollegeEmployee> collegeEmployee = getCollegeEmployee();
        for (CollegeEmployee employee : collegeEmployee) {
            System.out.println("学员员工id="+employee.getId());
        }

    }

}
//学校员工管理类
class SchoolManger {
    //生成学校的员工
    public List<SchoolEmployee> getSchoolEmployee() {
        ArrayList<SchoolEmployee> employeeArrayList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            SchoolEmployee employee = new SchoolEmployee();
            employee.setId("学校的员工id=" + i);
            employeeArrayList.add(employee);
        }
        return employeeArrayList;
    }

    //输出学校员工和学院员工信息
    public void printAllEmployee(CollegeManger collegeManger) {
        //获取到学校员工
        List<SchoolEmployee> employeeArrayList = this.getSchoolEmployee();
        System.out.println("--------学校员工--------");
        for (SchoolEmployee employee1 : employeeArrayList) {
            System.out.println(employee1.getId());
        }

        //CollegeManger与SchoolManger是直接朋友,相互之间访问
        System.out.println("--------学员员工-----------");
                collegeManger.printCollegeEmployee();
    }
}
  • 组合/聚合复用原则(优先使用组合,使系统更灵活,其次才考虑继承,达到复用的目的)

代码实现:

/*
   组合/聚合复用原则案例1  使用依赖实现复用
 */
public class A {

    public void method01() {
    }

    public void method02() {
    }
}


class B extends A {
    private A a;

    public void method() {
    }
}

class Test {
    public static void main(String[] args) {
        new B().method01();
        new B().method02();
    }
}
/*
   组合/聚合复用原则案例2  使用组合/聚合实现复用
 */
public class A {

      public void method01(){
      }

      public void method02(){
      }
}


class B{

     A a;

     public void setA(A a){
         this.a = a;
     }

     public void use(){
         a.method01();
         a.method02();
     }

}

class Test{
    public static void main(String[] args) {
         A a = new A();
         B b = new B();
         b.setA(a);
         b.use();
    }
}
/*
   组合/聚合复用原则案例3  使用依赖实现复用
 */
public class A {

      public void method01(){
      }

      public void method02(){
      }
}


class B{
     public void use(A a){
         a.method01();
         a.method02();
     }


}

class Test{
    public static void main(String[] args) {
         A a = new A();
         B b = new B();
         b.use(a);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃橘子的Crow

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值