设计模式之七大原则
单一职责原则
类的职责要单一,不能将太多的职责放在一个类中。
请看代码示例:
未采用单一职责原则
package com.std.www.designPattern.principle;
class Student{
public void getDBConnection(){
System.out.println("连接到数据库");
}
public void addStudent(){
System.out.println("增加了一名学生");
}
public void removeStudent(){
System.out.println("移除了一名学生");
}
public void closeDBConnection(){
System.out.println("关闭连接");
}
}
class Teacher{
public void getDBConnection(){
System.out.println("连接到数据库");
}
public void addTeacher(){
System.out.println("增加了一名老师");
}
public void removeTeacher(){
System.out.println("移除了一名老师");
}
public void closeDBConnection(){
System.out.println("关闭连接");
}
}
public class Client {
public static void main(String[] args) {
Student student=new Student();
student.getDBConnection();
student.addStudent();
student.removeStudent();
student.closeDBConnection();
Teacher teacher=new Teacher();
teacher.getDBConnection();
teacher.addTeacher();
teacher.removeTeacher();
teacher.closeDBConnection();
}
}
采用单一职责原则
package com.std.www.designPattern.principle;
class Student{
private DBConnection dbConnection;
public Student(DBConnection dbConnection) {
this.dbConnection = dbConnection;
}
public void addStudent(){
dbConnection.getDBConnection();
System.out.println("增加了一名学生");
dbConnection.closeDBConnection();
}
public void removeStudent(){
dbConnection.getDBConnection();
System.out.println("移除了一名学生");
dbConnection.closeDBConnection();
}
}
class Teacher{
private DBConnection dbConnection;
public Teacher(DBConnection dbConnection) {
this.dbConnection = dbConnection;
}
public void addTeacher(){
dbConnection.getDBConnection();
System.out.println("增加了一名老师");
dbConnection.closeDBConnection();
}
public void removeTeacher(){
dbConnection.getDBConnection();
System.out.println("移除了一名老师");
dbConnection.closeDBConnection();
}
}
class DBConnection{
public void getDBConnection(){
System.out.println("连接到数据库");
}
public void closeDBConnection(){
System.out.println("关闭连接");
}
}
public class Client {
public static void main(String[] args) {
Student student=new Student(new DBConnection());
student.addStudent();
student.removeStudent();
Teacher teacher=new Teacher(new DBConnection());
teacher.addTeacher();
teacher.removeTeacher();
}
}
从这里可以看出,没用采用单一原则下的Student和Teacher中重复写了数据库连接和关闭方法,并且将连接功能和增减功能写在一块,导致了高耦合,而采用之后,数据库连接可以重复利用,降低了的代码的复杂性,提高了内聚性,假设我们新增一个班主任的增删,可以重复调用数据库连接类
接口隔离原则
使用多个专门的接口来取代一个统一的原则。
请看代码示例:
未采用接口分离原则
package com.std.www.designPattern.principle;
interface IObject{
void addStudent();
void removeStudent();
void addTeacher();
void removeTeacher();
void getDBConnection();
void closeDBConnection();
}
class Student implements IObject{
private DBConnection dbConnection;
public Student(DBConnection dbConnection) {
this.dbConnection = dbConnection;
}
public void addStudent(){
dbConnection.getDBConnection();
System.out.println("增加了一名学生");
dbConnection.closeDBConnection();
}
public void removeStudent(){
dbConnection.getDBConnection();
System.out.println("移除了一名学生");
dbConnection.closeDBConnection();
}
@Override
public void addTeacher() {
}
@Override
public void removeTeacher() {
}
@Override
public void getDBConnection() {
}
@Override
public void closeDBConnection() {
}
}
class Teacher implements IObject{
private DBConnection dbConnection;
public Teacher(DBConnection dbConnection) {
this.dbConnection = dbConnection;
}
@Override
public void addStudent() {
}
@Override
public void removeStudent() {
}
public void addTeacher(){
dbConnection.getDBConnection();
System.out.println("增加了一名老师");
dbConnection.closeDBConnection();
}
public void removeTeacher(){
dbConnection.getDBConnection();
System.out.println("移除了一名老师");
dbConnection.closeDBConnection();
}
@Override
public void getDBConnection() {
}
@Override
public void closeDBConnection() {
}
}
class DBConnection implements IObject{
@Override
public void addStudent() {
}
@Override
public void removeStudent() {
}
@Override
public void addTeacher() {
}
@Override
public void removeTeacher() {
}
public void getDBConnection(){
System.out.println("连接到数据库");
}
public void closeDBConnection(){
System.out.println("关闭连接");
}
}
public class Client {
public static void main(String[] args) {
Student student=new Student(new DBConnection());
student.addStudent();
student.removeStudent();
Teacher teacher=new Teacher(new DBConnection());
teacher.addTeacher();
teacher.removeTeacher();
}
}
采用接口分离原则
package com.std.www.designPattern.principle;
interface IStudent{
void addStudent();
void removeStudent();
}
interface ITeacher{
void addTeacher();
void removeTeacher();
}
interface IDBConnection{
void getDBConnection();
void closeDBConnection();
}
class Student implements IStudent{
private DBConnection dbConnection;
public Student(DBConnection dbConnection) {
this.dbConnection = dbConnection;
}
public void addStudent(){
dbConnection.getDBConnection();
System.out.println("增加了一名学生");
dbConnection.closeDBConnection();
}
public void removeStudent(){
dbConnection.getDBConnection();
System.out.println("移除了一名学生");
dbConnection.closeDBConnection();
}
}
class Teacher implements ITeacher{
private DBConnection dbConnection;
public Teacher(DBConnection dbConnection) {
this.dbConnection = dbConnection;
}
public void addTeacher(){
dbConnection.getDBConnection();
System.out.println("增加了一名老师");
dbConnection.closeDBConnection();
}
public void removeTeacher(){
dbConnection.getDBConnection();
System.out.println("移除了一名老师");
dbConnection.closeDBConnection();
}
}
class DBConnection implements IDBConnection{
public void getDBConnection(){
System.out.println("连接到数据库");
}
public void closeDBConnection(){
System.out.println("关闭连接");
}
}
public class Client {
public static void main(String[] args) {
Student student=new Student(new DBConnection());
student.addStudent();
student.removeStudent();
Teacher teacher=new Teacher(new DBConnection());
teacher.addTeacher();
teacher.removeTeacher();
}
}
从上面看出,Student只依赖addStudent和removeStudent方法,同理两外两个类也依赖各自的方法,但我们如果实现第一种接口需要实现所有方法,通过接口隔离原则,我确定每个类的最小依赖接口,使得不同接口之间进行隔离
依赖倒转原则
要针对抽象层编程,而不要针对具体类编程。
请看代码示例:
未采用依赖倒转原则
package com.std.www.designPattern.principle;
interface IStudent{
void addStudent();
void removeStudent();
}
interface IDBConnection{
void getDBConnection();
void closeDBConnection();
}
class Student implements IStudent {
private MysqlDBConnection dbConnection;
public Student(MysqlDBConnection dbConnection) {
this.dbConnection = dbConnection;
}
public void addStudent(){
dbConnection.getDBConnection();
System.out.println("增加了一名学生");
dbConnection.closeDBConnection();
}
public void removeStudent(){
dbConnection.getDBConnection();
System.out.println("移除了一名学生");
dbConnection.closeDBConnection();
}
}
class MysqlDBConnection implements IDBConnection{
public void getDBConnection(){
System.out.println("连接到Mysql数据库");
}
public void closeDBConnection(){
System.out.println("关闭Mysql连接");
}
}
class SqlServerDBConnection implements IDBConnection{
public void getDBConnection(){
System.out.println("连接到SqlServer数据库");
}
public void closeDBConnection(){
System.out.println("关闭SqlServer连接");
}
}
public class Client {
public static void main(String[] args) {
Student student=new Student(new MysqlDBConnection());
student.addStudent();
student.removeStudent();
}
}
采用依赖倒转原则
package com.std.www.designPattern.principle;
interface IDBConnection{
void getDBConnection();
void closeDBConnection();
}
/**
* 依赖注入的三种方式
* */
interface IStudent{
//接口注入
void addStudent(IDBConnection idbConnection);
void removeStudent();
}
class Student implements IStudent{
private IDBConnection dbConnection;
//构造注入
public Student(IDBConnection dbConnection) {
this.dbConnection = dbConnection;
}
//设值注入
public void setDbConnection(IDBConnection dbConnection) {
this.dbConnection = dbConnection;
}
public void addStudent(IDBConnection idbConnection){
dbConnection.getDBConnection();
System.out.println("增加了一名学生");
dbConnection.closeDBConnection();
}
public void removeStudent(){
dbConnection.getDBConnection();
System.out.println("移除了一名学生");
dbConnection.closeDBConnection();
}
}
class MysqlDBConnection implements IDBConnection{
public void getDBConnection(){
System.out.println("连接到Mysql数据库");
}
public void closeDBConnection(){
System.out.println("关闭Mysql连接");
}
}
class SqlServerDBConnection implements IDBConnection{
public void getDBConnection(){
System.out.println("连接到SqlServer数据库");
}
public void closeDBConnection(){
System.out.println("关闭SqlServer连接");
}
}
public class Client {
public static void main(String[] args) {
Student student=new Student(new MysqlDBConnection());
student.addStudent(new SqlServerDBConnection());
student.removeStudent();
}
}
三种注入方式,使得Student根据注入的具体连接类可以连接到不同的数据库,依赖于抽象而非实现
里氏替换原则
在软件系统中,一个可以接受基类对象的地方必然可以接受一个子类的对象。
请看代码示例:
未采用里氏替换原则
package com.std.www.designPattern.principle;
class Student {
public void addStudent(){
System.out.println("增加了一名学生");
}
public void removeStudent(){
System.out.println("移除了一名学生");
}
}
class StudentDao{
private Student student;
public void setStudent(Student student) {
this.student = student;
}
public void add(){
student.addStudent();
}
public void remove(){
student.removeStudent();
}
}
class SquadLeader{
public void addStudent() {
System.out.println("增加了一名班长");
}
public void removeStudent() {
System.out.println("移除了一名班长");
}
}
public class Client {
public static void main(String[] args) {
StudentDao studentDao=new StudentDao();
studentDao.setStudent(new Student());
studentDao.add();
studentDao.remove();
}
}
采用里氏替换原则
package com.std.www.designPattern.principle;
abstract class BaseStudent{
public abstract void addStudent();
public abstract void removeStudent();
}
class Student extends BaseStudent{
public void addStudent(){
System.out.println("增加了一名学生");
}
public void removeStudent(){
System.out.println("移除了一名学生");
}
}
class StudentDao{
private BaseStudent student;
public void setStudent(BaseStudent student) {
this.student = student;
}
public void add(){
student.addStudent();
}
public void remove(){
student.removeStudent();
}
}
class SquadLeader extends BaseStudent{
public void addStudent() {
System.out.println("增加了一名班长");
}
public void removeStudent() {
System.out.println("移除了一名班长");
}
}
public class Client {
public static void main(String[] args) {
StudentDao studentDao=new StudentDao();
studentDao.setStudent(new Student());
studentDao.add();
studentDao.remove();
studentDao.setStudent(new SquadLeader());
studentDao.add();
studentDao.remove();
}
}
里氏替换原则要求继承尽量不重写父类的方法,而且尽量使用关联,聚合,组合等方式代替继承,符合开闭原则,对于两个功能重复的模块,我们可以剥离出一个更基础的模块来,然后让这两个模块继承该模块,如果新增一个例如副班长模块,我们只需继承而无需修改源代码
开闭原则
软件实体对扩是开放的,但对修改是关闭的,即在不修改一个软件的实体的基础上去扩展其功能
请看代码示例:
未采用开闭原则
package com.std.www.designPattern.principle;
class Student{
public void addStudent(){
System.out.println("增加了一名学生");
}
public void removeStudent(){
System.out.println("移除了一名学生");
}
public void exchange(){
System.out.println("交换一名学生");
}
}
采用开闭原则
package com.std.www.designPattern.principle;
class Student{
public void addStudent(){
System.out.println("增加了一名学生");
}
public void removeStudent(){
System.out.println("移除了一名学生");
}
}
class NewStudent extends Student{
public void exchangeStudent(){
System.out.println("交换了一名学生");
}
}
从上面例子看出,第一种方式修改了的Student的源代码,而第二种方式没有修改,而是创建一个新类对原来的Student进行功能扩展,而并没有修改原来Student的源代码
迪米特法则
一个软件实体对其它实体的引用越少越好,或者说如果这两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,而是通过引入一个第三者发生间接交互。
请看代码示例:
未采用迪米特法则
package com.std.www.designPattern.principle;
import java.util.ArrayList;
import java.util.List;
class DBConnection{
public void getDBConnection(){
System.out.println("打开数据库连接");
}
public void closeDbConnection(){
System.out.println("关闭数据库连接");
}
}
class StudentDisplay{
public void addStudent(){
DBConnection dbConnection=new DBConnection();
dbConnection.getDBConnection();
System.out.println("添加一名学生");
dbConnection.closeDbConnection();
}
public void removeStudent(){
DBConnection dbConnection=new DBConnection();
dbConnection.getDBConnection();
System.out.println("移除一名名学生");
dbConnection.closeDbConnection();
}
public void displayStudent(){
DBConnection dbConnection=new DBConnection();
dbConnection.getDBConnection();
System.out.println("输出学生列表");
dbConnection.closeDbConnection();
}
}
class TeacherDisplay{
public void addTeacher(){
DBConnection dbConnection=new DBConnection();
dbConnection.getDBConnection();
System.out.println("添加一名学生");
dbConnection.closeDbConnection();
}
public void removeTeacher(){
DBConnection dbConnection=new DBConnection();
dbConnection.getDBConnection();
System.out.println("移除一名名学生");
dbConnection.closeDbConnection();
}
public void displayTeacher(){
DBConnection dbConnection=new DBConnection();
dbConnection.getDBConnection();
System.out.println("输出学生列表");
dbConnection.closeDbConnection();
}
}
public class Client {
public static void main(String[] args) {
StudentDisplay studentDisplay=new StudentDisplay();
studentDisplay.displayStudent();
TeacherDisplay teacherDisplay=new TeacherDisplay();
teacherDisplay.displayTeacher();
}
}
采用迪米特法则
package com.std.www.designPattern.principle;
import java.util.ArrayList;
import java.util.List;
class DBConnection{
public void getDBConnection(){
System.out.println("打开数据库连接");
}
public void closeDbConnection(){
System.out.println("关闭数据库连接");
}
}
class PersonDao{
public void add(String type){
DBConnection dbConnection=new DBConnection();
dbConnection.getDBConnection();
System.out.println("添加一名"+type);
dbConnection.closeDbConnection();
}
public void remove(String type){
DBConnection dbConnection=new DBConnection();
dbConnection.getDBConnection();
System.out.println("移除一名"+type);
dbConnection.closeDbConnection();
}
public void getList(String type){
DBConnection dbConnection=new DBConnection();
dbConnection.getDBConnection();
System.out.println("返回+"+type+"+列表");
dbConnection.closeDbConnection();
}
}
class StudentDisplay{
public void addStudent(){
PersonDao student=new PersonDao();
student.add("学生");
}
public void removeStudent(){
PersonDao student=new PersonDao();
student.remove("学生");
}
public void displayStudent(){
PersonDao student=new PersonDao();
student.getList("学生");
System.out.println("输出学生列表");
}
}
class TeacherDisplay{
public void addTeacher(){
PersonDao teacher=new PersonDao();
teacher.add("老师");
}
public void removeTeacher(){
PersonDao teacher=new PersonDao();
teacher.remove("老师");
}
public void displayTeacher(){
PersonDao teacher=new PersonDao();
teacher.remove("老师");
System.out.println("输出老师列表");
}
}
public class Client {
public static void main(String[] args) {
StudentDisplay studentDisplay=new StudentDisplay();
studentDisplay.displayStudent();
TeacherDisplay teacherDisplay=new TeacherDisplay();
teacherDisplay.displayTeacher();
}
}
上面增加了一个中间类,让两个展示类通过这个中间类和数据库连接类进行交互,使得两个类解耦合,原本两个展示类都和数据库连接类交互,当新增一个数据库类或者展示类都可以通过这个中间类进行交互
合成复用原则
在复用功能时,应该尽量多使用组合和聚合关联关系,尽量少使用甚至不适用继承关系
请看代码示例:
未采用合成复用原则
package com.std.www.designPattern.principle;
class Student{
public void addStudent(){
System.out.println("添加一名学生");
}
public void removeStudent(){
System.out.println("移除一名学生");
}
}
class Teacher extends Student{
public void addTeacher(){
System.out.println("添加一名老师");
}
public void removeTeacher(){
System.out.println("移除一名老师");
}
}
class School extends Teacher{
public void addSchoolPerson(){
addStudent();
addTeacher();
}
public void removeSchoolPerson(){
removeStudent();
removeTeacher();
}
}
public class Client {
public static void main(String[] args) {
School school=new School();
school.addSchoolPerson();
school.removeSchoolPerson();
}
}
采用合成复用原则
package com.std.www.designPattern.principle;
class Student{
public void addStudent(){
System.out.println("添加一名学生");
}
public void removeStudent(){
System.out.println("移除一名学生");
}
}
class Teacher{
public void addTeacher(){
System.out.println("添加一名老师");
}
public void removeTeacher(){
System.out.println("移除一名老师");
}
}
class School {
private Student student=new Student();
private Teacher teacher=new Teacher();
public void addSchoolPerson(){
student.addStudent();
teacher.addTeacher();
}
public void removeSchoolPerson(){
student.removeStudent();
teacher.removeTeacher();
}
}
public class Client {
public static void main(String[] args) {
School school=new School();
school.addSchoolPerson();
school.removeSchoolPerson();
}
}
这里使用聚集的方式代替继承,使得这三个类解耦合,提高了代码的复用性