1.单一职责原则 一个类应该有且仅有一个引起它变化的原因 例如 实现登录功能,不应该设计一个类,即负责数据库的连接,又负责页面的初始化,又负责数据的接收和处理 而应该把这些功能分开,分成多个不同的类,各司其职
2.开闭原则 一个软件实体应该对拓展开放对修改关闭,也就是说,当需要修改功能或者添加新的功能时,不应该通过修改源代码的方式,而应该通过拓展 举例来说,某一个图形页面提供了各种各样的按钮,例如CircleButton RectangleButton,假设一开始页面使用的是圆形按钮,并且通过一个display方法显示,那如果想换成矩形的按钮,则需要修改图形页面的源代码,这就是违背了对修改关闭
那么如何做才符合开闭原则呢? 可以实现一个抽象按钮类,让各种各样的按钮类,无论是CircleButton、RectangleButton还是其他的,都继承它,在图形页面中只需要修改XML文件即可实现切换,而不需要修改源代码。
3.里氏代换原则
简单来说,代码中任何父类的地方都应该能替换成他的子类,反之则不一定成立,更专业的说法是 任何使用基类对象的地方都可以使用子类对象替换
举例来说
public abstract class Shape { public abstract double getArea(); } public class Rectangle extends Shape { private double width; private double height; public Rectangle(double width, double height) { this.width = width; this.height = height; } @Override public double getArea() { return width * height; } } public class Circle extends Shape { private double radius; public Circle(double radius) { this.radius = radius; } @Override public double getArea() { return Math.PI * radius * radius; } } 在这个例子中,我们有抽象类 Shape 和它的两个子类:Rectangle 和 Circle。每个形状都有一个获取面积的方法 getArea()。 假设现在有一个场景,我们需要计算一组形状的总面积。我们可以创建一个方法来处理这个问题: java public double getTotalArea(Shape[] shapes) { double total = 0.0; for (Shape shape : shapes) { total += shape.getArea(); } return total; }
那么在主类中
public static void main(String[] args) { Shape[] shapes = new Shape[3]; shapes[0] = new Rectangle(5, 4); shapes[1] = new Circle(3); shapes[2] = new Rectangle(2, 6); double totalArea = getTotalArea(shapes); System.out.println("Total area: " + totalArea); }
可以把Shape[]中的任意一个对象赋值为它的子类对象
可以看出,里氏替换原则就遵循了开闭原则的对拓展开放对修改关闭
4.依赖倒转原则
针对接口编程,而不是针对实现
举例来说
假设我们有一个Person类,它需要接收消息,最初的设计可能是这样的: java class Person { private Email email; public Person(Email email) { this.email = email; } public void receiveMessage(String message) { email.send(message); } } class Email { public void send(String message) { // 发送电子邮件的具体实现 } }
可以看到,在Person的构造方法中,设置了this.email=email,说明它直接依赖了Email类,并与他进行了耦合
那么假设我现在需要修改,用Wechat接收,那么我需要修改Person的源代码,这显然不符合开闭原则,因此可以这样做
public Abstarct一个接受类型类,存在一个抽象的send方法,让其他的方法,无论是email、phone、wechat类都继承他,实现各自的send方法,然后在Person的构造函数中
直接写 Public Person(AbstractReceive ab),然后再receiveMessage中,使用ab.send(message),这样调用的时候,直接实例化对象,然后注入想要的类型即可
例如在main方法中
Person person = new Person(Wechat wechat);
String message = "用于测试";
person.receiveMessage;
这样就满足了依赖倒转原则
5.接口隔离原则
简单来说,使用多个专门的接口,而不是使用一个单一的总接口,分割的思想
假设我们有一个Animal接口,包含各种动物可能会执行的动作: java interface Animal { void eat(); void sleep(); void fly(); // 飞行方法 } 然后我们创建了两个实现类:Dog和Bird,它们分别实现了Animal接口: java class Dog implements Animal { @Override public void eat() { System.out.println("Dog is eating"); } @Override public void sleep() { System.out.println("Dog is sleeping"); } @Override public void fly() { throw new UnsupportedOperationException("Dogs can't fly!"); } } class Bird implements Animal { @Override public void eat() { System.out.println("Bird is eating"); } @Override public void sleep() { System.out.println("Bird is sleeping"); } @Override public void fly() { System.out.println("Bird is flying"); } } 在这个例子中,Dog类需要实现fly()方法,尽管狗不会飞。这就是违反了接口隔离原则的一个例子,因为Dog类被迫实现了它并不需要的方法。
为了解决这个问题,我们可以将Animal接口拆分为多个更细粒度的接口: java interface Eater { void eat(); } interface Sleeper { void sleep(); } interface Flyer { void fly(); } class Dog implements Eater, Sleeper { @Override public void eat() { System.out.println("Dog is eating"); } @Override public void sleep() { System.out.println("Dog is sleeping"); } } class Bird implements Eater, Sleeper, Flyer { @Override public void eat() { System.out.println("Bird is eating"); } @Override public void sleep() { System.out.println("Bird is sleeping"); } @Override public void fly() { System.out.println("Bird is flying"); } }
7.合成复用原则
多用关联少用继承
假设我们有一个Car类,它需要一个发动机。最初的设计可能是这样的: //Engine是一个抽象类,符合依赖倒转原则 java class Car { private Engine engine; public Car() { this.engine = new Engine(); } public void drive() { engine.start(); } } class Engine { public void start() { // 启动发动机的具体实现 } }
在这个例子中,Car类通过组合关系包含了一个Engine对象。当我们创建一个新的Car实例时,它会自动拥有一个引擎。这就是合成复用的体现。 如果我们将上述设计改为通过继承实现,可能会像这样: java class Car extends Engine { public void drive() { start(); } } class Engine { public void start() { // 启动发动机的具体实现 } }
在上述例子中,如果Car类继承了Engine类,意味着Car类不仅具有汽车的功能,还承担了发动机的责任。这是因为继承是一种"是-a-kind-of"的关系,即子类代表了一种特殊的父类。在这种情况下,
Car类被看作是一种特殊的Engine,这与现实世界中的概念不符。
迪米特法则
不要和“陌生人说话”
假设我们有一个订单系统,包括Order、Customer和Product三个类: java class Order { private Customer customer; private List<Product> products; public Order(Customer customer, List<Product> products) { this.customer = customer; this.products = products; } public double calculateTotalPrice() { double totalPrice = 0; for (Product product : products) { totalPrice += product.getPrice(); } return totalPrice; } public void deliver() { // 调用快递服务将订单送给客户 // 这里违反了迪米特法则,因为Order类知道太多关于快递服务的知识 } } class Customer { private String name; private Address address; // 构造函数、getter和setter省略... } class Product { private String name; private double price; // 构造函数、getter和setter省略... }
在编写deliver的时候,如果我们直接在其中写快递的方法,就会导致Order了解太多无关的快递服务内容,那么如何避免呢?
定义一个新的类,把deliver方法作为它的方法,在Order中只需要实例化这个新的类并调用方法即可。
标签:软件设计,double,void,七大,模式,class,println,Override,public From: https://www.cnblogs.com/Arkiya/p/17880219.html