Article Directory
Pattern name | definition |
---|---|
Single responsibility principle | A class is only responsible for the corresponding responsibilities of one area |
Principle of opening and closing | The software entity is open to expansion and closed to modification |
Richter Substitution | All references to the base class can be transparently called to his subclasses |
Dependency injection | Abstraction should not depend on details, and details should depend on abstraction |
Interface isolation | Use multiple dedicated interfaces, don't use a general interface |
Synthetic reuse principle | Don't use inheritance when reusing, try to use composition/composite relationship |
Miditra Principles | A software experience reduced interaction with other entities |
Single responsibility principle
单一职责原则,一个类、模块、方法承担一个区域的相应职责,避免多个职责相互交叉,导致修改其中一个职责的时候,影响其他职责。
__单一职责优点:__
- Reduce complexity
- Improve readability and maintainability
- Reduce the risk caused by the change
example
DemoTest This example is the correct single responsibility principle
public class DemoTest{
public static void main(String[] args){
Demo d =new Demo();
d.run("大侠”);
d.run("汉堡");
}
}
class Demo{
public void run(String active){
System.out.println(active)
}
}
Example
Wrong Single Responsibility Principle
public class ErrorTest{
public static void main(String[] args){
Errord =new Error();
d.superMan("大侠”);
d.hanburger("汉堡");
}
}
class Error{
public void superMan(String active){
System.out.println(active)
}
public void hamburger(String active){
System.out.println(active)
}
}
Principle of opening and closing
开闭原则是指一个实体如类、方法、模块应该只提供扩展,不提供修改。
Advantage:
- Maintain the stability of the product;
- Does not affect the original code test operation;
- Make the code more modular and easy to maintain;
- Improve development efficiency;
Example:
/**
*顶层定义一个接口,获取家具信息的接口方法
*/
public interface Furniture{
public String getName();
public double getPrice();
public String getBrand();
public double getDiscounts();
public String getMaterials();
public String getColor();
}
public class Desk implements Furniture{
private double price;
private String brand;
private String materials;
private String color;
private double width;
private double height;
public Desk( double price, String brand, String materials, String color, double width, double height) {
this.price = price;
this.brand = brand;
this.materials = materials;
this.color = color;
this.width = width;
this.height = height;
}
@Override
public double getPrice() {
return price;
}
@Override
public String getBrand() {
return brand;
}
@Override
public String getMaterials() {
return materials;
}
@Override
public String getColor() {
return color;
}
@Override
public double getWidth() {
return width;
}
@Override
public double getHeight() {
return height;
}
}
class BSPHDesk extends Desk {
private double discount;
public BSPHDesk(double discount, double price, String brand, String materials, String color, double width, double height) {
super(price, brand, materials, color, width, height);
this.discount = discount;
}
public double getDiscountPrice() {
return getPrice() * discount;
}
}
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
BSPHDesk desk = new BSPHDesk(0.5,5000,"BSPH","实木","白色",500,600);
desk.getDiscountPrice();
System.out.println("原有价格:"+desk.getPrice()+","+"折扣价格:"+desk.getDiscountPrice());
}
}
Richter Substitution Principle
里氏代换原则 是指 一个实体如果使用父类,那么一定适用于子类,如果使用子类,那么他不能够使用父类。
advantage
- Improve the reusability of the code, the subclass has the methods and attributes of the parent class;
- Improve the scalability of the code and retain its own characteristics;
example:
public class LSPBase {
/**
* 父类方法运行
*/
public void parentRun(){
System.out.println("这个是里氏代换 父类方法 ");
}
}
public class LSPChild extends LSPBase{
@Override
public void parentRun() {
System.out.println("里氏代换覆盖");
}
public void childRun(String content){
System.out.println("childRun里氏代换覆盖"+content);
}
}
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
LSPBase base = new LSPBase();
run(base);//错误
LSPChild child = new LSPChild();
baseRun(child);//非错误
}
private void baseRun(LSPBase base){
base.parentRun();
}
private void run(LSPChild child) {
child.parentRun();
}
}
Principle of Dependency Injection
依赖注入原则 不要依赖于具体实现,要依赖于抽象。
1)高层模块不应该依赖底层模块,两者应该都依赖于抽象(抽象类和接口);
2)抽象(类或接口)不应该依赖于具体细节(实现类);
3)细节(具体类或接口)应该依赖于抽象
advantage:
- Separation of concerns;
- The boilerplate code in the application class is reduced, because all the work for initializing dependencies is handled by the injector component;
- Accessory components make the application easy to expand
- It's easy to unit test through mock objects
Disadvantages:
- Excessive use will make it difficult to maintain;
Do not use dependency injection
public class NonDependency {
public void send(String message, String title) {
System.out.println("这个消息内容:" + message + ",标题:" + title);
}
}
public class NonDependencyApplication {
NonDependency dependency = new NonDependency();
public void receive(String message, String title) {
dependency.send(message, title);
}
}
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
NonDependencyApplication application = new NonDependencyApplication();
application.receive("这个市各消息","这个市各标题");
}
}
Use dependency injection
public interface Dependency {
void send(String message, String title);
}
class EmailDependency implements Dependency {
@Override
public void send(String message, String title) {
System.out.println("Email sent to "+message+ " with title="+title);
}
}
public class SMSSDependency implements Dependency{
@Override
public void send(String message, String title) {
System.out.println("Email sent to "+message+ " with title="+title);
}
}
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
EmailDependency email= new EmailDependency();
email.send("这个是一个邮箱内容 ","这个是一个邮箱标题");
SMSSDependency smss = new SMSSDependency();
email.send("这个是一个smss内容 ","这个是一个smss标题");
}
}