【六大设计原则】开放封闭原则

581 阅读3分钟

六大设计原则

单一职责原则

里氏替换原则

依赖倒置原则

接口隔离原则

迪米特法则

开放封闭原则

定义

类、模块、函数等等等应该是可以拓展的,但是不可修改。

白话点来说就是,拓展延伸可以,但是你不可以修改我。

示例

此处以售卖楼盘为例

定义房产信息

import java.math.BigDecimal;

public interface IHouse {

    String getAddress();

    String getArea();

    String getSchool();

    BigDecimal getPrice();
}

房产信息包含了地址,面积,学区房以及房价

定义实现类

import com.design.principle.openclosed.IHouse;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Service
public class HouseImpl implements IHouse {

    private String address;
    private String area;
    private String school;
    private BigDecimal price;

    public HouseImpl(String address, String area, String school, BigDecimal price) {
        this.address = address;
        this.area = area;
        this.school = school;
        this.price = price;
    }

    @Override
    public String getAddress() {
        return address;
    }

    @Override
    public String getArea() {
        return area;
    }

    @Override
    public String getSchool() {
        return school;
    }

    @Override
    public BigDecimal getPrice() {
        return price;
    }
}

定义一个售楼处

import com.design.principle.openclosed.IHouse;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class SalesOffice {

    private final static List<IHouse> houseList = new ArrayList<>();

    static {
        houseList.add(new HouseImpl("淮海路100弄世界花苑1栋一单元201室", "100m^2", "实验小学", new BigDecimal(1000000)));
        houseList.add(new HouseImpl("淮海路100弄世界花苑1栋一单元202室", "102m^2", "实验小学", new BigDecimal(1150000)));
        houseList.add(new HouseImpl("淮海路100弄世界花苑3栋二单元203室", "100m^2", "实验小学", new BigDecimal(1100000)));
        houseList.add(new HouseImpl("淮海路100弄世界花苑3栋二单元204室", "110m^2", "实验小学", new BigDecimal(1200000)));
        houseList.add(new HouseImpl("东海路300弄龙庭花苑2栋一单元501室", "150m^2", "东海小学", new BigDecimal(1700000)));
    }

    public static void main(String[] args) {
        for (IHouse house : houseList) {
            System.out.println("卖出房源->地址:" + house.getAddress() + ";面积:" + house.getArea() + ";学区:" + house.getSchool() + ";房价:" + house.getPrice());
        }
    }
}

image.png

此时可以正常售卖房产

新需求

因为房地产行业进入冷冬,集团准备开展活动,对满足条件的房产进行优惠售卖。以上的项目是无法满足需求的,所以需要对该项目进行改造。

方案一:修改接口

修改IHouse,添加 getDiscounts()方法,然后对应的去修改实现类,在售楼处通过实际价格 getPrice() 减去优惠价格 getDiscounts() 得到售楼价,但是在此处就会发现,修改的接口,就需要对应的去修改实现类HouseImpl和售楼处SalesOffice,不推荐。

代码:

import java.math.BigDecimal;

public interface IHouse {

    String getAddress();

    String getArea();

    String getSchool();

    BigDecimal getPrice();

    BigDecimal getDiscounts();
}
import com.design.principle.openclosed.IHouse;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Service
public class HouseImpl implements IHouse {

    private String address;
    private String area;
    private String school;
    private BigDecimal price;
    private BigDecimal discount;

    public HouseImpl(String address, String area, String school, BigDecimal price, BigDecimal discount) {
        this.address = address;
        this.area = area;
        this.school = school;
        this.price = price;
        this.discount = discount;
    }

    @Override
    public String getAddress() {
        return address;
    }

    @Override
    public String getArea() {
        return area;
    }

    @Override
    public String getSchool() {
        return school;
    }

    @Override
    public BigDecimal getPrice() {
        return price;
    }

    @Override
    public BigDecimal getDiscounts() {
        return discount;
    }
}
import com.design.principle.openclosed.IHouse;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class SalesOffice {

    private final static List<IHouse> houseList = new ArrayList<>();

    static {
        houseList.add(new HouseImpl("淮海路100弄世界花苑1栋一单元201室", "100m^2", "实验小学", new BigDecimal(1000000), new BigDecimal(1000)));
        houseList.add(new HouseImpl("淮海路100弄世界花苑1栋一单元202室", "102m^2", "实验小学", new BigDecimal(1150000), new BigDecimal(2100)));
        houseList.add(new HouseImpl("淮海路100弄世界花苑3栋二单元203室", "100m^2", "实验小学", new BigDecimal(1100000), new BigDecimal(3000)));
        houseList.add(new HouseImpl("淮海路100弄世界花苑3栋二单元204室", "110m^2", "实验小学", new BigDecimal(1200000), new BigDecimal(2000)));
        houseList.add(new HouseImpl("东海路300弄龙庭花苑2栋一单元501室", "150m^2", "东海小学", new BigDecimal(1700000), new BigDecimal(5000)));
    }

    public static void main(String[] args) {
        for (IHouse house : houseList) {
            System.out.println("卖出房源->地址:" + house.getAddress() + ";面积:" + house.getArea() + ";学区:" + house.getSchool() + ";房价:" + house.getPrice().subtract(house.getDiscounts()));
        }
    }
}

image.png

方案二:修改实现类

在实现类出定义一个 getDiscounts(), 在 getPrice()方法里计算优惠后的价格, 但是这里存在一个问题, getPrice()得到的价格是优惠后的价格,那么销售人员或者购买人员无法知道房产的原价和优惠价格了。

代码

@Override
public BigDecimal getPrice() {
    return price.subtract(getDiscounts());
}

private BigDecimal getDiscounts() {
    return discount;
}

image.png

方案三:添加扩展类

添加子类活动价实现类 ActivityPriceImpl 继承 HouseImpl, 重写getPrice()方法, 这样就不会修改原来的实现类,改动少,风险也小。

代码

import java.math.BigDecimal;

public class ActivityPriceImpl extends HouseImpl {

    public ActivityPriceImpl(String address, String area, String school, BigDecimal price) {
        super(address, area, school, price);
    }

    @Override
    public BigDecimal getPrice() {
        BigDecimal price = super.getPrice();
        // 所有房产优惠1000
        return price.subtract(new BigDecimal(1000));
    }
}

image.png

优点

1)降低耦合性。

2)适应性,灵活性,稳定性比较良好。

3)开闭原则是最基础的一个原则,前面介绍的5个原则都是开闭原则的具体形态,而开闭原则才是其精神领袖。