面向对象的六大原则-Android设计模式

2019-07-26  本文已影响0人  Dawn试点人工智能

面向对象有六大原则:单一职责原则、开闭原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特原则。

单一职责原则

单一职责原则英文名:Single Responsibility Principle ,缩写是SRP.SRP的定义是:就一个类而言,应该仅有一个引起它变化的原因。一个类中应该是一组相关性很高的函数,数据的封装。

定义:

不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。

问题由来:

类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。

解决方案:

遵循单一职责原则。分别建立两个类T1、T2,使T1完成职责P1功能,T2完成职责P2功能。这样,当修改类T1时,不会使职责P2发生故障风险;同理,当修改T2时,也不会使职责P1发生故障风险

遵循单一职责原的优点有:

1,可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
2,提高类的可读性,提高系统的可维护性;
3,变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。
4,需要说明的一点是单一职责原则不只是面向对象编程思想所特有的,只要是模块化的程序设计,都适用单一职责原则。
https://blog.csdn.net/IBelieve1974/article/details/54898341

开闭原则

开闭原则英文全称:Open Close Principle,缩写是OCP.
开闭原则,顾名思义,对扩展开放,对修改封闭.

开闭原则的定义:

软件中的对象(类、模块、函数等)应该对于扩展是开放的。但修改是封闭的。

开闭原则和依赖倒置原则

追求的结果是完全一样的,所有类都去依赖于抽象类。只是角度,不一样,依赖倒置原则是从这样的角度谈得,通常习惯性设计是高层依赖低层,现在变为低层依赖高层定义的接口。而开闭原则谈的是,加入抽象类,低层便于扩展,高层代码可以保持不变。

里氏替换原则

里氏替换原则英文全称是Liskov Substitution Principle.缩写是LSP.

定义:

所有引用基类的地方必须能透明的使用其子类的对象。
通俗讲:只要父类能出现的地方子类就可以出现。而且替换为子类也不会产生任何错误或异常,使用者可能不知道是子类还是父类。但反过来就不行,有子类出现的地方父类未必就能适应。

面向对象的三大特点:封装、继承、多态。
LSP就是依赖于继承、多态。
LSP的核心原理是抽象。
Liskov替换原则核心就是子类能完全替换它的基类。


LSP.jpg

依赖倒置原则

依赖倒置原则英文全称是Dependence Inversion Principle.缩写是DIP.
依赖倒置原则关键点:
1,高层模块不应该依赖底层模块,两者应该依赖其抽象。
2,抽象不应该依赖细节。
3,细节应依赖抽象。
在Java语言中,抽象就是指接口后抽象类,两者都是不能直接被实例化的。细节就是实现类,实现接口或继承抽象类而产生的类就是细节,其特点是可以直接被实例化,也就是加上一个关键字new产生一个对象。高层模块就是调用端,低层模块就是具体实现类。依赖倒置原则在Java语言中的表现就是:模块间的依赖通过抽象发送,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。
其实就是面向接口编程或是面向抽象编程。这里的抽象指的是接口或抽象类。
看看依赖倒置是怎样解决这个问题的?它的两个原则:

  1. 高层模块不该依赖于低层模块, 二者都该依赖于抽象

  2. 抽象不应该依赖于细节,细节应该依赖于抽象


    DIP.jpg
public interface ICar
{
void Run();
void Turn();
void Stop();
}
public class BmwCar implements  ICar
{
public void Run()
{
Console.WriteLine("宝马开始启动了");
}
public void Turn()
{
Console.WriteLine("宝马开始转弯了");
}
public void Stop()
{
Console.WriteLine("宝马开始停车了");
}
}
public class FordCar implements  ICar
{
publicvoidRun()
{
Console.WriteLine("福特开始启动了");
}
public void Turn()
{
Console.WriteLine("福特开始转弯了");
}
public void Stop()
{
Console.WriteLine("福特开始停车了");
}
}
public class HondaCar implements ICar
{
publicvoidRun()
{
Console.WriteLine("本田开始启动了");
}
public void Turn()
{
Console.WriteLine("本田开始转弯了");
}
public void Stop()
{
Console.WriteLine("本田开始停车了");
}
}
public class AutoSystem
{
private ICar icar;
public AutoSystem(ICar icar)
{
this.icar=icar;
}
private void RunCar()
{
icar.Run();
}
private void TurnCar()
{
icar.Turn();
}
private void StopCar()
{
icar.Stop();
}
}
UML类图基础了解

https://www.cnblogs.com/pangjianxin/p/7877868.html

接口隔离原则

接口隔离原则英文全称是interface Segregation Principles。缩写是ISP,

接口隔离原则定义:

客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
ISP将非常庞大,臃肿的接口拆分成更小的和更具体的接口,这样客户只需要知道他感兴趣的方法。
ISP的目的是系统解开耦合,从而容易重构,更改和重新部署。


ISP.jpg

见上图,该把接口细分到3个接口中去,保证每个类都只实现它需要的接口。

接口隔离原则与单一职责原则有什么区别呢?

单一职责原则,是指一个类只应该响应一个变化。比如一个赛马的程序,需要两个功能一是记每匹马跑的圈数,另一个是计算谁是对每匹马计算最终得分。 这两个功能有一点的联系,但是外部调用有可能只需要统计每匹马跑的圈数。所以要把这两个功能写到一个类里面。否则违反了单一职责原来。


ISP_UML.jpg
interface IOrderForPortal{
    String getOrder();
}
interface IOrderForOtherSys{
    String insertOrder();
    String getOrder();
}
interface IOrderForAdmin{ //extendsIOrderForPortal,IOrderForOtherSys
    String deleteOrder();
    String updateOrder();
    String insertOrder();
    String getOrder();
}
/*
interface IOrderForPortal{
    String getOrder();
}
interface IOrderForOtherSys{
    String insertOrder();
}
interface IOrderForAdmin extendsIOrderForPortal,IOrderForOtherSys{
    String updateOrder();
    String deleteOrder();
}
*/
class Order implements IOrderForPortal,IOrderForOtherSys,IOrderForAdmin{
    private Order(){
        //--什么都不干,就是为了不让直接 new,防止客户端直接New,然后访问它不需要的方法.
    }
    //返回给Portal
    public static IOrderForPortal getOrderForPortal(){
        return (IOrderForPortal)new Order();
    }
    //返回给OtherSys
    public static IOrderForOtherSys getOrderForOtherSys(){
        return (IOrderForOtherSys)new Order();
    }
    //返回给Admin
    public static IOrderForAdmin getOrderForAdmin(){
        return (IOrderForAdmin)new Order();
    }
    //--下面是接口方法的实现.只是返回了一个String用于演示
    public String getOrder(){
        return "implemented getOrder";
    }
    public String insertOrder(){
        return "implemented insertOrder";
    }
    public String updateOrder(){
        return "implemented updateOrder";
    }
    public String deleteOrder(){
        return "implemented deleteOrder";
    }
}
public class TestCreateLimit{
    public static void main(String[] args){
        IOrderForPortal orderForPortal =Order.getOrderForPortal();
        IOrderForOtherSys orderForOtherSys =Order.getOrderForOtherSys();
        IOrderForAdmin orderForAdmin = Order.getOrderForAdmin();
        System.out.println("Portal门户调用方法:"
+orderForPortal.getOrder());
        System.out.println("OtherSys外部系统调用方法:"
+orderForOtherSys.insertOrder());
        System.out.println("Admin管理后台调用方 
 法:"+orderForAdmin.getOrder()+";"
    +orderForAdmin.insertOrder()+";"
    +orderForAdmin.updateOrder()+";"
    +orderForAdmin.deleteOrder());
    }
}

SOLID:单一职责,开闭原则,里氏替换,接口隔离,依赖倒置。这几个关键字:抽象,单一职责,最小化。

迪米特原则

迪米特原则英文全称为Law of Demeter. 缩写是LOD,也称为最少知识原则(Least Knowledge Principle)。
一个对象应该对其他对象有最少的了解。
通俗讲:一个类应该对自己需要耦合或调用的类知道的最少,类的内部实现与调用者或者依赖者没关系,调用者或依赖者只需要知道它需要的方法即可。


LOD.jpg
//房间
public class Room {
    public float area;
    public float price;
    public Room(float area, float price) {
        this.area = area;
        this.price = price;
    }
    @Override
    public String toString() {
        return "Room [area="+area+",price="+price+"]";
    }
}
//中介
public class Mediator {
List<Room> mRooms=new ArrayList<>();

    public Mediator() {
        for (int i=0;i<5;i++){
            mRooms.add(new Room(14+i,(14+i)*1500));
        }
    }
    public Room rentOut(float area,float price){
        for (Room room:mRooms){
            if (isSuitable(area,price,room)) {
                return  room;
            }
        }
        return  null;
    }
    private boolean isSuitable(float area,float price,Room room)
{
        return room.price<=price&&room.area>=area;
    }
}
//租户
public class Tenant {
 public void rentRoom(float roomArea,
     float roomPrice,Mediator mediator){
      System.out.printf("租到房啦"+
         mediator.rentOut(roomArea,roomPrice));
 }
}

迪米特法则又叫最少知道原则。通俗的来讲,就是一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类来说,无论逻辑多么复杂,都尽量地的将逻辑封装在类的内部,对外除了提供的public方法,不对外泄漏任何信息。
迪米特法则还有一个更简单的定义:只与直接的朋友通信。首先来解释一下什么是直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。
耦合的方式很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友。
也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。
举一个例子:有一个集团公司,下属单位有分公司和直属部门,现在要求打印出所有下属单位的员工ID。
从逻辑上讲总公司只与他的分公司耦合就行了,与分公司的员工并没有任何联系,这样设计显然是增加了不必要的耦合。
按照迪米特法则,应该避免类中出现这样非直接朋友关系的耦合

class SubCompanyManager{
    public List<SubEmployee> getAllEmployee(){
        List<SubEmployee> list = new ArrayList<SubEmployee>();
        for(int i=0; i<100; i++){
            SubEmployee emp = new SubEmployee();
            //为分公司人员按顺序分配一个ID
            emp.setId("分公司"+i);
            list.add(emp);
        }
        return list;
    }
    public void printEmployee(){
        List<SubEmployee> list = this.getAllEmployee();
        for(SubEmployee e:list){
            System.out.println(e.getId());
        }
    }
}
 
class CompanyManager{
    public List<Employee> getAllEmployee(){
        List<Employee> list = new ArrayList<Employee>();
        for(int i=0; i<30; i++){
            Employee emp = new Employee();
            //为总公司人员按顺序分配一个ID
            emp.setId("总公司"+i);
            list.add(emp);
        }
        return list;
    }
    
    public void printAllEmployee(SubCompanyManager sub){
        sub.printEmployee();
        List<Employee> list2 = this.getAllEmployee();
        for(Employee e:list2){
            System.out.println(e.getId());
        }
    }
}

public class Client{
    public static void main(String[] args){
        CompanyManager e = new CompanyManager();
        e.printAllEmployee(new SubCompanyManager());
    }
}

<Android源码设计模式解析与实战>读后感;记录下。方便回顾。

上一篇下一篇

猜你喜欢

热点阅读