美文网首页
面向对象的六大原则-Android设计模式

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

作者: Dawn试点人工智能 | 来源:发表于2019-07-26 10:14 被阅读0次

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

    单一职责原则

    单一职责原则英文名: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源码设计模式解析与实战>读后感;记录下。方便回顾。

    相关文章

      网友评论

          本文标题:面向对象的六大原则-Android设计模式

          本文链接:https://www.haomeiwen.com/subject/ymmcrctx.html