七大设计原则

设计模式原则就是程序员在编程时,应当遵守的原则,也是各种设计模式的基础(即:设计模式依据什么设计出来)。设计模式常用的七大原则有:
1.单一职责原则
2.开放封闭原则
3.里氏代换原则
4.依赖倒转原则
5.合成/聚合复用原则
6.接口隔离原则
7.迪米特法则

一.单一职责原则

  • 就一个类而言,应该仅有一个引起它变化的原因(职责)
  • 单一职责原则对类来说,即一个类应该只负责一项职责。
  • 如类A负责两个不同职责:职责1,职责2,当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A 的粒度分解为A1,A2
  • 主要根据不同的角度划分职责
    实例:交通工具类
    方案一:
    run方法中,违反了单一职责原则,修改vehicle类
     class vehicle
{
	public void run(String vehicle)
	{
		System.out.println(vehicle+"在公路上跑");
	}
}
public class singleresponsibility {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        vehicle s=new vehicle();
        s.run("汽车");
        s.run("火车");
        s.run("飞机");
	}
}

修改分析:
1.这种修改方法没有对原来的类做大的修改,只是增加方法;
2.增加的部分不影响原有部分,降低了变更引起的风险;
3.这里在类这个级别上没有遵守单一职责原则,但是在方法级别上,仍然是遵守单一职责。

class vehicle
{
	public void run(String vehicle)
	{
		System.out.println(vehicle+"在公路上跑");
	}
	public void fly(String vehicle)
	{
		System.out.println(vehicle+"在天上飞");
	}
	public void swim(String vehicle)
	{
		System.out.println(vehicle+"在水里游");
	}
}
public class singleresponsibility {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
        vehicle s=new vehicle();
        s.run("汽车");
        s.swim("轮船");
        s.fly("飞机");  
	}
}

单一职责原则注意事项和细节:
1)降低类的复杂度,一个类只负责一项职责。
2)提高类的可读性,可维护性
3)降低变更引起的风险
4)通常情况下,应当遵守单一职责原则。只有逻辑足够简单,才可以在代码级违反单一职责原则: 只有类中方法数量足够少,可以在方法级别保持单一职责原则。

二.开放-封闭原则

  • 开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则——面向对象设计的终极目标
  • 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。
  • 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
  • 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。
    实例:实现一个画图形的类
    本例,需要新增一个图形种类时,修改的地方比较多违反了开闭原则(对扩展(提供方)开放,对修改(使用方)关闭):需要给类增加新功能的时候, 尽量不要修改代码,或者尽可能少修改代码。
    原代码:
class juxing
{
	void show()
	{
		System.out.println("画一个矩形");
	}
}
class circle
{
	void show()
	{
		System.out.println("画一个圆形");
	}
}
class sanjiaoxing//新增加
{
	void show()
	{
		System.out.println("画一个三角形");
	}
}
 class GraphicDraw
 {
	 void show(int i)
	 {
		 if(i==1)
		 {
			 juxing jx=new juxing();
			 jx.show();
		 }
		 else if(i==2)
		 {
			 circle c=new circle();
			 c.show();
		 }
		 else if(i==3)//新增
		 {
			 sanjiaoxing sjx=new sanjiaoxing();
			 sjx.show();
		 }
		 
	 }
 }
public class singleresponsibility {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		GraphicDraw g=new GraphicDraw();
		g.show(1);//新增之后客户端也要改
	}
}

改进思路:创建抽象Shape类做成基类,并提供抽象的draw方法,让子类去实现,当需要新的图形时,只需要让新的图形继承Shape, 并实现draw方法

abstract class shape
{
	public abstract void draw();
}
class GraphicDraw {	//新增绘制图形不需修改此类
	void drawgraph(shape s)
	{	
		s.draw();	
		}
}
class juxing extends shape
{
	public void draw() {
		// TODO Auto-generated method stub
		System.out.println("画一个矩形");
	}
}
class Circle extends shape
{
        public void draw()
        {
        	System.out.println("画一个圆形");
        }
}
class Triangle extends shape//新增三角形
{	
	public void draw()
	{
		System.out.println("画一个三角形");
	}
}

public class singleresponsibility {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		GraphicDraw g=new GraphicDraw();
		g.drawgraph(new Circle());
		g.drawgraph(new Triangle());
	}
}

开闭原则:

  • Open-Closed Principle原则:一个软件实体应当对扩展开放,对修改关闭。
  • 开闭原则是面向对象设计中“可复用设计”的基石,是面向对象设计中最重要的原则之一,其它很多的设计原则都是实现开闭原则的一种手段。
  • 开闭原则中“开”,是指对于组件功能的扩展是开放的, 是允许对其进行功能扩展的;
  • 开闭原则中“闭”,是指对于原有代码的修改是封闭的,即不应该修改原有的代码。

三.里氏代换原则

  • 继承的优点:
  • 子类拥有父类的所有方法和属性,从而可以减少创建类的工作量。
  • 提高了代码的重用性。
  • 提高了代码的扩展性,子类不但拥有了父类的所有功能,还可以添加自己的功能。
  • 继承的缺点:
    • 继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法。
    • 降低了代码的灵活性。因为继承时,父类会对子类有一种约束。
    • 增强了耦合性。当需要对父类的代码进行修改时,必须考虑到对子类产生的影响。有时修改了一点点代码都有可能需要对大段程序进行重构。
  • 继承包含这样一层含义:父类中已经实现的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏。
    缺点代码实例:
class A{
	public int func1(int num1, int num2){
		return num1-num2;  }
}
class B extends A{
  public int func1(int a,int b){
    return a+b;}
  public int func2(int a, int b){
    return func1(a,b)+9;}
}

public class singleresponsibility {

	public static void main(String[] args) {
		A a = new A();
		System.out.println("11-3=" +a.func1(11,3));
		System.out.println("1-8="+a.func1(1,8));
		System.out.println ("-------");
		B b = new B();
		System.out.println("11-3=" + b.func1(11,3));
		//这里本意是求出11-3,结果为14
		System.out.println("1-8="+ b.func1(1,8));//结果为9
		System.out.println("11+3+9="+b.func2(11,3));
	}
}

原因就是类B重写了父类的方法func1,造成原有功能出现错误。
里氏代换原则:

  • 子类型(subtype)必须能够替换它们的基(父)类型。(子类可以以父类的身份出现)
  • 是关于继承机制的原则,是实现开放-封闭原则的具体规范,违反了里氏代换原则必然违反了开放-封闭原则。
  • 只要有父类出现的地方,都可以使用子类来替代。而且不会出现任何错误或者异常。但是反过来却不行。子类出现的地方,不能使用父类来替代。
  • 里氏代换原则的主要作用:规范继承时子类的一些书写规则。其主要目的就是保持父类方法不被覆盖。
    通常的解决思路:
    让原来的父类和子类都继承一个更通俗的基类, 原有的继承关系去掉,采用依赖,聚合,组合等关系代替。
class Base {
	//把更加基础的方法和成员写到Base类
	}
	// A类
	class C extends Base {
	//返回两个数的差
	  public int func1(int num1, int num2) {
		  return num1 - num2;  }
	}
	class D extends Base{
	  C a=new C();
	  public int func1(int a,int b){
		  return a+b;	}
	  public int func2(int a, int b){
		  return func1(a,b)+9;	}
	  public int func3(int a, int b){
		  return this.a.func1(a,b);	}
	}

	public class main{
	  public static void main(String[] args) {
		C a = new C();
		System.out.println("11-3=" +a.func1(11,3));
		System.out.println("1-8="+a.func1(1,8));
		System.out.println ("-------");
		D b= new D();
		//因为D类不再继承C类,因此调用者,不会再func1是求减法
		//调用完成的功能就会很明确
		System. out.println("11+3=" + b. func1(11, 3));//这里本意是求出11+3
		System. out.println("1+8=" + b.func1(1, 8));// 1+8
		System. out.println("11+3+9=" + b.func2(11, 3));
		//使用组合仍然可以使用到A类相关方法
		System. out.println("11-3=" + b.func3(11, 3));// 这里本意是求出11-3
		}	
	}
  1. 里氏代换原则规定,子类不能覆写父类已实现的方法。父类中已实现的方法其实是一种已定好的规范和契约,如果随意修改它,那么可能会带来意想不到的错误。由子类来实现抽象方法,这里使用的其实就是里氏代换原则。
  2. 子类中可以增加自己特有的方法。子类继承了父类,拥有了父类和方法,同时还可以定义自己有,而父类没有的方法。这是在继承父类方法的基础上进行功能的扩展,符合里氏代换原则。

四.依赖倒转原则

  • 高层模块不应该依赖低层模块,二者都应该依赖其抽象
  • 抽象不应该依赖细节,细节应该依赖抽象
  • 依赖倒转(倒置)的中心思想是面向接口编程
  • 依赖倒转原则是基于这样的设计理念:
    相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在Java中,抽象指的是接口或抽象类,细节就是具体的实现类。
  • 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
    实例:实现person类接收信息方式
class Email
{
	public 	String getinfo()
	{
		return "Email:helloworld";
	}
}
/* Person 类 接受消息,将Email类作为参数 产生了依赖
 1. 如果参数发生变化,即接受的是微信或短信整个方法需要改动*/
class person
{
	public void person(Email e)
	{
		System.out.println(e.getinfo());
	}
}
public class main
{
	 public static void main(String[] args) 
	{
		person p=new person();
		p.person(new Email());
	}	
}

分析:如果我们获取的对象是微信,短信等,则新增类,同时Perons也要增加相应的接收方法
解决:引入一个抽象的接口IReceiver,表示接收者,这样Person 类与接口IReceiver发生依赖
因为Emai1, WeiXin等属于接收的范围,它们各自实现IReceiver接口, 这样就符合依赖倒转原则。
修改代码

interface receive
{
	public String getinfo();
}
class Email implements receive
{
	public 	String getinfo()
	{
		return "Email:helloworld";
	}
}
class weixin implements receive
{

	@Override
	public String getinfo() {
		// TODO Auto-generated method stub
		return "wechat:helloworld";
	}
	
}
/* Person 类 接受消息将IReciver 接口 作为参数 产生了依赖*/
class person
{
	public void person(receive e)
	{
		System.out.println(e.getinfo());
	}
}
public class main
{
	 public static void main(String[] args) 
	{
		person p=new person();
		p.person(new Email());
		p.person(new weixin());
	}	
}

依赖倒转原则的注意事项和细节:

  1. 低层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好。
  2. 变量的声明类型尽量是抽象类或接口,这样变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化。
    B obj=new A(); //B是抽象类,A继承B, 如果要扩展A,则只要扩充B
  3. 继承时遵循里氏替换原则。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值