设计模式的领悟

目录:

  1. 设计模式之单一原则
  2. 设计模式之里氏替换原则
  3. 设计模式之依赖倒置原则
  4. 设计模式之接口隔离原则
  5. 设计模式之迪米特法则
  6. 设计模式之权衡法:开闭原则 

单一原则

单一,从字面上看都能理解,就是单一,一个类只负责一项职责,实现高内聚,低耦合。为什么要这样做呢?稍微有点经验的猿猴都尝到过单一原则的好处,一个类承担的职责越多,在整个项目中,就会出现到处都有它,超高耦合,举个栗子!!!类A  负责两个职责:A1  A2 A3职责,如果有一天A2职责需求发生改变,你就要去修改A了,A3有变化,又要修改A类,频繁的这种操作,可能会导致原本运行正常A1职责的功能发生故障。所以,我们要把A分开两个类来去实现,专业的人,干专业的事情,专业的人干出来的事情出错率肯定比啥都会不太专业的干的要好。

代码举例

public class Person {
    private String name;
    private String age;
    private String gender;
    //get  set 方法

    public boolean addPerson(Person person) {
        //添加人逻辑
        return true;
}

    public boolean deleterPerson(Person person) {
        //删除人逻辑
        return true;
}

如果你自己随意的话,当然程序也可以跑,但是仔细考虑这个类的设计,是有问题的,用户的属性和其他的操作,放到一起?这个是一个程序猿该有的思维么?这严重违背了我们第一项原则,所以在写这类代码的时候,我们应该将操作行为抽取出来,新建一个类去管理这个人。

总结:专业的人,做专业的事情,类的设计,尽量做到能写好了再也不需要做修改,拿起来就用!!!

里氏替换原则

上代码

public class Substruction {

        public int reduce(int a, int b) {
            return a - b;
        }
    }

    public class Addition extends Substruction {

        @Override
        public int reduce(int a, int b) { //错误案例,这种代码写法是严重破坏了,里氏替换原则
            //重写了reduce  修改了reduce 逻辑
            return a + a - b;
        }
        
        //遵循里氏替换原则
        public int reduce(int a, int b,int c) {
            //重载了 Substruction
            return a + a - b-c;
        }

        public int add(int a, int b) {

            return a + b;
        }
    }

总结:你可以集成,拥有你老爸的能力,甚至升级,扩展其他能力,但是,不要去改变你老爸已有的能力。

你可能怀疑的说,我就这样写,程序照样跑的飞起,好吧,你继续!!

依赖倒置原则

上代码

public void test() throws Exception {
        Book book = new Book();
        Me me = new Me();
        me.purchasing(book);
    }

    public class Me {
        void purchasing(Book book) {
            System.out.println("我购买了" + book.result());
        }
    }
    public class Book {
        public String result() {
            return "一本书";
        }
    }

      假如有一天,需求发生变化,我要买的不是书,是机器人,这个时候你会发现,暂时还办不到,要改代码,如果需求又变化了,又得改代码,这肯定不是好的设计!原因是应为你和书太依赖了,耦合性太高了,必须想办法降低书和你之间的耦合度

上代码

public void test() throws Exception {
        Book book = new Book();
        Robot robot = new Robot();
        Me me = new Me();
        me.purchasing(book);
        me.purchasing(robot);
    }
    public interface IPurchase {
        public abstract String result();
    }
    public class Me {
        void purchasing(IPurchase purchase) {
            System.out.println("我购买了" + purchase.result());
        }
    }
    public class Book implements IPurchase {
        @Override
        public String result() {
            return "一本书";
        }
    }
    public class Robot implements IPurchase {
        @Override
        public String result() {
            return "机器人";
        }
    }

上面代码遵循依赖倒置原则

看,这个时候,你不可能只能买书,你只跟买买买有关系,实现一下买的接口,你想买什么买什么!很灵活。

接口隔离原则

上代码

 //调料接口
    public interface ISeasoning {
        //加盐
        public abstract String withSalt();
        //加油
        public abstract String refuel();
        //加酱油
        public abstract String soySauce();
        //加醋
        public abstract String vinegar();
        //加辣椒酱
        public abstract String chiliSauce();

    }
    //炒青菜
    public class Vegetables implements ISeasoning{
        @Override
        public String withSalt() {
            return "加盐";
        }
        @Override
        public String refuel() {
            return "加油";
        }
        @Override
        public String vinegar() {
            return "加酱油";
        }
        @Override
        public String soySauce() {
            return "";
        }
        @Override
        public String chiliSauce() {
            return "";
        }

    }

看上面代码,老大,我炒个青菜,不用加那么多调料的,我不需要加醋,加辣椒!这种设计过于臃肿,显然不是好的设计

那么我们简单设计一下,符合我们接口隔离的原则!

//基本调料
    public interface IBasic {
        //加盐
        public abstract String withSalt();
        //加油
        public abstract String refuel();
        //加酱油
        public abstract String soySauce();

    }

    //酸辣
    public interface IHotAndSour {
        //加醋
        public abstract String vinegar();
        //加辣椒酱
        public abstract String chiliSauce();
    }

    //炒青菜
    public class Vegetables implements IBasic{
        @Override
        public String withSalt() {
            return "加盐";
        }
        @Override
        public String refuel() {
            return "加油";
        }
        @Override
        public String soySauce() {
            return "加醬油";
        }
    }

    //凉拌青瓜
    public class CucumberSalad implements IBasic,IHotAndSour{

        @Override
        public String withSalt() {
            return "加盐";
        }
        @Override
        public String refuel() {
            return "加油";
        }
        @Override
        public String soySauce() {
            return "加醬油";
        }

        @Override
        public String vinegar() {
            return "加醋";
        }

        @Override
        public String chiliSauce() {
            return "加辣椒酱";
        }
    }

我们拆分了接口,一个是基本的调料,一个是酸辣接口,这个时候,你做菜就好做选着了!不要建立庞大臃肿的接口,尽量细化他们

,这样你才能根据自己的业务作出选择这个跟前面的单一原则很类似,其实是有区别的,单一是职责单一,接口是注重对需求抽象。

但是接口也不能设计的太小了,这样不仅没有隔离的效果,还变的复杂了,设计一定要适度。尽量用最少的方法,完成所有的需求。

接口设计的时候,一定要花些时间去思考,这样才能把握住这一原则!!!

迪米特法则

这个我是这样理解的:这是一个特务法则,最好不要跟任何人有关系,也尽量不要让任何人了解你,你只跟你的唯一上级联系,如果这是一个人,而且还是程序猿,那他一定会猝死,但是如果放到程序里,这样是很好的降低了类与类之间的耦合。我们变成的秘籍不就是:低耦合,高内聚么!对外除了提供public 方法,不要对外泄露任何信息。

上代码

 //主管特务
    public class Supervisor {
        //主管管理的特务列表
        private List<String> suList = new ArrayList<>();

        //获取特务员信息
        private List<String> getSupervisor() {
            if (suList.size() == 0) {
                for (int i = 0; i < 10; i++) {
                    suList.add("Super特务" + i);
                }
            }
            return suList;
        }

        //所有特务信息
        public void pintfSupervisor(ChiefSpies chief) {
            List<String> supervisor = this.getSupervisor();
            for (String supers : supervisor) {
                System.out.println(supers);
            }
            //这种写法,就违背了迪米特法则,直接把下面自己管理的名单拿了过来,
            //这样耦合性就太强了,万一上头被日本仔端了,被人名单也到手了,这就麻烦了!
            //我们改一改,万一被日本仔发现了,端了,也不至于知道太多信息。
            List<String> chieStringList = chief.getChiefSpies();
            for (String chie : chieStringList) {
                System.out.println(chie);
            }
        }
    }

    //主长特务
    public class ChiefSpies {
        //主管所做的的,特务列表
        private List<String> chList = new ArrayList<>();
        //获取特务员信息
        private List<String> getChiefSpies() {
            if (chList.size() == 0) {
                for (int i = 0; i < 10; i++) {
                    chList.add("chList特务" + i);
                }
            }
            return chList;
        }
    }

上面代码,上级直接拿到下级的所有名单,这种写法耦合性太强了,上级只需要知道,目前到底有多少特务了,你告诉我一下就好了,上级也不能随便拿名单上来,这样太危险,我们修改一下!

 //主管特务
    public class Supervisor {
        //主管所做的的,特务列表
        private List<String> suList = new ArrayList<>();
        //获取特务员信息
        private List<String> getSupervisor() {
            if (suList.size() == 0) {
                for (int i = 0; i < 10; i++) {
                    suList.add("Super特务" + i);
                }
            }
            return suList;
        }

        //所有特务信息
        public void pintfSupervisor(ChiefSpies chief) {
            //修改后,这里只告诉上级目前的特务人员情况,具体跟某个特务没有联系
            chief.pintfSupervisor();
            List<String> supervisor = this.getSupervisor();
            for (String supers : supervisor) {
                System.out.println(supers);
            }
        }
    }

    //主长特务
    public class ChiefSpies {
        //主管所做的的,特务列表
        private List<String> chList = new ArrayList<>();

        //获取特务员信息
        private List<String> getChiefSpies() {
            if (chList.size() == 0) {
                for (int i = 0; i < 10; i++) {
                    chList.add("chList特务" + i);
                }
            }
            return chList;
        }

        //特务员信息
        public void pintfSupervisor() {
            List<String> chieStringList = this.getChiefSpies();
            for (String chie : chieStringList) {
                System.out.println(chie);
            }
        }
    }

按照迪米特法则,应该避免类中出现这样非直接朋友关系的耦合。我再举个例子

A特务中有 B  A1   A2  A3  A4特务员

B特务是A特务的其中一位管理,他又有自己的下属:B1 B2 B3 B4

那么A 可以和B 直接联系,但是A 不能跟B1直接联系,有什么事,A直接联系B就好了!如果A又跟B中的子级有联系,这样一旦暴露,会被一锅端的!

哎,其实每个法则都是要有个度的,不能过分的迪米特啊,这样会产生大量的中介,导致整个系统会变得很复杂,需要思考,反复的去衡量,一句话:做到高内聚,低耦合。

好,最后,到了我们的

开闭原则了

这个没什么好说的,就是遵循上面的5大原则,然后再加上我们的23种设计模式,这样去设计程序,开闭原则自然水到渠成!

借个图说明一下

这是我目前对六大原则的理解,不知道是不是我理解有误,麻烦高手指点!!!

理解完六大原则,下面我得在一次看看我们的23种设计模式,希望有不一样的收获!!!

感谢坚持到最后的你!!!一起加油!!!

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值