专栏首页后端技术学习设计模式之设计原则

设计模式之设计原则

设计模式之设计原则

相关设计原则图

设计原则

下面我们来看它们的使用的相关场景:

1.单一职责原则

单一职责原则:类的职责单一,不能将太多的职责放在一个类中,该原则是实现高内聚、低耦合的指导方针

比如:进行登录操作需要经过用户请求、参数校验、查找用户、连接数据库、操作数据库等这些操作

public class Login1 {

    //登录,用户请求该方法
    public String login(String username,String password){
        Boolean bo = validate(username,password);   //参数校验
        Object user = findUser(username, password); //查找用户
        if(user==null){
            return "登录失败";
        }
        return "SUCCESS";
    }

    //参数校验
    public Boolean validate(String username,String password){
        return true;
    }

    //查找用户信息
    public Object findUser(String username,String password){
        return null;
    }

    //链接数据库
    public Connection getConn(){
        return null;
    }

    //操作数据库
    public ResultSet query(){
        return null;
    }
}

根据上面的职责单一原则,我们可以将其变成:

用户请求、数据查找、数据库连接、数据库操作等

public class LoginController {

    @Autowired
    private LoginService loginService;

    //①登录,用户请求该方法
    public String login(String username,String password){
        Boolean bo = validate(username,password);   //参数校验
        Object user = loginService.findUser(username, password); //查找用户
        if(user==null){
            return "登录失败";
        }
        return "SUCCESS";
    }


    //②参数校验
    public Boolean validate(String username,String password){
        return true;
    }
}

数据查询业务

public class LoginService {

    @Autowired
    private LoginDao loginDao;

    public Object findUser(String username, String password) {
        return loginDao.query();
    }
}

数据库操作:

public class LoginDao {

    @Autowired
    private DBUtil dbUtil;

    //查询数据库
    public Object query() {
        return dbUtil.getConn();
    }
}

数据库连接

public class DBUtil {
    private Object conn;

    public Object getConn() {
        return conn;
    }
}

这个时候,我们就实现了不同的类做不同的事了。而不是一个类做所有的事。

2.开闭原则

开闭原则:一个软件应当对扩展开发、对修改关闭。即在不修改源代码的情况下改变对象的行为

比如:我们现在需要查看报表,但是由于之前没有预留接口,导致没法进行扩展,出现需要修改原来的代码的情况:

public class PieChart {

    public void display(){
        System.out.println("饼状报表展示");
    }
}

之后又加了一个柱状报表:

public class BarChart {

    public void display(){
        System.out.println("柱状报表展示");
    }
}

现在想进行饼状、柱状报表的查看,代码可能是这样的:

public class ChartDisplay {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int i=sc.nextInt();

        //输入1,则打印饼状报表
        if(i==1){
            PieChart chart = new PieChart();
            chart.display();
         //输入2,则打印柱状报表
        }else if(i==2){
            BarChart chart = new BarChart();
            chart.display();
        }
    }
}

这个时候就不符合开闭原则了,这个时候首先想到的是给以后的更多的报表预留接口,这样方便后来的报表查看,编写一个接口,然后使用抽象类去继承,这里使用抽象类进行演示:

public abstract class AbstractChart {
    abstract void display();
}

进行继承操作

柱状报表:

public class BarChart extends AbstractChart{

    @Override
    public void display(){
        System.out.println("柱状报表展示");
    }
}

饼状报表:

public class PieChart  extends AbstractChart{

    @Override
    public void display(){
        System.out.println("饼状报表展示");
    }
}

进行展示

public class ChartDisplay {

    private static AbstractChart abstractChart;

    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        String className=sc.nextLine();

        //根据输入的类名获取对应实例
        setAbstractChart(className);

        //调用方法
        abstractChart.display();
    }

    /***
     * 根据需要创建实例
     */
    public static void setAbstractChart(String className) throws Exception {
        abstractChart = (AbstractChart) Class.forName(className).newInstance();
    }
}

也即首先抽象出原始接口,在原始接口的基础之后进行扩展。

3.里氏代换原则

里氏代换原则:在软件系统中,一个可以接收基类(父类)对象的地方必然可以接收一个子类对象。其属于开闭原则的实现

给用户发消息:

public class CommonCustomer {

    private String name;

    private String phone;

    public CommonCustomer() {
    }

    public CommonCustomer(String name, String phone) {
        this.name = name;
        this.phone = phone;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String sefInfo() {
        return "给普通客户发消息,客户名字:" + name + ",客户手机号:"+phone;
    }
}

vip用户:

public class VipCustomer {

    private String name;

    private String phone;

    public VipCustomer() {
    }

    public VipCustomer(String name, String phone) {
        this.name = name;
        this.phone = phone;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String sefInfo() {
        return "给VIP客户发消息,客户名字:" + name + ",客户手机号:"+phone;
    }

}

发消息:

public class SendMessage {

    public static void main(String[] args) {
        CommonCustomer commonCustomer = new CommonCustomer("王五","13670001111");
        VipCustomer vipCustomer= new VipCustomer("赵六","13670001133");

        send(vipCustomer);
        send(commonCustomer);
    }

    //给VIP客户发消息
    public static void send(VipCustomer vipCustomer){
        System.out.println(vipCustomer.sefInfo());
    }

    //给普通客户发消息
    public static void send(CommonCustomer commonCustomer){
        System.out.println(commonCustomer.sefInfo());
    }
}

从上面的代码我们可以抽象出公共的信息,同时对公共信息进行扩展,然后调用方法进行发消息

public abstract class Customer {

    private String name;

    private String phone;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public abstract String sefInfo();
}

进行公共行为扩展:

普通用户:

public class CommonCustomer extends Customer{

    @Override
    public String sefInfo() {
        return "给普通客户发消息,客户名字:" + super.getName() + ",客户手机号:"+super.getPhone();
    }
}

vip用户

public class VipCustomer extends Customer {

    @Override
    public String sefInfo() {
        return "给VIP客户发消息,客户名字:" + super.getName() + ",客户手机号:"+super.getPhone();
    }
}

进行发送操作:

public abstract class SendMessage {

    public static void main(String[] args) {
        Customer commonCustomer = new CommonCustomer();
        commonCustomer.setName("王五");
        commonCustomer.setPhone("13670001111");
        Customer vipCustomer= new VipCustomer();
        vipCustomer.setName("赵六");
        vipCustomer.setPhone("13670001155");

        send(vipCustomer);
        send(commonCustomer);
    }

    //给VIP客户发消息
    public static void send(Customer customer){
        System.out.println(customer.sefInfo());
    }
}

同时在此基础上,我们可以进行对应的业务操作。

4.依赖倒转原则

依赖倒转原则:抽象不应该依赖细节实现,细节应当依赖抽象,也即面向接口编程,用到接口的地方,通过依赖注入将接口的实现对象注入进去。

抽象接口:

public abstract class AbstractChart {
    abstract void display();
}

进行继承:

public class BarChart extends AbstractChart {
@Override
public void display(){
    System.out.println("柱状报表展示");
  }
}
public class PieChart  extends AbstractChart {

    @Override
    public void display(){
        System.out.println("饼状报表展示");
    }
}

进行展示:

public class ChartDisplay {

    private AbstractChart abstractChart;

    //展示报表
    public void showChart(){
        abstractChart.display();
    }

    //Setter注入
    public void setAbstractChart(AbstractChart abstractChart) {
        this.abstractChart = abstractChart;
    }
}

5.接口隔离原则

接口隔离原则:不使用一个总接口,而使用多个接口进行隔离,即客户端不依赖它原本不需要调用的接口

使用一个总接口完成所有操作:

public interface DataRead {

    //增删改查
    void query();
    void insert();
    void delete();
    void update();

    //定时任务执行
    void queryTask();
    void createTask();

    //报表
    void reportExcel();
}

这是不符合接口隔离原则的,因此我们可以将增删查改放入一个接口,定时任务放入一个接口,报表放入一个接口

增删查改接口:

public interface CrudInterface {

    //增删改查
    void query();
    void insert();
    void delete();
    void update();
}

定时任务接口:

public interface TaskInterface {

    //定时任务执行
    void queryTask();
    void createTask();
}

报表接口:

public interface ReportInterface {

    //报表
    void reportExcel();
}

6.合成/复用原则

合成/复用原则:尽量使用对象组合,而不是使用继承来达到复用的目的

public class BookDao extends MySQLUtil {

    //查询
    public ResultSet query() throws Exception{
        //获得数据库链接
        Connection conn = super.getConn();
        PreparedStatement ps = conn.prepareStatement("select * from table");
        return ps.executeQuery();
    }
}

如果数据源发生改变,此时就不能达到复用了,采用DBUtils,然后采用MysSQLUtils继承,进行注入,如果更换其他数据,注入即可。因此可以采用注入的放入,这样可以方便复用,工具类中,放入那个参数就使用哪个。

public class BookDao  {

    @Autowired
    private MySQLUtil mySQLUtil;

    //查询
    public ResultSet query() throws Exception{
        //获得数据库链接
        Connection conn = mySQLUtil.getConn();
        PreparedStatement ps = conn.prepareStatement("select * from table");
        return ps.executeQuery();
    }
}

7.迪米特原则

迪米特原则:一个软件实体应当尽可以少的和其他类发生相互作用,降低耦合度

public class OrderController {

    private GoodsDao goodsDao;
    private OrderDao orderDao;
    private LogDao logDao;

    //添加订单
    public void add(){
        //①修改库存
        goodsDao.modify();
        //②增加订单
        orderDao.add();
        //③记录日志
        logDao.recode();
    }

}

修改成:

商品信息操作:

public class GoodsController {

    private GoodsService goodsService;

    public void modify(){
        goodsService.modify();
    }
}

进行订单新增:

public class OrderController {

    private OrderService orderService;

    //添加订单
    public void add(){
    }

}

logDao:

public class LogDao {
    public void recode() {
        System.out.println("记录日志!");
    }
}

也即不同的类进行不同的操作。

本文分享自微信公众号 - 后端技术学习(gh_9f5627e6cc61),作者:路行的亚洲

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-11-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Netty实现简单RPC调用

    我们知道Dubbo是一个RPC框架,那RPC框架需要实现什么?需要实现的是调用远程服务和本地服务一样方便,同时提高调用远程服务的性能。而服务端和客户端之间的关系...

    路行的亚洲
  • 设计模式之单例模式

    在前面中,我们知道如果一个bean需要被加载,首先需要获取资源的位置,然后根据资源位置获取xml文件,然后将其变成document,然后根据document对元...

    路行的亚洲
  • pmq学习一-一些典型的使用和套路

    pmq是信也科技开源的一款消息中间件,虽然没有RocketMQ和Kafka出名,但是里面的代码还是有值得我们学习的地方的。

    路行的亚洲
  • Android中网络框架简单封装的实例方法

    Android作为一款主要应用在移动终端的操作系统,访问网络是必不可少的功能。访问网络,最基本的接口有:HttpUrlConnection,HttpClient...

    砸漏
  • Android设计模式二

    在组件构建过程中,某些接口之间直接的依赖常常会带来很多问题,甚至根本无法实现。采用添加一层间接(稳定)接口,来隔离本来互相紧密关联的接口是一种常见的解决方案。

    爱因斯坦福
  • 【设计模式】—— 创建者模式Builder

      模式意图   一个对象的创建十分复杂,为了区分构建过程和使用过程,因此分开。使用一个Director类进行对象的创建,Builder规定了这个创建过程。 ...

    用户1154259
  • 设计模式的十八般武艺

    其实字面意思就已经表达的比较明确,单一,也就是干尽量少的事情。在HDU中可以对耦合和内聚程度的评判有一定的了解。

    ClericYi
  • 设计模式整理 顶

    Iterator模式可以帮助我们分离具体的集合跟遍历,就是在代码中更换了集合,也可以不需要重新调用新集合的方法。

    算法之名
  • JAVA中的23种设计模式(GOF)

    volatile 保证数据的可见性,让线程内存数据的变化立刻显示到主存中,而且有序性可以避免指令重排,但是不保证原子性。

    HcodeBlogger
  • JavaSE学习总结(五)——封装,继承,多态很简单

    java面向对象的三大特性是:封装、继承与多态,是面向对象编程的核心。 一、封装 简单说封装就是将同一类事物的特性与功能包装在一起,对外暴露调用的接口。 封装:...

    张果

扫码关注云+社区

领取腾讯云代金券