面向对象设计的三大特点与五大基本原则

面向对象设计

一、面向对象设计的三个基本要素

面向对象的三个基本特征是:封装、继承、多态。

1. 封装性

封装是一种信息隐蔽技术,他体现于类的说明,是都西昂重要的特性。

封装使得数据和操作数据的方法封装成一个整体,想成为独立性很强的模块,使得用户只能看到对象的外部特征,内部是看不到的。

简而言之就是说,封装使对象的设计者与对象的使用者分开,使用者只要知道对象可以做什么就可以了,无需知道具体是怎么实现的。借助封装有助于提高类和系统的安全性。

例:属性私有,get/set方法,有参构造 ,方法

2.继承性

继承是一种由已有类创建子类的机制,利用继承,可以先创建一个共有属性的一般类,根据这个类再创建具有特殊属性的子类,被继承的类成为父类,当然子类也可以成为父类来继续向下扩展。

例:子承父类

3.多态

同一个信息被不同的对象接收到时可能产生不同的行为,这就是多态性。有继承(接口)有重写,父类引用指向子类对象,就会产生多态。多态可以改善程序的组织架构,提高程序的可扩展性。

例:父类指向子类对象,子类重写父类方法

二、面向对象设计的五个基本设计原则

面向对象设计的五个基本设计原则是:单一职责原则、开放封闭原则、里氏替换原则、依赖倒置原则、接口隔离原则

1.单一职责原则

就一个类而言,应该只专注于做一件事和仅有一个引起它变化的原因。

也可以理解为引用变化的原因,当你发现有两个变化会要求我们修改这个类,那么你就要考虑撤分这个类了。因为职责是变化的一个轴线,当需求变化时,该变化会反映类的职责的变化。

“就像一个人身兼数职,而这些事情相互关联不大,甚至有冲突,那他就无法很好的解决这些职责,应该分到不同的人身上去做才对。”

interface Modem//
{
    public void dial(string pno);//拨号
    public void hangup();//挂断
    public void send(char c);//发送
    public void recv();//接受
}
//应改为
interface DataChannel//数据通道
{
    public void send(char c);
    public void recv();
}
interface Connection//链接
{
    public void dial(string pno);
    public void hangup();
}

 

优点:消除耦合,减小因需求变化引起代码僵化

2·开放封闭原则

其核心思想是:软件实体应该是可扩展的,而不可修改的。也就是,对扩展开放,对修改封闭。开放封闭原则主要体现在两个方面 1、对扩展开放,意味着有新的需求或者变化时,可以对现有代码进行扩展,以适应新的情况。 2、对修改封闭,意味着一旦设计完成,就可以独立完成其工作,而不要对其进行任何尝试的修改。

public interface Bark {
    public void bark();
}
public class Awaw implements Bark{
    @Override
    public void bark() {
        System.out.println("嗷嗷~~");
    }
}
public class Zhazha implements Bark{
    @Override
    public void bark() {
        System.out.println("喳喳~~");
    }
}
public abstract class Bird {
    //声明属性
    private Bark bark;//接口的对象
    //设置set属性
    public void setBark(Bark bark) {
        this.bark = bark;
    }
    /**
     * 鸟叫的方法
     */
    public void birdBark(){
        bark.bark();
    }
}
public class Test {
    public static void main(String[] args) {
        //测试
        //声明鸟的叫声
        Bark awaw = new Awaw();
        Bark zhazha = new Zhazha();
        //bird对象
        Bird rocketBird = new RocketBird();
        rocketBird.setBark(awaw);
        Bird splitBird = new SplitBird();
        splitBird.setBark(zhazha);
    }
}

 

优点:

1、降低程序各部分之间的耦合性,使程序模块互换成为可能; 2、使软件各部分便于单元测试,通过编制与接口一致的模拟类(Mock),可以很容易地实现软件各部分的单元测试; 3、利于实现软件的模块的呼唤,软件升级时可以只部署发生变化的部分,而不会影响其它部分;

3·里氏替换原则

核心思想:子类必须能够替换其父类。这一思想体现为对继承机制的约束规范,只有子类能够替换父类时才能保证系统在运行期内识别子类,这是保证继承复用的基础。在父类和子类的具体行为中,必须严格把握继承层次中的关系和特征,将父类替换为子类,程序的行为不会发生任何变化。同时,这一约束反过来则是不成立的,子类可以替换父类,但是父类不一定能替换子类。

对于这个原则,通俗一些的理解就是,父类的方法都要在子类中实现或者重写。

public abstract class Bird {
    /**
     * 飞的方法
     */
    void fly(){
        System.out.println("弹跳-飞");
    }
    /**
     * 叫的方法
     */
    void call(){
        System.out.println("嗷~!");
    }
    /**
     * 攻击的抽象方法
     */
    abstract void attack();
}
public class RocketBird extends Bird {
    @Override
    void attack() {
        System.out.println("加速冲刺");
    }
}
public class SplitBird extends Bird{
​
    @Override
    void attack() {
        System.out.println("分裂攻击");
    }
}
public class Test {
    public static void main(String[] args) {
        Bird splitBird = new SplitBird();
        Bird rocketBird = new RocketBird();
        splitBird.attack();
        rocketBird.attack();
    }
}

 

优点:

1、保证系统或子系统有良好的扩展性。只有子类能够完全替换父类,才能保证系统或子系统在运行期内识别子类就可以了,因而使得系统或子系统有了良好的扩展性。 2、实现运行期内绑定,即保证了面向对象多态性的顺利进行。这节省了大量的代码重复或冗余。避免了类似instanceof这样的语句,或者getClass()这样的语句,这些语句是面向对象所忌讳的。 3、有利于实现契约式编程。契约式编程有利于系统的分析和设计,指我们在分析和设计的时候,定义好系统的接口,然后再编码的时候实现这些接口即可。在父类里定义好子类需要实现的功能,而子类只要实现这些功能即可。

4·依赖倒置原则

其核心思想是:依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。

反面例子:

img 缺点:耦合太紧密,Light发生变化将影响ToggleSwitch。

解决方法:

img

优点:更为通用、更为稳定。

优点:

使用传统过程化程序设计所创建的依赖关系,策略依赖于细节,这是糟糕的,因为策略受到细节改变的影响。依赖倒置原则使细节和策略都依赖于抽象,抽象的稳定性决定了系统的稳定性。

5·接口隔离原则

其核心思想是:使用多个小的专门的接口,而不要使用一个大的总接口。

“不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。”

img

img

 

posted @ 2021-07-31 11:15  RenVei  阅读(1289)  评论(0编辑  收藏  举报