"围观"设计模式(1)--单一职责原则(SRP,Single Responsibility Principle)

沉寂了一个月的时间,仔细学习了下设计模式,从本篇博文开始陆续更新设计模式系列的文章,我给它起了个有意思的名字叫做:“围观”设计模式,当然围观是加引号的,我写博文分享的目的一方面是将自己学到的一些心得体会分享给大家,另一方面是博文与实际的案例结合,达到可以用于实际项目中的目的。希望看到博文的朋友多多提出宝贵的建议与批评,我会虚心的接受。


单一职责原则


单一功能原则(Single responsibility principle)规定每个类都应该有一个单一的功能,并且该功能应该由这个类完全封装起来。所有它的(这个类的)服务都应该严密的和该功能平行(功能平行,意味着没有依赖)。——维基百科


我们这里定义了这样的一个接口,包括setCarName,setCarColor,startUp,run和stop方法,那么这里应该很明显,所有的事情都要交给Car的实现类去完成,其中setCarName,setCarColor可以认为是完成了属性设置的任务,而后面的三个startUp、run、stop则完成了车的具体动作。从这里可以看出这个接口提供的方法存在职责不单一的问题,当然话说回来,setCarName和setCarColor如果放在一个接口中,那就职责单一了吗?一个设置名称,一个是设置颜色,也不是完全的单一嘛,我在这里的看法是不要斤斤计较,过分的划分功能,会导致设计的复杂化,加大工作量,所以在这里我觉得职责在划分的时候,需要进行一个抽象的过程,将完成的功能相近的划分到一起我觉得就可以了。

package cn.design.pattern2016032001SingleResponsibility;

public interface Car {

	/** 设置名称 */
	public void setCarName(String carName);
	
	/** 设置颜色*/
	public void setCarColor(String carColoe);
	
	/** 启动*/
	public void startUp();
	
	/** 行驶*/
	public void run();
	
	/** 停止*/
	public void stop();
	
}
package cn.design.pattern2016032001SingleResponsibility;

public class CarImpl implements Car {

	@Override
	public void setCarName(String carName) {
		System.out.println("名称:" + carName);
	}

	@Override
	public void setCarColor(String carColoe) {
		System.out.println("颜色:" + carColoe);
	}

	@Override
	public void startUp() {
		System.out.println("启动");
	}

	@Override
	public void run() {
		System.out.println("行驶");
	}

	@Override
	public void stop() {
		System.out.println("停止");
	}

}
package cn.design.pattern2016032001SingleResponsibility;

public class MainTest {

	public static void main(String[] args) {
		Car car = new CarImpl();
		car.setCarName("HongQi");
		car.setCarColor("Black");
		
		car.startUp();
		car.run();
		car.stop();
	}
}

那么我们应该怎么设计这个接口呢?

参考了《设计模式之禅》中的例子,将不同职责的操作分开到不同的接口中去。

package cn.design.pattern2016032002SingleResponsibility;

public interface Car {

	/** 设置名称 */
	public void setCarName(String carName);
	
	/** 设置颜色*/
	public void setCarColor(String carColoe);
}
package cn.design.pattern2016032002SingleResponsibility;

public interface CarAction {

	/** 启动*/
	public void startUp();
	
	/** 行驶*/
	public void run();
	
	/** 停止*/
	public void stop();
}
package cn.design.pattern2016032002SingleResponsibility;

public interface CarOperate extends Car,CarAction{

}
package cn.design.pattern2016032002SingleResponsibility;

public class CarImpl implements CarOperate{

	@Override
	public void setCarName(String carName) {
		System.out.println("名称:" + carName);
	}

	@Override
	public void setCarColor(String carColoe) {
		System.out.println("颜色:" + carColoe);
	}

	@Override
	public void startUp() {
		System.out.println("启动");
	}

	@Override
	public void run() {
		System.out.println("行驶");
	}

	@Override
	public void stop() {
		System.out.println("停止");
	}


}
package cn.design.pattern2016032002SingleResponsibility;

public class MainTest {

	public static void main(String[] args) {
		CarOperate car = new CarImpl();
		Car carSet = (Car) car;
		carSet.setCarName("HongQI");
		carSet.setCarColor("Black");
		
		CarAction carAction = (CarAction)car;
		carAction.startUp();
		carAction.run();
		carAction.stop();
	}
}
这些代码比较简单,我这里就不再过多的说明了。


我对这个问题有自己的看法,看下类图


这里会发生耦合,理论上应该尽量避免的,但是我觉得这样设计的话更能体现出单一职责原则。不过应该说尽量避免耦合才好,可能我的这种想法并不是推荐的方法。读者可以进行参考。

package cn.design.pattern2016032003SingleResponsibility;

public interface Car {

	/** 设置名称 */
	public void setCarName(String carName);
	/** 名称 */
	public String getCarName();
	
	/** 设置颜色*/
	public void setCarColor(String carColoe);
	/** 颜色 */
	public String getCarColor();
}
public interface CarAction {

	/** 启动*/
	public void startUp();
	
	/** 行驶*/
	public void run();
	
	/** 停止*/
	public void stop();
}

package cn.design.pattern2016032003SingleResponsibility;

public class CarImpl implements Car{

	private String carName;
	private String carColor;
	
	@Override
	public void setCarName(String carName) {
		this.carName = carName;
		System.out.println("名称:" + carName);
	}

	@Override
	public void setCarColor(String carColoe) {
		this.carColor = carColoe;
		System.out.println("颜色:" + carColoe);
	}

	@Override
	public String getCarName() {
		return this.carName;
	}

	@Override
	public String getCarColor() {
		return this.carColor;
	}

}

package cn.design.pattern2016032003SingleResponsibility;

public class CarActionImpl implements CarAction{

	private Car car;
	
	public CarActionImpl(Car car){
		this.car = car;
	}
	
	@Override
	public void startUp() {
		System.out.println("启动>>" + car.getCarName());
	}

	@Override
	public void run() {
		System.out.println("行驶");
	}

	@Override
	public void stop() {
		System.out.println("停止>>" + car.getCarName());
	}
}

package cn.design.pattern2016032003SingleResponsibility;

public class CarOperate {

	private Car car ;
	private CarAction carAction ;
	
	public CarOperate(Car car,CarAction carAction){
		this.car = car;
		this.carAction = carAction;
	}

	public Car getCar() {
		return car;
	}

	public CarAction getCarAction() {
		return carAction;
	}
	
	
}

package cn.design.pattern2016032003SingleResponsibility;

public class MainTest {

	public static void main(String[] args) {
		Car car = new CarImpl();
		CarAction carAction = new CarActionImpl(car);
		CarOperate carOper = new CarOperate(car,carAction);
		/**
		 * 如果在Action中需要得到Car中的属性可以通过构造函数进行设置
		 */
		carOper.getCar().setCarColor("Black");
		carOper.getCar().setCarName("HongQI");
		
		carOper.getCarAction().startUp();
		carOper.getCarAction().stop();
	}
}

虽然这样的话体现单一设计模式比较好一些,但是还是感觉类之间的耦合有点强,不知道读者对这样的设计有什么看法呢?可以评论提出宝贵的建议。


单一职责模式的优点


1. 降低了单个类的复杂性,尽量保证一个类中操作的类型一致

2. 可读性较好,因为单一职责的原因,对某种职责的操作可以去具体的类中查看。


补充说明


单一职责原则,理论上我们要进行遵循的,但是往往实践中并不一定完全按照他的思路去设计,我的看法还是,尽量在完成业务需要的情况下,考虑按照单一职责原则对接口和类进行设计,类的设计过程中,不要过度的划分,适可而止就好。


源码已经上传至GitHub:下载设计模式代码

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


什么是设计模式一套被反复使用、多数人知晓的、经过分类编目的、代码 设计经验 的总结;使用设计模式是为了 可重用 代码、让代码 更容易 被他人理解、保证代码 可靠性;设计模式使代码编制  真正工程化;设计模式使软件工程的 基石脉络, 如同大厦的结构一样;并不直接用来完成代码的编写,而是 描述 在各种不同情况下,要怎么解决问题的一种方案;能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免引
单一职责原则定义(Single Responsibility Principle,SRP)一个对象应该只包含 单一的职责,并且该职责被完整地封装在一个类中。Every  Object should have  a single responsibility, and that responsibility should be entirely encapsulated by t
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强烈推荐。原文截图*************************************************************************************************************************原文文本************
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,它是针对软件开发中经常遇到的一些设计问题,总结出来的一套通用的解决方案。
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
迭代器模式提供了一种方法,用于遍历集合对象中的元素,而又不暴露其内部的细节。
外观模式又叫门面模式,它提供了一个统一的(高层)接口,用来访问子系统中的一群接口,使得子系统更容易使用。
单例模式(Singleton Design Pattern)保证一个类只能有一个实例,并提供一个全局访问点。
组合模式可以将对象组合成树形结构来表示“整体-部分”的层次结构,使得客户可以用一致的方式处理个别对象和对象组合。
装饰者模式能够更灵活的,动态的给对象添加其它功能,而不需要修改任何现有的底层代码。
观察者模式(Observer Design Pattern)定义了对象之间的一对多依赖,当对象状态改变的时候,所有依赖者都会自动收到通知。
代理模式为对象提供一个代理,来控制对该对象的访问。代理模式在不改变原始类代码的情况下,通过引入代理类来给原始类附加功能。
工厂模式(Factory Design Pattern)可细分为三种,分别是简单工厂,工厂方法和抽象工厂,它们都是为了更好的创建对象。
状态模式允许对象在内部状态改变时,改变它的行为,对象看起来好像改变了它的类。
命令模式将请求封装为对象,能够支持请求的排队执行、记录日志、撤销等功能。
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 基本介绍 **意图:**在不破坏封装性的前提下,捕获一个对象的内部状态,并在该
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为
享元模式(Flyweight Pattern)(轻量级)(共享元素)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结