浅谈java设计模式的原则

纯属个人拙见,欢迎指点

物极必反的道理大家都明白,这些原则并不是要我们刻板的去遵守。开发需要遵循实际条件,不能按部就班的来完成一个项目。但这些原则,能帮我们在编码项目过程中,避开不必要的错误,提升项目的可维护性。

设计模式有六大原则,分别是:

  • 开闭原则
  • 里氏代换原则
  • 单一职责原则
  • 依赖倒置原则
  • 接口隔离原则
  • 迪米特法则

开闭原则

对扩展开放,对修改关闭。当软件有新功能,新变化时,我们应该尽可能去增加他的行为方法来改变,而不是通过修改现有代码来满足。这就是为什么,好的软件项目通常具有非常棒的扩展性。

工厂模式就遵守这一原则

编程的总原则是:低耦合,高内聚。

里氏代换原则

子类可以去扩展父类,但请尽量避免重写父类的方法,除非父类是一个基类。因为会出现,当你在子类需要使用父类的一个方法时,而此时这个方法刚好被子类重写,就可能会出现问题。

代码说明:

//父亲喜欢读军事书籍
public class Father{

    public void readBook(){
        System.out.println("读军事书籍");
    }
}

/*儿子除了喜欢读军事书籍外,还喜欢读科幻小说,此时就需要扩展读科幻小说的方法。在这里,当子类重写了父类的方法后,他就无法使用父类的readBook()方法。
*/
public class Son extends Father{

    public void readBook(){
        System.out.println("读科幻小说");
    }
}

//家庭
public class Family{
    public static void main(String[] args){
        Son son = new Son();
        son.readBook();
    }
}

输出结果只有:读科幻小说

单一职责原则

好比生活中的各个职业,负责各种的岗位,比如交警,职责上只负责交通管理,他不参与消防等其他工作的道理相同。

代码说明:

public class Person{
    //管理交通
    public void manageTraffic(){

    }

    //消防工作
    public void controlFire(){

    }

    //救治病人
    public void treatmentPatient(){

    }
}

如果我们这样写,来描述不同人的不同职责,那么会发生什么么?

//社会
public class Social{

    public static void main(String[] args){

        Person person1 = new Person();
        //此时person1是交警
        person.manageTraffic();

        Person person2 = new Person();
        //此时person2是消防员
        person2.controlFire();

        Person person3 = new Person();
        //此时person3是医生
        person3.controlFire();
    }
}

这里Person类里面,不同职业的人,有且我们只用到了属于他的职能,但其他不相关的职能也被放置在里面的话,可能被滥用

就存在违反单一职责。

遵循这一原则的话,我们需要把不同对象独立出来,例如交警

//这是一个交警类
public class TrafficPolice{
    //管理交通
    public void manageTraffic(){
        System.out.println("管理交通");
    }

}

有时候不要为了灵活而取巧,在实际开发中,代码的往往很复杂,遵循这一原则你可以方便的维护你的代码,减少代码的复杂性。

依赖倒置原则

中心思想就是面向接口编程,就是如果类需要依赖对象,而依赖的作用是为了使用该对象的方法,那么我们考虑用依赖接口的来达到这个目的。

相当拗口,举个人穿衣服的例子。

//外套类
public class Coat{

    //穿上的类型
    public void onType(){
        System.out.println("外套穿上");
    }
}

//人类
public class Person{

    //此处和外套进行了依赖
    public void wear(Coat coat){
        System.out.println(coat.onType());
    }
}

//穿衣
public class WearClothing{

    public static void main(String[] args){
        Person person = new Person();
        person.wear(new Coat());
    }
}

结果为:外套穿上

但是,我们穿衣打扮这件事情,不可能只穿外套,而不穿内衣裤、鞋子。

//鞋子类
public class Shose{

    //穿上的类型
    public void onType(){
        System.out.println("鞋子穿上");
    }
}

不难看出,当我们需要穿上鞋子时,必须在人这个类里修改代码,你需要再添加鞋子的依赖,否则,我们没法穿上。即改为:

public class Person{

    //此处和外套进行了依赖
    public void wear(Coat coat){
        System.out.println(coat.onType());
    }

    //此处和鞋子进行了依赖
    public void wear(Shose shose){
        System.out.println(shose.onType());
    }
}

//穿衣
public class WearClothing{

    public static void main(String[] args){
        Person person = new Person();
        person.wear(new Coat());
        person.wear(new Shose());
    }
}

结果为:外套穿上
    鞋子穿上

发现没有,如果当依赖对象的实现越多,Person类修改的也需要越多,但Person这个类是在高层,它负责业务逻辑的处理,应该去依赖抽象(抽象类或借口)来减少这些耦合。

这里的高层指事件的发起处(人),底层指最后的现实处(各种衣物)。

因为都属于衣物,所以我们可以定义一个IClothing的接口。

//穿衣打扮接口
interface IClothing{

    public void onType();
}

让底层的Coat、Shoes去具体现实各自的IClothing这个接口。

//外套
public class Coat implements IClothing{

    public void onType(){
        System.out.println("外套穿上");
    }
}

//鞋子类
public class Shose implements IClothing{

    public void onType(){
        System.out.println("鞋子穿上");
    }
}

在Person这个类里,我们依赖接口,而不是底层

public class Person {

    public void wear(IClothing iClothing){

        System.out.println(iClothing.onType());
    }
}

最后,我们发现,只要传入接口的实现,而不需要在高层(Person)里修改代码,就能得到我们要的结果。

public class WearClothing{

    public static void main(String[] args){
        Person person = new Person();
        person.wear(new Coat());
        person.wear(new Shose());
    }
}

结果为:外套穿上
    鞋子穿上

说了这么多,我们要明白的一件事情就是这么做的理由,高层的东西之所以要避免去修改,是因为它是事件逻辑操作入口,一旦修改,极有可能造成程序其他地方用到此高层的地方出错,而依赖抽象可以很好的解决这种耦合。

接口隔离原则

高层应只依赖对它有用的接口

举个人的行为习惯的例子

inteface Action {

    //吃
    public void eat();
    //睡
    public void sleep();
    //喝
    public void drink();

    //谈话
    public void talk();
    //工作
    public void work();
    //购物
    public void shopping();
}

//女人
public class Women{
    Action action;

    public Women(Action action){
        this.action = action;
    }

    public void hasAction(){
        action.eat();
        action.sleep();
        action.drink();
        action.talk();
        action.work();
        action.shopping();
    }

}

public class WomenAction implements Action{
    //吃
    public void eat(){
        System.out.println("吃");
    };
    //睡
    public void sleep(){
        System.out.println("睡");
    };
    //喝
    public void drink(){
        System.out.println("喝");
    };

    //谈话
    public void talk(){
        System.out.println("谈话");
    };
    //工作
    public void work(){
        System.out.println("工作");
    };
    //购物
    public void shopping(){
        System.out.println("购物");
    };

}

public class Baby{
    Action action;

    public Baby(Action action){
        this.action = action;
    }

    public void hasAction(){
        action.eat();
        action.sleep();
        action.drink();
    }

}

//婴儿
public class BabyAction implements Action{
    //吃
    public void eat(){
        System.out.println("吃");
    };
    //睡
    public void sleep(){
        System.out.println("睡");
    };
    //喝
    public void drink(){
        System.out.println("喝");
    };

    //婴儿不会谈话,工作,购物,但是由于实现了Action这个接口,它的所有方法都必须被重写
    public void talk(){

    };

    public void work(){

    };

    public void shopping(){

    };

}

public class Behaviour{

    public static void main(String[] args){

        Women women = new Women(new WomenAction());
        women.hasAction();

        Baby baby = new Baby(new BabyAction())
        baby.hasAction();

    }
}

结果为:吃
    睡
    喝
    谈话
    工作
    购物
    吃
    睡
    喝

看到婴儿的行为习惯实现,类的有几个方法是没被用到的,这就造成了代码的臃肿 ,这时就需要对接口进行拆分隔离,使得WomenAction和BabyAction要实现接口最小。讲Action进行拆分,然后再各自实现需要的接口。


//基础的行为接口
inteface IBaseAction {

    //吃
    public void eat();
    //睡
    public void sleep();
    //喝
    public void drink();


}

//女人的行为接口
inteface IWomenAction{
    //谈话
    public void talk();
    //工作
    public void work();
    //购物
    public void shopping();
}

//女人
public class Women{
    IBaseAction iBaseAction;
    IWomenAction iWomenAction;

    public Women(IBaseAction iBaseAction,IWomenAction iWomenAction;){
        this.iBaseAction = iBaseAction;
        this.iWomenAction = iWomenAction;
    }

    public void hasAction(){
        iBaseAction.eat();
        iBaseAction.sleep();
        iBaseAction.drink();

        iWomenAction.talk();
        iWomenAction.work();
        iWomenAction.shopping();
    }

}

public class WomenAction implements IBaseAction,IWomenAction{
    //吃
    public void eat(){
        System.out.println("吃");
    };
    //睡
    public void sleep(){
        System.out.println("睡");
    };
    //喝
    public void drink(){
        System.out.println("喝");
    };

    //谈话
    public void talk(){
        System.out.println("谈话");
    };
    //工作
    public void work(){
        System.out.println("工作");
    };
    //购物
    public void shopping(){
        System.out.println("购物");
    };

}

public class Baby{
    IBaseAction iBaseAction;

    public Baby(IBaseAction iBaseAction){
        this.iBaseAction = iBaseAction;
    }

    public void hasAction(){
        iBaseAction.eat();
        iBaseAction.sleep();
        iBaseAction.drink();
    }

}

//婴儿
public class BabyAction implements IBaseAction{
    //吃
    public void eat(){
        System.out.println("吃");
    };
    //睡
    public void sleep(){
        System.out.println("睡");
    };
    //喝
    public void drink(){
        System.out.println("喝");
    };



}

public class Behaviour{

    public static void main(String[] args){
        Women women = new Women(new WomenAction());
        women.hasAction();

        Baby baby = new Baby(new BabyAction())
        baby.hasAction();

    }
}

结果一样 

  • 接口要小没错,能提高程序的灵活性,但记住灵活的东西,往往需要付出复杂的代价。所以接口小的要控制好。

迪米特法则

对象与对象之间应尽量减少耦合。

就是不要借用别人的地方做本该属于自己的事情。

又称为最少知道原则。

举个例子,小张和小陈是好朋友,小陈总是会邀请小张去吃饭、唱歌、烫头。


//小张
public class Z{

    public void sing(){
        System.out.println("唱歌");
    }

    public void eat(){
        System.out.println("吃饭");
    }

    public void perm(){
        System.out.println("烫头");
    }

}

//小陈
public class C{

    public void inviteZ(Z z ){
        z.sing();
        z.eat();
        z.perm();
    }
}

//娱乐
public class Entertainment{

    public static void main(String[] args){
        C c = new C();
        c.inviteZ();
    }

}

结果为:唱歌
    吃饭
    烫头

我们看到在小陈这个类里面他调用了过多的小张方法,也就是小张把把自己的方法公开的太多,这样就大大增加了两者的耦合性,也就是小陈过多的知道小张的爱好。

但朋友间也是需要保持一定距离,才会有舒适感。所以,小张应该只暴露一个方法来给小陈,告诉他们之间有哪些娱乐活动。

//小张
public class Z{

    //更改为私有
    private void sing(){
        System.out.println("唱歌");
    }

    private void eat(){
        System.out.println("吃饭");
    }

    private void perm(){
        System.out.println("烫头");
    }

    //只暴露一个方法给小陈调用
    public void entertainmentWithC(){
        sing();
        eat();
        perm();
    }
}

//小陈
public class C{

    public void inviteZ(Z z ){
        z.entertainmentWithC();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值