首页 > 其他分享 >设计模式的七大原则

设计模式的七大原则

时间:2022-08-29 16:11:46浏览次数:64  
标签:原则 void 七大 System class println 设计模式 public out

编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战, 设计模式是为了让程序(软件),具有如下更好的特性

  1. 代码重用性 (即:相同功能的代码,不用多次编写)
  2. 可读性 (即:编程规范性,便于其他程序员的阅读和理解)
  3. 可扩展性 (即:当需要增加新的功能时,非常的方便,称为可维护)
  4. 可靠性 (即:当我们增加新的功能后,对原来的功能没有影响)

使程序呈现高内聚, 低耦合的特性

那么一个设计模式在这样设计的时候,要遵循哪些原则呢,即设计模式为什么这么设计的依据, 下面开始介绍,设计模式的 七大原则

  1. 单一职责原则
  2. 接口隔离原则
  3. 依赖倒转(倒置)原则
  4. 里氏替换原则
  5. 开闭原则
  6. 迪米特法则
  7. 合成复用原则

开闭原则

对扩展开放,对修改关闭,不能去修改原有的代码,实现一个热插拔的效果,易于维护和升级,

想要达到这种效果,我们需要使用接口和抽象类

创建抽象类

public abstract class AbstratSkin {

    public abstract void display();
}

 

public class DefaultSkin extends AbstratSkin {

    @Override
    public void display() {
        System.out.println("默认颜色");
    }
}

  

public class HeiSkin extends AbstratSkin{
    @Override
    public void display() {
        System.out.println("黑色");
    }
}

  可以理解为具体业务,去执行程序的

public class Input {

    private AbstratSkin skin;

    public void setSkin(AbstratSkin skin) {
        this.skin = skin;
    }

    public void display() {
        skin.display();
    }

}

  

public class Client {

    public static void main(String[] args) {
        Input input = new Input();
        DefaultSkin defaultSkin = new DefaultSkin();
        input.setSkin(defaultSkin);
        input.display();
    }
}

  

 里式替换原则:

是面向对象设计的基本原则之一.

任何基类可以出现的地方,子类一定可以出现,通俗理解:子类可以拓展父类的功能,但不能改变父类原有的功能,换句话说,子类继承父类时,除了添加新的方法完成新增功能外,尽量不要重写父类的方法.

如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特比偶尔是运用多态比较频繁时,程序运行出错的概率会非常大.

面向对象中的继承性思考:

  1. 继承包含这样一层含义:父类中凡是已经实现好的方法, 实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏。
  2. 继承在给程序设计带来便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能产生故障
  3. 问题提出:在编程中,如何正确的使用继承? => 里氏替换原则

里氏替换原则基本介绍:

  1. 里氏替换原则(Liskov Substitution Principle)在1988年,由麻省理工学院的以为姓里的女士提出的。
  2. 如果对每个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。换句话说,所有引用基类的地方必须能透明地使用其子类的对象。
  3. 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法
  4. 里氏替换原则告诉我们,继承实际上让两个类耦合性增强了, 在适当的情况下,可以通过聚合,组合,依赖 来解决问题

我们也可以通过提升的方法,来尽量满足里氏替换原则,假设现在有两个类,A 类和 B 类,如果 B 类继承 A 类,需要重写 A 类中的某些方法,那么,我们在 A 类 和 B 类之上,再抽取出一个更加通用的父类 Base,让 A 类和 B 类同时去继承 Base,这样 B 类就无须重写 A 类中的某些方法,达到基类的引用对子类对象透明的效果

代码一:

未遵循里氏替换原则,由于子类 B 继承父类 A 时重写了 func1() 方法,导致程序中使用多态时,本意是想调用重写前的方法,结果变成了重写后的方法,所以程序输出结果和预期不同

public interface Quadrilateral {

    double getLength();

    double getWidth();
}

 

public class Rectangle implements Quadrilateral{

    private double length;

    private double width;

    public void setLength(double length) {
        this.length = length;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    @Override
    public double getLength() {
        return length;
    }

    @Override
    public double getWidth() {
        return width;
    }
}
public class Square implements Quadrilateral {

    private double side;

    public void setSide(double side) {
        this.side = side;
    }

    @Override
    public double getLength() {
        return side;
    }

    @Override
    public double getWidth() {
        return side;
    }
}
public class Client {

    public static void main(String[] args) {
        Rectangle r = new Rectangle();
        r.setLength(20);
        r.setWidth(10);
        resize(r);
        print(r);
    }

    public static void resize(Rectangle r) {
        while (r.getWidth() <= r.getLength()) {
            r.setWidth(r.getWidth() + 1);
        }
    }

    public static void print(Quadrilateral q) {
        System.out.println(q.getLength());
        System.out.println(q.getWidth());
    }
}

依赖倒转原则:

依赖倒转(Dependence Inversion Principle )原则是指:

  1. 高层模块不应该依赖低层模块,二者都应该依赖其抽象
  2. 抽象不应该依赖细节,细节应该依赖抽象
  3. 依赖倒转(倒置)的中心思想是面向接口编程
  4. 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中,抽象指的是接口或抽象类,细节就是具体的实现类
  5. 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成
public interface HardDisk {

    /**
     * 存储数据
     * @param data
     */
    void save(String data);

    /**
     * 获取数据
     * @return
     */
    String getData();
}

 

public interface Cpu {

    /**
     * 运行cpu
     */
    void run();
}
public interface Memory {

    /**
     * 保存
     */
    void save();
}
创建实现类实现业务
public class XiJieHardDisk implements HardDisk{

    @Override
    public void save(String data) {
        System.out.println("使用希捷硬盘存储数据为:" + data);
    }

    @Override
    public String getData() {
        System.out.println("使用希捷硬盘读取数据");
        return "数据";
    }
}
public class IntelCpu implements Cpu{
    @Override
    public void run() {
        System.out.println("使用inter处理器");
    }
}
public class JinstonMemory implements Memory{

    @Override
    public void save() {
        System.out.println("使用金士顿内存条");
    }
}

组装接口即可

@Getter
@Setter
public class Computer {

    private HardDisk disk;

    private Cpu cpu;

    private Memory memory;

    public void run() {
        System.out.println("运行计算机");
        String data = disk.getData();
        System.out.println("从硬盘上读取的数据是:" + data);
        cpu.run();
        memory.save();
    }

}
public class ComputerDemo {

    public static void main(String[] args) {
        //创建组件
        HardDisk hardDisk = new XiJieHardDisk();
        Cpu cpu = new IntelCpu();
        Memory memory = new JinstonMemory();
        //创建计算机
        Computer computer = new Computer();
        //组装计算机
        computer.setDisk(hardDisk);
        computer.setCpu(cpu);
        computer.setMemory(memory);
        computer.run();
    }

}

 

 如果后续要替换硬件,可以创建好新的硬件实现接口功能,然后在Computer替换变量即可

接口隔离原则:

Interface Segregation Principle

基本介绍:客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上

举例说明:

  1. 类A通过接口Interface1依赖类B,类C通过接口Interface1依赖类D,如果接口Interface1对于类A和类C来说不是最小接口,但是类B和类D必须去实现他们不需要的方法。
  2. 按隔离原则应当这样处理:将接口Interface1拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则

 

 

 问题代码:

public interface SafetyDoor {

    //防盗
    void antiTheft();

    //防火
    void fireProof();

    //防水
    void waterProof();
}

//实现功能
public class HeiSafetyDoor implements SafetyDoor{
    @Override
    public void antiTheft() {
        System.out.println("防盗");
    }

    @Override
    public void fireProof() {
        System.out.println("防火");
    }

    @Override
    public void waterProof() {
        System.out.println("防水");
    }
}

//程序开始,开始使用安全门
public class Client {

    public static void main(String[] args) {
        HeiSafetyDoor door = new HeiSafetyDoor();
        door.antiTheft();
        door.fireProof();
        door.waterProof();
    }
}

 

 

 此时:如果我另一个类,不想实现其中的功能,就不得不实现了,所以要把接口隔离开

优化代码:

//防盗接口
public interface AntiTheft {

    //防盗
    void antiTheft();
}

//防火接口
public interface FireProof {

    //防火
    void fireProof();

}
//防水接口
public interface WaterProof {

    //防水
    void waterProof();

}

//实现我需要的功能接口即可

public class HeiSafetyDoor implements AntiTheft,FireProof,WaterProof{

    @Override
    public void antiTheft() {
        System.out.println("防盗");
    }

    @Override
    public void fireProof() {
        System.out.println("防火");
    }

    @Override
    public void waterProof() {
        System.out.println("防水");
    }
}

//这个实现类我只需要两个功能,那我就不需要实现别的接口就好了

public class RedSafetyDoor implements AntiTheft,FireProof{
    @Override
    public void antiTheft() {
        System.out.println("防盗");
    }

    @Override
    public void fireProof() {
        System.out.println("防火");
    }
}

//程序启动,开始使用安全门

public class Client {

    public static void main(String[] args) {
        HeiSafetyDoor door = new HeiSafetyDoor();
        door.antiTheft();
        door.fireProof();
        door.waterProof();

        System.out.println("============");
        //创建另一个安全门对象
        RedSafetyDoor redSafetyDoor = new RedSafetyDoor();
        redSafetyDoor.antiTheft();
        redSafetyDoor.fireProof();

    }
}

迪米特法则

迪米特法则的基本介绍

  1. 一个对象应该对其他对象保持最少的了解

  2. 类与类关系越密切,耦合度越大

  3. 迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的public 方法,不对外泄露任何信息

  4. 迪米特法则还有个更简单的定义:只与直接的朋友通信 

 

//明星
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Star {

    private String name;
}

//粉丝
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Fans {

    private String name;
}

//公司
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Company {
    private String name;

}

@Data
public class Agent {

    private Star star;

    private Fans fans;

    private Company company;

    //和粉丝见面
    public void meeting() {
        System.out.println(star.getName() + "和" + fans.getName() + "见面");
    }

    //和公司洽谈
    public void business() {
        System.out.println(star.getName() + "和" + company.getName() + "洽谈");
    }
}

public class Client {

    public static void main(String[] args) {
        //创建经纪人
        Agent agent = new Agent();
        //创建明星
        Star star = new Star("林青霞");
        //创建粉丝
        Fans fans = new Fans("李四");
        //创建公司
        Company company = new Company("苹果");
        agent.setStar(star);
        agent.setFans(fans);
        agent.setCompany(company);
        agent.meeting();
        agent.business();
    }
}

合成复用原则

合成复用原则(Composite Reuse Principle)

原则是尽量使用合成/聚合的方式,而不是使用继承,即尽量使用 has a 的关系,而不要使用 is a 的关系

 

标签:原则,void,七大,System,class,println,设计模式,public,out
From: https://www.cnblogs.com/lpzjava/p/16619056.html

相关文章

  • JavaScript设计模式及代码实现——单例模式
    单例模式1定义保证一个类仅有一个实例,并提供一个访问它的全局访问点。2应用时机当一个类的实例被频繁使用,如果重复创建这个实例,会无端消耗资源。比如dialog弹......
  • 设计模式—模板方法模式(template)
         模板方法模式,我们来看一下定义:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。我们来定......
  • 设计模式-装饰者模式(Decorate)
    首先我们来看一下装饰者模式的UML图 图中各个类的含义不懂没有关系,下面我会用一个形象的例子来一一介绍他们,相信大家看完后肯定就明白了  比如,我们玩了一款游戏,里......
  • 设计模式之(3)——抽象工厂方法模式
    定义:抽象工厂模式简单地讲,就是提供一个超级工厂,围绕这个超级工厂创建其他工厂;抽象工厂模式提供一个创建一些列相关或者相互依赖对象的接口;在此之前我们先来讲一下产品......
  • 学习设计模式和画图
    目录参考参考使用keynote画图https://www.yrunz.com/p/用keynote画出手绘风格的配图/使用plantuml进行设计......
  • 9.设计模式-原型模式
    1.单例模式1.饿汉式packagecom.serlyf.singleton;/***单例模式-饿汉式*1.构造私有*2.本类创建静态示例*3.getInstance()方法公开*/publicclassSingl......
  • 设计模式-建造者模式
    //1.定义产品//2.抽象构造者,定义抽象方法//3.具体建造者,生产具体的建造方法//4.指挥者,负责生产具体的产品packagecom.serlyf.builder;//产品publicclassHouse......
  • 尚硅谷-设计模式篇
    ​ 只学了点理论概念,没有实操代码,感觉无论是项目架构、代码设计,还是团队人员管理,其实都是设计模式的具体落地实现。https://www.bilibili.com/video/BV1G4411c7N4?p=149&......
  • 常见的设计模式-单例模式
    简述实现了类在当前进程中只有一个实例,比如python-GC重写__new__实现单例classA:def__new__(cls,*args,**kwargs):ifnothasattr(cls,'_instance......
  • 设计模式之工厂模式
    packagecn.com.pep.model.simpleFactory;/***@Title:CheesePizza*@Description:*@authorwwh*@date2022-8-2214:22:53*/publicclassCheesePiz......