目录:
- 设计模式之单一原则
- 设计模式之里氏替换原则
- 设计模式之依赖倒置原则
- 设计模式之接口隔离原则
- 设计模式之迪米特法则
- 设计模式之权衡法:开闭原则
单一原则
单一,从字面上看都能理解,就是单一,一个类只负责一项职责,实现高内聚,低耦合。为什么要这样做呢?稍微有点经验的猿猴都尝到过单一原则的好处,一个类承担的职责越多,在整个项目中,就会出现到处都有它,超高耦合,举个栗子!!!类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种设计模式,希望有不一样的收获!!!
感谢坚持到最后的你!!!一起加油!!!