zoukankan      html  css  js  c++  java
  • OOP 面向对象 七大原则 (一)

    OOP 面向对象   七大原则 (一)

      大家众所周知,面向对象有三大特征继承封装多态的同时,还具有这七大原则,三大特征上一篇已经详细说明,这一篇就为大家详解一下七大原则: 单一职责原则,开闭原则,里氏替换原则,依赖倒置原则,接口隔离原则,迪米特法则,组合聚合复用原则

      单一职责原则:一个类只负责一个领域的内容,简而言之就是自己的类负责自己的事情,与别的类互不干涉

      场景案例:女孩子购物

      

    /**
    			 * 	oop 单一原则实现
    			 *  @author gongliying
    			 * 	@data 2019-06-10
    			 */
    			aaa(){
    				class People{
    					getAll(){
    						console.log("打车去Dior实体店买口红")
    						console.log("打车去Only实体店买裙子")
    					}
    				}
    				new People().getAll();
    			}
    

       打车去实体店买口红跟打车去实体店买裙子,我虽然写在了同样一个方法里面,但是呢却不能同时进行

        解决思路:面向对象单一职责,一个类只做一件事情,互不干涉

    aaa(){
    				class People{
    					Dior(content){
    						console.log('打车去Dior实体店买' + content)
    					}
    					Only(content){
    						console.log('打车去Only实体店' + content)
    					}
    					getAll(){
    						this.JD('口红')
    						this.TM('裙子')
    					}
    				}
    				new People().getAll();        //打车去Dior实体店买口红
                                         //打车去Only实体店买裙子
                                             }

      这样事情就解决了,一个类方法只做一件事情,我在Dior的方法中只能去买口红,不能去进行买裙子的操作,这就是单一原则

       开闭原则:对修改关闭,对扩展开放

        一个对象(模板,类,方法)只要是在生命周期内,都会发生变化,而开闭原则就是在不修改原有模块的基础上,扩展其功能

        还以口红为例,商场中有一家店面里面之后Dior和CHANEL两个品牌,那么店员介绍的品牌不是Dior就是CHANEL,一般情况下都会这样写

    /**
    	* oop 开闭原则实现
    	* @author 宫丽颖
    	* @date 2019-06-13
     */
    	achieve(){
    		let  type ='dior' 
    		if (type == 'dior') {
    			console.log('这是dior')
    		}else{
    			console.log('这是chanel')
    		}
             }        
         //这是dior

        这样写是没有什么问题的,但是呢,店面中又有新牌子了ysl,这就变成不是dior 不是CHANEL就是ysl了  随之我们的代码就又变成的这样  

    /**
    			 * oop 开闭原则实现
    			 * @author 宫丽颖
    			 * @date 2019-06-13
    			 */
    			achieve(){
    				let  type ='chanel' 
    				if (type == 'dior') {
    					console.log('这是dior')
    				}else if(type == 'chanel'){
    					console.log('这是chanel')
    				}else{
    					console.log('这是ysl')
    				}
                        //这是chanel },

        随着商店店面更新的口红牌子越来越多,需求越来越多的时候,随之意味这样的代码,对原来代码的修改也越来越多,如果一不小心改错的话,可能整段就垮掉,为了解决这样的事件,建议使用开闭原则,对修改关闭,对扩展开放

    /**
    			 * oop 开闭原则实现
    			 * @author 宫丽颖
    			 * @date 2019-06-13
    			 */
    			achieve() {
    				let  type = 'ysl'
    				if (type == 'dior') return this.dior.dior();
    				if (type == 'chanel') return this.chanel.chanel();
    				if (type == 'ysl') return this.ysl.ysl();
    			},
    
                  dior : {
    		      dior() {
                    	  alert('这是dior')
    			 }
    	      	},
    		    chanel : {
    			chanel() {
         		  alert('这是chanel')
    			}
    	         },
    		    ysl : {
    			ysl() {
    			  alert('这是ysl')
    			}
    		    }           //结果为弹出  这是ysl
    

      这样增加需求的时候直接在data里面定义一个就好了,再多的需求也不怕不怕啦~~~

      里氏替换原则:父类能出现的地方,可以用子类代替,子类拥有父类的所有属性和方法,通俗来说子类拥有父类的功能,可以拓展父类的功能,但是不能修改父类的功能

      口红为例?

    /**
    			 * oop 里氏替换原则实现
    			 * @author 宫丽颖
    			 * @date 2019-06-13
    			 */
    			achieve() {
    				class Kouhong{
    					constructor(e){
    						this.name=e.name
    						this.price=e.price
    					}
    					look(){
    						console.log(this.name,'的口红,一共',this.price,'元')
    					}
    				}
    
    
    				//子类
    				class Dior extends Kouhong{
    					look(){
    						console.log('这是',this.name,'的口红,一共',this.price)
    					}
    				}
    
    				var kouhong = new Kouhong({
    					name:"砖红色",
    					price:300
    				})
    				var dior =new Dior({
    					name:"脏橘色",
    					peice:280
    				})
    
    			
    				kouhong.look()   //砖红色 的口红,一共 300 元
    				dior.look()      //这是 大红色 的口红,一共 280
    
    			},
    

      这样写的话,你会发现子类直接覆盖了父类的内容,修改了父类的功能,虽然代码上没什么问题,但是对于以后的优化有着很大的影响,也违背了里氏替换原则,里氏替换原则要求拥有父类的所有方法,可以扩展父类的方法,但是不能修改,我用历史替换比较一下

    /**
    			 * oop 里氏替换原则实现
    			 * @author 宫丽颖
    			 * @date 2019-06-13
    			 */
    			achieve() {
    				class Kouhong{
    					constructor(e){
    						this.name=e.name
    						this.price=e.price
    					}
    					look(){
    						console.log(this.name,'的口红,一共',this.price,'元')
    					}
    					saw(){
    						console.log('口红很贵哦的!!')
    					}
    				}
    
    
    				//子类
    				class Dior extends Kouhong{
    					look(){
    						console.log('这是',this.name,'的口红,一共',this.price)
    					}
    				}
    				
    				class CHANEL extends Kouhong{
    					see(){
    						console.log('这是',this.name,'的口红,一共',this.price,'元')
    					}
    					so(){
    						console.log('因为那么贵所以才买不起嘛!!!!')
    					}
    				}
    
    				var kouhong = new Kouhong({
    					name:"砖红色",
    					price:300
    				})
    				var dior =new Dior({
    					name:"脏橘色",
    					price:280
    				})
    				var chanel = new CHANEL({
    					name:"豆沙色",
    					price:320
    				})
    
    			
    				kouhong.look()      //砖红色 的口红,一共 300 元            父类本身
    				dior.look()         //这是 脏橘色 的口红,一共 280          子类1继承父类将父类方法覆盖
    				chanel.look()       //豆沙色 的口红,一共 320 元       子类2继承父类显示父类方法
    				chanel.see()        //这是 豆沙色 的口红,一共 320 元     子类2在继承父类上扩展自己的方法
    				chanel.saw()        //口红很贵哦的!!             子类2继承父类另一个方法    子类继承了父类的所有方法
    				chanel.so()         //因为那么贵所以才买不起嘛!!!!        子类2扩展自己的另一个方法
    
    			},
    

      由此可见,子类1在继承父类的时候将父类覆盖,但是子类2在继承父类的时候继承了父类的所有方法并扩展了自己的方法,这就是里氏替换原则

       依赖倒置原则:程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。(节选自百度百科)

        emmmm,很官方的一句话 ,我用白话解释一下,就是说高层的模块不要依赖于低层的模块,不要靠比自己层级低的模块,高层低层应该同时依靠抽象,而抽象不应该依赖于细节而是应该细节依赖抽象 ,要是还没有懂的话,画张图把,当然还是口红为例了

    这样看是不是看懂了呢 这个人就是高层,左图就是在说 高层依赖低层,如果这个高层抹口红就只能抹口红,不能在抹其他的 ,要是想在抹别的,就要再加方法,太啰嗦

                     而右图就是在说明定义了一个抽象类抹,如果没有口红了还可以抹眼影啊,粉底之类的,人与眼影之间依赖抹这个抽象类来实现,这个抹眼影 这个细节依赖于抽象抹这个类,而这个高层人也可以创建不同的高层话不多说,代码附上

                        class cosmetics{
    					daub(){
    						console.log('抹了什么?')
    					}
    				}
    				class kouhong extends cosmetics{
    					go(){
    						return "抹了口红"
    					}
    				}
    				class yanying extends cosmetics{
    					go(){
    						return "抹了眼影"
    					}
    				}
    				class fendi extends cosmetics{
    					go(){
    						return "抹了粉底"
    					}
    				}
    				class people {
    					constructor(name) {
    						this.name = name
    					}
    					gotoEat(mo) {
    						console.log(this.name, mo.go())
    					}
    				}
    				kouhong = new kouhong
    				yanying = new yanying
    				fendi = new fendi
    				gong = new people('宫')
    				liying = new people('丽颖')
    
    				gong.gotoEat(kouhong)      //宫 抹了口红
    				gong.gotoEat(yanying)      //宫 抹了眼影
    				gong.gotoEat(fendi)        //宫 抹了粉底
    
    				liying.gotoEat(fendi)      //丽颖 抹了粉底
    

      结果我不仅通过抹的抽象类,创建了不同的细节,还创建不同的高层,不同的人通过抹的类创建了不同的细节,他们之间是不会相互影响的,这就是依赖倒置原则。

      

  • 相关阅读:
    利用Spring AOP自定义注解解决日志和签名校验
    SpringBoot返回date日期格式化,解决返回为TIMESTAMP时间戳格式或8小时时间差
    @RequestBody配合@JsonFormat注解实现字符串自动转换成Date
    Mysql的时间类型问题
    IntelliJ IDEA使用maven-javadoc-plugin生成Java Doc控制台乱码
    Maven学习笔记(十二)-maven打包之resource配置
    SpringBoot使用@Value从yml文件取值为空--注入静态变量
    cloud server ribbon 自定义策略配置
    JNA 如何 加载多个 存在依赖的 DLL 库
    Remote Desktop File Format
  • 原文地址:https://www.cnblogs.com/gongliying/p/11000060.html
Copyright © 2011-2022 走看看