开闭原则是指对扩展开放,对修改开闭,提高软件系统的可复用性及可维护性,是面向对象的最基础设计原则。
Software entities like classes,modules and functions shoud be open for extension but closed for modifications.
/*
* Copyright (c) 2020 liuhy
* 项目名称:softwareDesignPrinciple
* 文件名称:bread.java
* 创建日期:2020/5/23 下午6:41
* 作者:liuhy
*/
package com.liuhy.sdp.ocp;
/**
* Created on 2020/5/23.
*
* @author haiyu Liu
*/
public class bread implements commodity{
private Integer fid;
private String name;
private float price;
public bread(Integer fid, String name, float price) {
this.fid = fid;
this.name = name;
this.price = price;
}
public Integer getFid() {
return this.fid;
}
public String getName() {
return this.name;
}
public float getPrice() {
return this.price;
}
//
}
/*
* Copyright (c) 2020 liuhy
* 项目名称:softwareDesignPrinciple
* 文件名称:breadDiscount.java
* 创建日期:2020/5/23 下午6:44
* 作者:liuhy
*/
package com.liuhy.sdp.ocp;
/**
* Created on 2020/5/23.
*
* @author haiyu Liu
*/
public class breadDiscount extends bread {
public breadDiscount(Integer fid, String name, float price) {
super(fid, name, price);
}
public float getDiscountPrice(){
return super.getPrice()*0.9F;
}
}
/*
* Copyright (c) 2020 liuhy
* 项目名称:softwareDesignPrinciple
* 文件名称:commodity.java
* 创建日期:2020/5/23 下午6:16
* 作者:liuhy
*/
package com.liuhy.sdp.ocp;
/**
* Created on 2020/5/23.
*
* @author haiyu Liu
*/
interface commodity {
Integer getFid();
String getName();
float getPrice();
}
里氏替换原则就是子类可以扩展父类的功能,但不能够改变父类原有的功能。调用父类的功能,替换成子类也一定能够完成。
Inheritance should ensure that any property proved about supertype objects also holds for subtype objects.
package com.liuhy.sdp.lsp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class FatherClass {
public void doWork(){
System.out.println("老爹做编码工作");
}
}
package com.liuhy.sdp.lsp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class SonClass extends FatherClass{
//做为儿子,你不应该把父亲的实现方法重写,不符合,使用父亲的地方,都能够用子类去替换。
// public void doWork(){
// System.out.println("儿子学习小学语文");
// }
public void doStudyWork(){
System.out.println("儿子学习小学语文");
}
}
/**
* Created on 2020/5/23.
*
* @author haiyu Liu
*/
public class test {
public static void main(String[] args) {
//看看是不是好儿子
//不是好儿子,虽然你帮助了你的爹,但是想让你爸爸做事儿啊,写代码啊
// SonClass son=new SonClass();
// son.doWork();
// son.doStudyWork();
//这个儿子好,没有帮倒忙。
SonClass son1=new SonClass();
son1.doWork();
son1.doStudyWork();
}
}
单一职责原则是指一个类有且仅有一个引起这个类变化的原因。
There should never be more than one reason for a class to change
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class Pay {
//在这个方法中,写入了三种支持方式,当一个改变时,可能影响另外一下,实现的代码职责也有可能不同。
public void forPay(String paytype){
if("wxpay".equals(paytype)){
System.out.println("欢迎使用微信支付");
}else if("alipay".equals(paytype)){
System.out.println("欢迎使用支付宝支付");
}else{
System.out.println("欢迎银联支付");
}
}
}
package com.liuhy.sdp.srp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class AliPay {
public void forPay(){
System.out.println("欢迎使用支付宝支付");
}
}
package com.liuhy.sdp.srp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class UnionPay {
public void forPay(){
System.out.println("欢迎银联支付");
}
}
package com.liuhy.sdp.srp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class WechatPay {
public void forPay(){
System.out.println("欢迎使用微信支付");
}
}
package com.liuhy.sdp.srp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class test {
public static void main(String[] args) {
//在这个类中实现了多种支付试,不利于代码的维护
Pay pay=new Pay();
pay.forPay("wxpay");
//因此对支付方式,创建不同的类,实现不同的支付
//当然可以做一些顶层的接口设计
WechatPay wxpay=new WechatPay();
wxpay.forPay();
AliPay aliPay=new AliPay();
aliPay.forPay();
UnionPay unionPay=new UnionPay();
unionPay.forPay();
}
}
依赖倒置原则是指抽象不应该依赖具体,具体应该依赖抽象
High level modules shouldnot depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details. Details should depend upon abstractions.
package com.liuhy.sdp.dip;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class CStudy implements IStudy{
@Override
public void study() {
System.out.println("liuhy学习C");
}
}
package com.liuhy.sdp.dip;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class GoStudy implements IStudy {
@Override
public void study() {
System.out.println("liuhy学习GO");
}
}
package com.liuhy.sdp.dip;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class JavaStudy implements IStudy {
@Override
public void study() {
System.out.println("liuhy学习JAVA");
}
}
package com.liuhy.sdp.dip;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public interface IStudy {
void study();
}
package com.liuhy.sdp.dip;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class Liuhy {
//最少知道
private IStudy iStudy;
public Liuhy() {
}
public void studyJava(){
System.out.println("liuhy在学习JAVA");
}
public void studyGo(){
System.out.println("liuhy在学习GO");
}
public void studyC(){
System.out.println("liuhy在学习C");
}
public void dostudy(IStudy iStudy){
iStudy.study();
}
public Liuhy(IStudy iStudy){
this.iStudy=iStudy;
}
public void dostudy(){
this.iStudy.study();
}
}
package com.liuhy.sdp.dip;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class test {
public static void main(String[] args) {
//如果liuhy要学习AI了,怎么办?,还要创建一个方法,那么在实现的地方及调用的地方都需要修改
Liuhy liuhy=new Liuhy();
liuhy.studyJava();
liuhy.studyGo();
liuhy.studyC();
//因此抽象了一下顶层接口,在liuhy类中加入dostudy
liuhy.dostudy(new JavaStudy());
//另外还可以在构造方法时,传入类的方式,依赖注入
liuhy.dostudy(new GoStudy());
liuhy.dostudy();
}
}
接口隔离原则是指面向接口编程,在接口中尽量只包含调用者感兴趣的方法。
The dependency of one class to another one should depend on the smallest possible interface.
package com.liuhy.sdp.isp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
//public class Cooker implements IManagement {
public class Cooker implements ICooker {
// @Override
// public void managementBook() {
// System.out.println("厨师不用管理书");
// }
//
// @Override
// public void managementStudent() {
// System.out.println("厨师不用管理学生");
// }
@Override
public void doCook() {
System.out.println("厨师用做饭");
}
@Override
public void doWork() {
System.out.println("厨师用工作");
}
@Override
public void managementTime() {
System.out.println("厨师管理时间");
}
// @Override
// public void doSutdy() {
// System.out.println("厨师不用学习");
// }
}
package com.liuhy.sdp.isp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public interface ICooker {
void doCook();
void doWork();
void managementTime();
}
package com.liuhy.sdp.isp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public interface IManagement {
//在这个接口中有教师、学生、厨师的一个些工作,其中有些需要分别实现的的,有些不需要实现的
void managementBook();
void managementStudent();
void doCook();
void doWork();
void managementTime();
void doSutdy();
//根据接口隔离原则,应该建立一个单一的接口,类对接口的依赖应该是最小的,接口的方法要适度,因此
//我们把接口进行细化,并拆分成三个接口。
}
package com.liuhy.sdp.isp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public interface ISudtent {
void managementTime();
void doSutdy();
}
package com.liuhy.sdp.isp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public interface ITeacher {
void managementBook();
void managementStudent();
void doWork();
void managementTime();
}
package com.liuhy.sdp.isp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
//public class Sutdent implements IManagement {
public class Sutdent implements ISudtent {
// @Override
// public void managementBook() {
// System.out.println("学生不用管理书");
// }
//
// @Override
// public void managementStudent() {
// System.out.println("学生不用管理学生");
// }
//
// @Override
// public void doCook() {
// System.out.println("学生不用做饭");
// }
//
// @Override
// public void doWork() {
// System.out.println("学生不用工作");
// }
@Override
public void managementTime() {
System.out.println("学生管理时间");
}
@Override
public void doSutdy() {
System.out.println("学生应该学习");
}
}
package com.liuhy.sdp.isp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
//public class Teacher implements IManagement {
public class Teacher implements ITeacher {
@Override
public void managementBook() {
System.out.println("老师用管理书");
}
@Override
public void managementStudent() {
System.out.println("老师用管理学生");
}
// @Override
// public void doCook() {
// System.out.println("老师不用做饭");
// }
@Override
public void doWork() {
System.out.println("老师用工作");
}
@Override
public void managementTime() {
System.out.println("老师管理时间");
}
// @Override
// public void doSutdy() {
// System.out.println("老师不用学习");
// }
}
package com.liuhy.sdp.isp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public interface IManagTime {
void managementTime();
}
迪米特原则又叫最少知道原则(Least Knowledge Principle,LKP)
Talk only to your immediate friends and not to strangers。
package com.liuhy.sdp.lod;
import java.util.ArrayList;
import java.util.List;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class Boss {
public void commandCheckWork(Leader leader){
// List
// workList.add(new Work(i));
// }
// leader.checkWorks(workList);
//检查完工作,向boss汇报一下就成了,不想知道leader具体怎么检查的
leader.checkWorks();
}
}
package com.liuhy.sdp.lod;
import java.util.ArrayList;
import java.util.List;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class Leader {
public void checkWorks(List
System.out.println("检查工作数量:"+workList.size());
}
public void checkWorks(){
List
for(int i=0;i<5;i++){
workList.add(new Work(i));
}
System.out.println("检查工作数量:"+workList.size());
}
}
package com.liuhy.sdp.lod;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class Work {
public Work(Integer i){
System.out.println("我是第"+i+"项工作");
}
}
package com.liuhy.sdp.lod;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class test {
public static void main(String[] args) {
//其实,老板不需要知道你检查工作的过程,也不需要知道具体的工作是什么,只需要检查完汇报给他就行了。
Boss boss=new Boss();
Leader leader=new Leader();
boss.commandCheckWork(leader);
//因此,我们可以把检查工作的过程放到leader类中,因此修改了 leader.checkWorks();
}
}
合成复用原则是指要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。如果要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。
package com.liuhy.sdp.carp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public abstract class DBConnect {
public abstract void connection();
}
package com.liuhy.sdp.carp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class DBConnection {
public void connection(){
System.out.println("我是MySQL数据库连接");
}
}
package com.liuhy.sdp.carp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class MySQLConnect extends DBConnect {
@Override
public void connection() {
System.out.println("我是MySQL连接");
}
}
package com.liuhy.sdp.carp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class OracleConnect extends DBConnect {
@Override
public void connection() {
System.out.println("我是Oracle连接");
}
}
package com.liuhy.sdp.carp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class StudentDao {
//尽量使用组合、聚合关系,而不是使用继承关系达到复用目的,降低类与类之间的耦合度。
//有利于扩展,因此建立一个DBconnet抽象类,MySQLConnect,OracleConnect实现类
private DBConnection dbConnection;
private DBConnect dbConnect;
public void setDbConnection(DBConnection dbConnection) {
this.dbCOnnection= dbConnection;
}
public void addStudent(){
System.out.println(dbConnection+"增加一个学生");
}
public void addStudent(DBConnect dbConnect){
this.dbCOnnect=dbConnect;
System.out.println(dbConnect+"增加一个学生");
}
}
package com.liuhy.sdp.carp;
/**
* Created on 2020/5/30.
*
* @author haiyu Liu
*/
public class test {
public static void main(String[] args) {
StudentDao studentDao=new StudentDao();
studentDao.setDbConnection(new DBConnection());
studentDao.addStudent();
//
studentDao.addStudent(new MySQLConnect());
}
}
学习设计原则,是设计模式的基础。在实际过程中,应该有一定度的遵循设计原则,不要为设计原则而设计原则。