设计模式

设计模式

[TOC]

七大原则

单一职责原则

对类来说,一个类应该只负责一项职责,如类A负责两个不同职责:职责1和职责2.当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将A的粒度分解为A1和A2.

接口隔离原则

客户端不应该依赖于它不需要的接口,即一个类对另一个类的依赖一个建立在最小的接口上(接口拆分)

  • 类A类B如果

依赖倒转原则

  • 高层模块不应该依赖于底层模块,二者都应该依赖其抽象
  • 抽象不应该依赖细节,细节应该依赖抽象
  • 依赖倒转的中心思想时面向接口编程
  • 依赖倒转原则时基于这样的设计原理:相对于细节的多变性,抽象的对象要稳定的多.以抽象为基础搭建订单架构比以细节为基础的架构要稳定的多.在java中,抽象指的是接口或抽象类
  • 使用接口或抽象类的目的时制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成/

依赖关系传递的三种方式

  • 接口传递

    interface IOpenAndClose{
        void open();
    }
    
    interface Imple {
        void play();
    }
    
    class OpenAndClose implements IOpenAndClose{
        //通过传入方法参数传入实现类
        publick void open(Imple imple){
            imple.play();
        }
    }
    
  • 构造方法传递

    interface IOpenAndClose{
        void open();
    }
    
    interface Imple {
        void play();
    }
    
    class OpenAndClose implements IOpenAndClose{
        public Imple imple;
        
        //通过构造方法传入实现类
        public OpenAndClose(Imple imple){
            this.imple=imple;
        }
        public void open(){
            this.imple.play();
        }
    }
    
  • setter方法传递

    interface IOpenAndClose{
        void open();
    }
    
    interface Imple {
        void play();
    }
    
    class OpenAndClose implements IOpenAndClose{
        public Imple imple;
        
        //通过setter方法传入实现类
        public SetImple(Imple imple){
            this.imple=imple;
        }
        public void open(){
            this.imple.play();
        }
    }
    

    注意事项和细节

    • 底层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好.
    • 变量的声明类信息尽量是抽象类或接口,这样我们的变量引用和实际对象键,旧存在一个缓冲层,利于程序扩展和优化.
    • 继承时遵循里氏替换原则

里氏替换原则

  • 继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,但如果子类对这些已经实现的方法任意需修改,就会对整个继承体系造成破坏.

  • 继承在给程序设计带来方便的同时,也带来了弊端,比如使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类锁继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有设计到子类的功能都有可能长生故障.

  • 子类尽量不要重写父类的方法

  • 继承实际上让两个类耦合性增强,在适当情况下,可以通过聚合,组合,依赖来解决问题.

class A{
    //两数相减
    publci int func1(int num1 ,int num2){
        return num1 - num2;
    }
}

class B extends A{
    //无意将方法重写为两数相加
    publci int func1(int a ,int b){
        return a + b;
    }
    //B实现的功能,目的返回两数相减再加9,实际a+b+9
    publci int func2(int a ,int b){
        return func1(a,b)+9;
    }
}

通过聚合修改

class Base{}

class A extends Base{
    public void func1(int num1,int num2){return num1 + num2;}
}
//不在继承自A类
class B extends Base{
    private A a = new A();
    
    //任然重写了A的方法
    public int func1(int a,int b){return a+b;}
    
    public int func2(int a,int b){return func1(a+b)+9;}
    
    //任然可以使用原本的A的方法
    public int func3(int a,int b){return this.a.func1(a,b);}
}

开闭原则 ocp

  • 最基础,最重要的设计原则

  • 一个软件实体如类,模块和函数应该对扩展开放(==提供者==),对修改关闭(==使用者==).用抽象搭建跨框架,用实现扩展细节

  • 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化

  • 编程中遵循其他原则,以及使用设计模式的目的就是遵循拟开闭原则

    class 绘图类{
       fun(){ 
              //接收对象,判断类型运行绘图
        
          //运行1
          //运行2
          //当需要添加新,没有对修改关闭,需要新的运行3
              //运行3
       }
    }
    class Base{}
    class 绘图类1 extends Base{}
    class 绘图类2 extends Base{}
    //新增绘图类
    class 绘图类3 extends Base{}
    

    修改后

    class 绘图类{
       do{}
    }
    class Base{
        //继承需要实现的抽象方法
        public abstract  void do{}
    }
    class 绘图类1 extends Base{do{1}}
    class 绘图类2 extends Base{do{2}}
    //新增绘图类
    class 绘图类3 extends Base{do{3}}
    

迪米特原则

  • 一个对象应该对其他对象保持着最少的了解(例:下订单)

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

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

  • 简单定义:只与直接订单朋友通信

  • ==直接朋友==:每个对象都会与其他的对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系.耦合的方式很多,依赖,关联,组合,聚合等.其中,我们称出现成员变量,方法参数,方法返回值中的类为直接朋友,而出现在局部变量中的类不是直接的朋友.也就是说,陌生的类最好不要以局部变量的形式出现子类的内部

    
    
    public class Lishitihuan {
        public static void main(String[] args) {
            SchoolManager schoolManager = new SchoolManager();
            schoolManager.printAllEmployee(new CollegeManager());
        }
    }
    
    //学校总部员工
    class Employee {
        private String id;
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getId() {
            return id;
        }
    }
    
    //学院员工
    class CollegeEmployee {
        private String id;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    }
    
    //管理学院员工的管理类
    class CollegeManager {
        //返回学院的所有员工
        public List<Employee> getAllEmployee() {
            List<Employee> list = new ArrayList<Employee>();
            //添加10个员工
            for (int i = 0; i < 10; i++) {
                Employee emp = new Employee();
                emp.setId("学院员工" + i);
                list.add(emp);
            }
            return list;
        }
    }
    
    //SchoolManager的直接朋友类CollegeEmployee  
    
    //学校管理类
    class SchoolManager {
        //SchoolManager的直接朋友类: 返回值
        public List<CollegeEmployee> getAllEmployee() {
            List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
            
            //添加10个总部员工
            for (int i = 0; i < 5; i++) {
                CollegeEmployee emp = new CollegeEmployee();
                emp.setId("学校总部员工" + i);
                list.add(emp);
            }
            return list;
        }
        //输出学校总部员工的信息        //SchoolManager的直接朋友类: 参数
        public void printAllEmployee(CollegeManager collegeManager) {
            
            //获取学院员工  此处不是成员变量,返回值,参数,所有不是直接朋友
            //
            List<CollegeEmployee> list = this.getAllEmployee();
            System.out.println("-----------学院员工------------");
            for (CollegeEmployee employee : list) {
                System.out.println(employee.getId());
            }
            //学校总部员工
            List<Employee> list2 = new CollegeManager(). getAllEmployee();
            System.out.println("-----------学校总部员工------------");
            for (Employee employee : list2) {
                System.out.println(employee.getId());
            }
        }
    }
    

    修改后

    //管理学院员工的管理类
    class CollegeManager {
        //放回学院的所有员工
        public List<Employee> getAllEmployee() {
            List<Employee> list = new ArrayList<Employee>();
            //添加10个员工
            for (int i = 0; i < 10; i++) {
                Employee emp = new Employee();
                emp.setId("学院员工" + i);
                list.add(emp);
            }
            return list;
        }
        public void printEmployee(){
            //获取学院员工  此处不是成员变量,返回值,参数,所以不是直接朋友
            //
            List<Employee> list = this.getAllEmployee();
            System.out.println("-----------学校员工------------");
            for (Employee employee : list) {
                System.out.println(employee.getId());
            }
        }
    }
    
    //学校管理类
    class SchoolManager {
    
        //SchoolManager的直接朋友类: 返回值
        public List<CollegeEmployee> getAllEmployee() {
            List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
    
            //添加10个总部员工
            for (int i = 0; i < 5; i++) {
                CollegeEmployee emp = new CollegeEmployee();
                emp.setId("学校总部员工" + i);
                list.add(emp);
            }
            return list;
        }
    
        //输出学校总部员工的信息        //SchoolManager的直接朋友类: 参数
        public void printAllEmployee(CollegeManager sub) {
            sub.printEmployee();
            //学校总部员工
            List<CollegeEmployee> list2 =  getAllEmployee();
            System.out.println("-----------学校总部员工------------");
            for (CollegeEmployee employee : list2) {
                System.out.println(employee.getId());
            }
        }
    }
    

    迪米特法则的核心是==降低==类之间的耦合

合成复用原则

  • 尽量使用合成或聚合的方式,而不是继承

UML

  • 建模语言

    类之间的六种关系

    链接:https://blog.csdn.net/qq_29379115/article/details/78332487

    https://www.jianshu.com/p/ca8b1b08b420

    一、继承关系(泛化关系)

    ​ 继承指的是一个类(称为子类、子接口)继承另外的一个类(父类、父接口)的功能,并可以增加它自己的新功能的能力。在java中继承关系通过关键字extends明确标识,在设计时一般没有争议性。在UML类图设计中,继承用一条带空心三角箭头的实线表示,从子类指向父类,或者子接口指向父接口。

    img

二、实现关系

​ 实现指的是一个Class类实现interface接口(可以是多个)的功能,实现是类与接口之间最常见的关系。在java中实现关系通过implements明确标识,在设计时一般没有争议性。在UML类图设计中,实现用一条带空心三角箭头的虚线表示,从类指向实现的接口。

img

三、依赖关系

​ 简单地理解,依赖就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性、临时性、非常弱的,但是类B的变化会影响到类A。比如某人要过河,需要借用一条船,此时人与船之间的关系就是依赖。表现在代码层面为,类B作为参数被类A在某个method方法中使用。在UML类图设计中,依赖关系用由类A指向类B的带箭头虚线表示。

img

四、关联关系

​ 关联体现的是两个类之间语义级别的强依赖关系,比如我和我的朋友,这种关系比依赖更强、不存在依赖关系的偶然性、关系也不是临时性的,一般是长期性的,而且双方的关系一般是平等的。关联可以是单向、双向的。表现在代码层面为,被关联类B以类的属性的形式出现在关联类A中,也可能是关联类A引用了一个类型为被关联类B的全局变量。在UML类图设计中,关联关系用由关联类A指向被关联类B的带箭头实线表示,在关联的两端可以标注关联双方的角色和多重性标记。

img

五、聚合关系

​ 聚合是关联关系的一种特例,它体现的是整体与部分的关系,即has-a的关系。此时整体与部分之间是可分离的,它们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享。比如计算机与CPU、公司与员工的关系等,比如一个航母编队包括航空母舰、驱逐护卫舰、舰载飞机及核动力攻击潜艇等。表现在代码层面,和关联关系是一致的,只能从语义级别来区分。在UML类图设计中,聚合关系以空心菱形加实线箭头表示。

img

六、组合关系

​ 组合也是关联关系的一种特例,它体现的是contains-a的关系,这种关系比聚合更强,也成为强聚合。它同样体现整体与部分间的关系,但此时整体与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束,比如人和人的大脑。表现在代码层面,和关联关系是一致的,只能从语义级别来区分。在UML类图设计中,组合关系以实心菱形加实线箭头表示。

img

总结:

​ 对于继承、实现这两种关系没多少疑问,它们体现的是类和类、类与接口之间的纵向关系。其他的四种关系体现的是类与类、或者类与接口之间的引用、横向关系,是比较难区分的,有很多事物间的关系要想准确定位是很难的。前面也提到,这四种关系都是语义级别的,所以从代码层面并不能完全区分各种关系,但总的来说,后几种关系所表现的强弱程度依次为:组合>聚合>关联>依赖。

装饰者模式

  • 装饰着模式:动态的将星星呢附加到对象上.在对象功能扩展方面,它比继承更有弹性,转世这模式也体现了开闭原则(ocp)

  • 这里提到的==动态的将新功能附加到对象和ocp原则==,

  • Component:主体,比如衣服

  • ConcreteComponent:具体的主类

  • Decorator:装饰者

[图片上传失败...(image-81bd42-1595647854838)]

//看idea
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355