写在后面

  • 记录学习设计模式的笔记
  • 进步对设计模式的灵活运用

学习地址

https://www.bilibili.com/vide...

https://www.bilibili.com/vide...

参考文章

http://c.biancheng.net/view/1...

我的项目源码
https://gitee.com/zhuang-kang/DesignPattern

3,软件设计准则

在软件开发中,为了进步软件系统的可维护性和可复用性,减少软件的可扩展性和灵活性,程序员要尽量依据6条准则来开发程序,从而进步软件开发效率、节约软件开发老本和保护老本。

3.1 开闭准则

对扩大凋谢,对批改敞开。在程序须要进行拓展的时候,不能去批改原有的代码,实现一个热插拔的成果。简言之,是为了使程序的扩展性好,易于保护和降级。

想要达到这样的成果,咱们须要应用接口和抽象类。

因为形象灵活性好,适应性广,只有形象的正当,能够根本放弃软件架构的稳固。而软件中易变的细节能够从抽象派生来的实现类来进行扩大,当软件须要发生变化时,只须要依据需要从新派生一个实现类来扩大就能够了。

3.2 里氏代换准则

里氏代换准则是面向对象设计的根本准则之一。

里氏代换准则:任何基类能够呈现的中央,子类肯定能够呈现。艰深了解:子类能够扩大父类的性能,但不能扭转父类原有的性能。换句话说,子类继承父类时,除增加新的办法实现新增性能外,尽量不要重写父类的办法。

如果通过重写父类的办法来实现新的性能,这样写起来尽管简略,然而整个继承体系的可复用性会比拟差,特地是使用多态比拟频繁时,程序运行出错的概率会十分大。

里氏代换准则谬误示范

package com.zhuang.principle.liskov;/** * @Classname Liskov * @Description 里氏代换准则谬误示范 * @Date 2021/3/15 13:58 * @Created by dell */public class Liskov {    public static void main(String[] args) {        A a = new A();        System.out.println("11-3=" +a.fun1(11,3));        System.out.println("11-8=" +a.fun1(11,8));        System.out.println("===================");        B b = new B();        System.out.println("11-3="+b.fun1(11,3));        System.out.println("1-8="+b.fun1(1,8));        System.out.println("11+3+9="+b.fun2(11,3));    }}class A{    //返回两个数的差    public int fun1(int num1,int num2){        return num1-num2;    }}//B类继承A 减少新性能,实现两个数相加,而后和9求和class B extends A{    @Override    public int fun1(int a, int b) {        return a+b;    }    public int fun2(int a, int b) {        return fun1(a,b)+9;    }}

里氏代换准则正确示范

package com.zhuang.principle.liskov;/** * @Classname Liskov2 * @Description 里氏代换准则 * @Date 2021/3/15 14:13 * @Created by dell */public class Liskov2 {    public static void main(String[] args) {        Base base = new Base();        base.add(5,6);        base.sub(6,2);        Sub sub = new Sub();        sub.mul(5,6);        sub.div(10,2);    }}class Base {    //通用加法运算    public void add(int a, int b) {        System.out.println(a + "+" + b + "=" + (a + b));    }    //通用减法运算    public void sub(int a, int b) {        System.out.println(a + "-" + b + "=" + (a - b));    }}class Sub extends Base {    //子类特有乘法运算    public void mul(int a, int b) {        System.out.println(a + "*" + b + "=" + (a * b));    }    //子类特有除法运算    public void div(int a, int b) {        System.out.println(a + "/" + b + "=" + (a / b));    }}

3.3 依赖倒转准则

高层模块不应该依赖低层模块,两者都应该依赖其形象;形象不应该依赖细节,细节应该依赖形象。简略的说就是要求对形象进行编程,不要对实现进行编程,这样就升高了客户与实现模块间的耦合。

依赖倒转准则谬误示范

package com.zhuang.principle.inversion;/** * @Classname DependenceInversion1 * @Description 依赖倒转准则谬误示范 * @Date 2021/3/15 13:20 * @Created by dell */public class DependenceInversion1 {    public static void main(String[] args) {        Person person = new Person();        person.receive(new Email());        person.receive(new WeiXin());    }}//定义接口interface IReceiver{    public String getInfo();}class WeiXin implements IReceiver{    @Override    public String getInfo() {        return "发送微信音讯...";    }}class Email implements IReceiver{    @Override    public String getInfo() {        return "发送邮件音讯...";    }}//对接口的依赖class Person{    public void receive(IReceiver receiver){        System.out.println(receiver.getInfo());    }}

依赖倒转准则正确示范

package com.zhuang.principle.inversion;/** * @Classname DependenceInversion2 * @Description 依赖倒转准则正确示范 * @Date 2021/3/15 13:27 * @Created by dell */public class DependenceInversion2 {    public static void main(String[] args) {        Client client = new Client();        client.receive(new Emailiml());        client.receive(new WXimpl());    }}interface IReceive{    public void printInfo(Integer uid);}class WXimpl implements IReceive {    @Override    public void printInfo(Integer uid) {        System.out.println("发送微信音讯"+uid);    }}class Emailiml implements IReceive {    @Override    public void printInfo(Integer uid) {        System.out.println("发送邮件信息"+uid);    }}class Client{    public void receive(IReceive receive){        receive.printInfo(12345);    }}

面向对象的开发很好的解决了这个问题,个别状况下形象的变动概率很小,让用户程序依赖于形象,实现的细节也依赖于形象。即便实现细节一直变动,只有形象不变,客户程序就不须要变动。这大大降低了客户程序与实现细节的耦合度。

3.4 接口隔离准则

客户端不应该被迫依赖于它不应用的办法;一个类对另一个类的依赖应该建设在最小的接口上。

接口隔离准则

package com.zhuang.principle.segregation;/** * @Classname Sergregation * @Description 接口隔离准则 * @Date 2021/3/15 13:02 * @Created by dell */public class Sergregation {    public static void main(String[] args) {        C c = new C();        c.depend1(new A());        c.depend2(new A());//C类通过接口去依赖A类        c.depend3(new A());        System.out.println("=======================");        D d = new D();        d.depend1(new B());        d.depend4(new B());//D类通过接口去依赖B类        d.depend5(new B());    }}interface interface1{    void operation1();}interface interface2{    void operation2();    void operation3();}interface interface3{    void operation4();    void operation5();}class A implements interface1,interface2{    @Override    public void operation1() {        System.out.println("A 实现了operation1.....");    }    @Override    public void operation2() {        System.out.println("A 实现了operation2......");    }    @Override    public void operation3() {        System.out.println("A 实现了operation3......");    }}class B implements interface1,interface3{    @Override    public void operation1() {        System.out.println("B 实现了operation1.....");    }    @Override    public void operation4() {        System.out.println("B 实现了operation4.....");    }    @Override    public void operation5() {        System.out.println("B 实现了operation5.....");    }}//C类通过接口interface1,interface2依赖应用A类 只会应用到1,2,3办法class C{    public void depend1(interface1 i){        i.operation1();    }    public void depend2(interface2 i){        i.operation2();    }    public void depend3(interface2 i){        i.operation3();    }}//D类通过接口interface1,interface3 依赖应用B类,用到1,4,5办法class D{    public void depend1(interface1 i){        i.operation1();    }    public void depend4(interface3 i){        i.operation4();    }    public void depend5(interface3 i){        i.operation5();    }}

3.5 迪米特法令

迪米特法令又叫起码常识准则。

只和你的间接敌人交谈,不跟“陌生人”谈话(Talk only to your immediate friends and not to strangers)。

其含意是:如果两个软件实体毋庸间接通信,那么就不该当产生间接的互相调用,能够通过第三方转发该调用。其目标是升高类之间的耦合度,进步模块的绝对独立性。

迪米特法令中的“敌人”是指:以后对象自身、以后对象的成员对象、以后对象所创立的对象、以后对象的办法参数等,这些对象同以后对象存在关联、聚合或组合关系,能够间接拜访这些对象的办法。

上面看一个例子来了解迪米特法令

【例】明星与经纪人的关系实例

明星因为全身心投入艺术,所以许多日常事务由经纪人负责解决,如和粉丝的见面会,和媒体公司的业务洽淡等。这里的经纪人是明星的敌人,而粉丝和媒体公司是陌生人,所以适宜应用迪米特法令。

类图如下:

代码如下:

明星类(Star)

public class Star {    private String name;    public Star(String name) {        this.name=name;    }    public String getName() {        return name;    }}

粉丝类(Fans)

public class Fans {    private String name;    public Fans(String name) {        this.name=name;    }    public String getName() {        return name;    }}

媒体公司类(Company)

public class Company {    private String name;    public Company(String name) {        this.name=name;    }    public String getName() {        return name;    }}

经纪人类(Agent)

public class Agent {    private Star star;    private Fans fans;    private Company company;    public void setStar(Star star) {        this.star = star;    }    public void setFans(Fans fans) {        this.fans = fans;    }    public void setCompany(Company company) {        this.company = company;    }    public void meeting() {        System.out.println(fans.getName() + "与明星" + star.getName() + "见面了。");    }    public void business() {        System.out.println(company.getName() + "与明星" + star.getName() + "洽淡业务。");    }}

3.6 合成复用准则

合成复用准则是指:尽量先应用组合或者聚合等关联关系来实现,其次才思考应用继承关系来实现。

通常类的复用分为继承复用和合成复用两种。

继承复用尽管有简略和易实现的长处,但它也存在以下毛病:

  1. 继承复用毁坏了类的封装性。因为继承会将父类的实现细节裸露给子类,父类对子类是通明的,所以这种复用又称为“白箱”复用。
  2. 子类与父类的耦合度高。父类的实现的任何扭转都会导致子类的实现发生变化,这不利于类的扩大与保护。
  3. 它限度了复用的灵活性。从父类继承而来的实现是动态的,在编译时曾经定义,所以在运行时不可能发生变化。

采纳组合或聚合复用时,能够将已有对象纳入新对象中,使之成为新对象的一部分,新对象能够调用已有对象的性能,它有以下长处:

  1. 它维持了类的封装性。因为成分对象的外部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。
  2. 对象间的耦合度低。能够在类的成员地位申明形象。
  3. 复用的灵活性高。这种复用能够在运行时动静进行,新对象能够动静地援用与成分对象类型雷同的对象。

上面看一个例子来了解合成复用准则

【例】汽车分类管理程序

汽车按“动力源”划分可分为汽油汽车、电动汽车等;按“色彩”划分可分为红色汽车、彩色汽车和红色汽车等。如果同时思考这两种分类,其组合就很多。类图如下:

从下面类图咱们能够看到应用继承复用产生了很多子类,如果当初又有新的动力源或者新的色彩的话,就须要再定义新的类。咱们试着将继承复用改为聚合复用看一下。


写在最初

  • 如果我的文章对你有用,请给我点个,感激你!
  • 有问题,欢送在评论区指出!