Java程序设计六大原则设计模式

Java程序设计六大原则

一、单一职责原则:

一个接口或者类只有一个原因引起变化,即一个接口或者类只有一个职责,负责一件事情。(此原则同样适用于方法)

好处:1、复杂性降低;2、可读性提高;3、可维护性提高;4、变更风险降低

二、里氏替换原则:

父类能出现的地方子类就可以出现
定义解释:
1、子类必须完全实现父类的方法;

2、子类可以有自己的个性;

3、覆盖或者实现父类的方法时,输入参数可以被放大;

public class Father {undefined
    public Collection doSomething(HashMap map) {undefined
        System.out.println("父类被执行了");
        return map.values();
    }
}

public class Son extends Father {undefined
    public Collection  doSomething(Map  map) {undefined
        System.out.println("子类被执行了");
        return map.values();
    }    
}

public static void main(String[] args) {undefined
    Father father = new Father();
    Son son = new Son();
    HashMap<Object,Object> map = new HashMap<>();
    
    father.doSomething(map);
    son.doSomething(map);
}

以上代码执行时,子类重载了父类的doSomething方法,并且放大输入参数Hashmap→Map,执行以后,出现相同的结果,均输出"父类被执行了",并没有歪曲父类的意图,不会引起业务逻辑混乱,符合里氏替换原则。

4、覆写或者实现父类的方法时,输出结果可以被缩小;

三、依赖倒置原则:

1、高层不应该依赖底层,两者都应该依赖其抽象;

2、抽象不应该依赖细节,细节应该依赖抽象;
即模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或者抽象类产生的。更加简单的定义就是"面向接口编程(OOD:Object-Oriented Design)"

四、接口隔离原则:

通俗的讲,接口尽量细化,同时接口中的方法尽量少。说明:单一职责原则侧重于业务逻辑,即职责尽量少;而接口隔离原则侧重于接口中的方法尽量少。

五、迪米特法则:

也称为最少知识原则:一个对象应该对其他对象有最少的了解。通俗的讲:一个类应该对自己需要耦合或者调用的类知道的越少越好

六、开闭原则:

软件实体应该对扩展开放,对修改关闭。就是说应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。

设计模式:

一、门面模式(外观模式):

是指提供一个统一的接口去访问多个子系统的多个不同的接口,它为子系统中的一组接口提供一个统一的高层接口。使得子系统更容易使用。

定义一个(或多个)具备所需接口的新类(门面类);
新类门户使用原来的系统;
客户使用门面类对象与原系统打交道;

1、activity内部直接使用三方网络请求库的api 来请求网络,导致activity和网络请求库高度耦合,且违背单一职责原则。

2、使用门面模式对网络请求框架进行封装,使用单例模式编写门面类,在门面类内部直接使用三方网络请求库的api 来请求网络(即门面类拥有网络库的功能),并定义网络返回结果的接口,最后通过接口回调的方式返回网络请求结果到activity。

// 接口
public interface IHttpApi {

    void register();

    void login();

    void getUserInfo();
}

// 三方网络库
public class OkHttp implements IHttpApi {
    @Override
    public void register() {
        System.out.println("OkHttp register");
    }

    @Override
    public void login() {
        System.out.println("OkHttp login");
    }

    @Override
    public void getUserInfo() {
        System.out.println("OkHttp getUserInfo");
    }
}


// 门面类
public class UserApi {

    private OkHttp okHttp;

    public static UserApi getInstance(){
        return UserApiHelper.userApi;
    }

    private static class UserApiHelper{
        private static UserApi userApi = new UserApi();
    }

    private UserApi() {
        okHttp = new OkHttp();
    }

    public void login(){
        System.out.println("UserApi login");
        okHttp.register();
        okHttp.login();
    }

    public void getUserInfo(){
        System.out.println("UserApi getUserInfo");
        okHttp.login();
        okHttp.getUserInfo();
    }
}

// 使用
public static void main(String[] args) {
        UserApi.getInstance().login();
        UserApi.getInstance().getUserInfo();
    }

优点:解耦activity和三方网络库,activity实现单一职责原则;

缺点:门面类和网络请求库高度耦合,当需要切换网络库时,需要修改整个门面类,违背了开闭原则。

二、代理模式(Proxy):

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

1、创建代理类,三方库实现类,统一规则接口;

public interface IHttpApi {

    void register();

    void login();

    void getUserInfo();
}

2、代理类和三方库都要实现统一规则接口,同时代理类拥有三方库实现类这个对象(以接口的形式持有)

// 三方库OkHttp 
public class OkHttp implements IHttpApi {
    @Override
    public void register() {
        System.out.println("OkHttp register");
    }

    @Override
    public void login() {
        System.out.println("OkHttp login");
    }

    @Override
    public void getUserInfo() {
        System.out.println("OkHttp getUserInfo");
    }
}

// 三方库Volley 
public class Volley implements IHttpApi {
    @Override
    public void register() {
        System.out.println("Volley register");
    }

    @Override
    public void login() {
        System.out.println("Volley login");
    }

    @Override
    public void getUserInfo() {
        System.out.println("Volley getUserInfo");
    }
}

// 代理类
public class UserApi implements IHttpApi {
    private IHttpApi iHttpApi;

    public UserApi(IHttpApi iHttpApi) {
        this.iHttpApi = iHttpApi;
    }


    @Override
    public void register() {
        System.out.println("UserApi register");
        iHttpApi.register();
    }

    @Override
    public void login() {
        System.out.println("UserApi login");
        iHttpApi.login();
    }

    @Override
    public void getUserInfo() {
        System.out.println("UserApi getUserInfo");
        iHttpApi.getUserInfo();
    }
}

3、三方库实现类,直接使用三方网络请求库的api 来请求网络(即三方库实现类拥有网络库的功能)

4、统一规则接口,即get和post方法

5、在初始代理类时,需要传入三方库实现类的类型(如:volley或okhttp)。

6、用户调用代理类实现的网络请求接口时,代理类通过调用 持有的三方库实现类 去调用三方网络请求库的api 来请求网络。

7、代理类本身不具备网络库的功能,充当中介的作用,去调用三方库实现类。

public static void main(String[] args) {
        // 代理OkHttp
        System.out.println("代理OkHttp");
        OkHttp okHttp = new OkHttp();
        UserApi userApi = new UserApi(okHttp);
        userApi.register();
        userApi.login();
        userApi.getUserInfo();
        // 代理Volley
        System.out.println("代理Volley");
        Volley volley = new Volley();
        userApi = new UserApi(volley);
        userApi.register();
        userApi.login();
        userApi.getUserInfo();
    }

优点:解耦代理类和三方网络库,当需要更换三方网络库时,直接在初始化代理类时,需要传入新的三方库实现类。

三方库实现类使用了里氏替换原则,子类必须完全实现父类的方法。

三、单例模式:

确保一个类只有一个实例,而且自行实例化并向整个系统或应用提供这个实例。

饿汉模式
懒汉模式
Double Check Lock
枚举单例
静态内部类实现单例(最优雅单例)

private static class SingletonHolder {
    private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getSingleton5() {
    return SingletonHolder.INSTANCE;
}

四、建造者模式(Builder模式):

将一个复杂对象的创建和表示分离,使用相同的构建过程创建不同的对象。

public class TestPerson {
    private String mPersonName;
    private int mPersonAge;
    private int mSex;
    private String mCardNumber;

    public TestPerson TestPerson(){
        return new TestPerson(new TestPerson.Builder());
    }

    public TestPerson(TestPerson.Builder builder){
        this.mCardNumber = builder.mCardNumber;
        this.mSex = builder.mSex;
        this.mPersonAge = builder.mPersonAge;
        this.mPersonName = builder.mPersonName;
    }

    public static final class Builder {
        private String mPersonName;
        private int mPersonAge;
        private int mSex;
        private String mCardNumber;

        public Builder(){}

        public TestPerson build(){
            return new TestPerson(this);
        }

        public TestPerson.Builder addPersonName(String mPersonName) {
            this.mPersonName = mPersonName;
            return this;
        }

        public TestPerson.Builder addPersonAge(int mPersonAge) {
            this.mPersonAge = mPersonAge;
            return this;
        }

        public TestPerson.Builder addSex(int mSex) {
            this.mSex = mSex;
            return this;
        }

        public TestPerson.Builder addCardNumber(String mCardNumber) {
            this.mCardNumber = mCardNumber;
            return this;
        }
    }
}

TestPerson pserson = new TestPerson.Builder()
        .addPersonName("狗蛋")
        .addSex(1)
        .addPersonAge(18)
        .build();

五、观察者模式(Observer Pattern):

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。

三要素:Observer是观察者接口,Observable是被观察者接口,ObservableImpl是被观察者实现类(管理所有观察者)。

Observer观察者接口:

public interface Observer {
    void update(String message);
}

Observable被观察者接口:

public interface Observable {
    // 添加观察者
    void addObserver(Observer observer);

    // 移除观察者
    void removeObserver(Observer observer);

    // 通知观察者
    void notifyObserver(String message);
}

ObservableImpl被观察者实现类:

public class ObservableImpl implements Observable {

    private List<Observer> observerList = new ArrayList<>();

    public static ObservableImpl getInstance() {
        return ObservableHelper.observable;
    }

    private static class ObservableHelper {
        private static ObservableImpl observable = new ObservableImpl();
    }

    @Override
    public void addObserver(Observer observer) {
        if (!observerList.contains(observer)) {
            observerList.add(observer);
        }
    }

    @Override
    public void removeObserver(Observer observer) {
        if (observerList.contains(observer)) {
            observerList.remove(observer);
        }
    }

    @Override
    public void notifyObserver(String message) {
        for (Observer observer : observerList) {
            observer.update(message);
        }
    }
}

ObserverImpl观察者实现类:

public class ObserverImpl implements Observer {

    private String observerName;

    public ObserverImpl(String observerName) {
        this.observerName = observerName;
    }

    @Override
    public void update(String message) {
        System.out.println(observerName + ":" + message);
    }
}

ObserverImpl观察者实现类,一般不需要单独编写实现类,这里是为了测试;比如:view要观察activity数据变化而刷新UI,view只要实现Observer观察者接口,view就是观察者实现类。

public static void main(String[] args) {
        // 创建观察者
        ObserverImpl observer1 = new ObserverImpl("observer1");
        ObserverImpl observer2 = new ObserverImpl("observer2");
        ObserverImpl observer3 = new ObserverImpl("observer3");
        // 添加观察者
        ObservableImpl.getInstance().addObserver(observer1);
        ObservableImpl.getInstance().addObserver(observer2);
        ObservableImpl.getInstance().addObserver(observer3);
        // 通知观察者
        ObservableImpl.getInstance().notifyObserver("更新数据");
    }

六、工厂模式:

定义一个用于创建对象的接口,让子类决定实例化哪个类。

创建一个接口:

public interface Car {
    void drive();
}

创建实现接口的实体类:

// 自行车
public class Bike implements Car{
    @Override
    public void drive() {
        System.out.println("Bike drive");
    }
}


// 大巴
public class Bus implements Car{
    @Override
    public void drive() {
        System.out.println("Bus drive");
    }
}

// 火车
public class Train implements Car {
    @Override
    public void drive() {
        System.out.println("Train drive");
    }
}

创建一个工厂,生成基于给定信息的实体类的对象:

public class CarFactory {
    public static Car makeCar(String type) {
        Car car = null;
        switch (type) {
            case "Bike":
                car = new Bike();
                break;
            case "Bus":
                car = new Bus();
                break;
            case "Train":
                car = new Train();
                break;
        }
        return car;
    }
}

使用该工厂,通过传递类型信息来获取实体类的对象。

public static void main(String[] args) {
        CarFactory.makeCar("Bike").drive();
        CarFactory.makeCar("Bus").drive();
        CarFactory.makeCar("Train").drive();
    }

七、策略模式:

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换,策略模式让算法独立于使用它的客户而独立变化。

  • 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时;
  • 需要安全地封装多种同一类型的操作时;
  • 出现同一抽象类有多个子类,而又需要使用if-else或者switch-case来选择具体子类时。

使用场景:RecyclerView.ViewHolder,一个新闻列表页面,根据不同的viewtype需要分别显示左文右图和左图右文的效果;

创建一个接口,这里使用RecyclerView.ViewHolder

public abstract static class ViewHolder {
        // ...
}

创建实现接口的实体类

static class ViewHolder extends RecyclerView.ViewHolder {
	private ImageView ivIcon;
	private TextView tvZhName;
	private TextView tvEnName;

	public ViewHolder(View view) {
		super(view);
		ivIcon = view.findViewById(R.id.iv_icon);
		tvZhName = view.findViewById(R.id.tv_zh_name);
		tvEnName = view.findViewById(R.id.tv_en_name);
	}
}

根据不同的viewtype创建不同策略(布局)的ViewHolder

public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
	View view = null;
	if (viewType == 15 || viewType == 16 || viewType == 17) {
		view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_long, parent, false);
	} else {
		view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_control, parent, false);
	}
	ViewHolder holder = new ViewHolder(view);
	return holder;
}

八、责任链模式:

避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/46307.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

elasticsearch查询操作(API方式)

说明&#xff1a;elasticsearch查询操作除了使用DSL语句的方式&#xff08;参考&#xff1a;http://t.csdn.cn/k7IGL&#xff09;&#xff0c;也可以使用API的方式。 准备 使用前需先导入依赖 <!--RestHighLevelClient依赖--><dependency><groupId>org.ela…

内存泄漏是什么?有什么危害

内存泄漏是什么&#xff1f;有什么危害 1. 前言1.内存泄漏是什么&#xff1f;2. 为什么会发生内存泄漏3. 内存泄漏的危害4. 总结 1. 前言 在各种项目开发中&#xff0c;内存泄漏是一个很严重的问题。对资源管理、性能优越、系统稳定性&#xff0c;以及是否安全产生极大印象。本…

AndroidStudio设计一个计算器

界面设计 activity_calcuator.xml 设计&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-auto&qu…

2、基于redis实现分布式锁

目录 2.1. 基本实现2.2. 防死锁2.3. 防误删2.4. redis中的lua脚本2.4.1 redis 并不能保证2.4.2 lua介绍 2.5. 使用lua保证删除原子性 2.1. 基本实现 借助于redis中的命令setnx(key, value)&#xff0c;key不存在就新增&#xff0c;存在就什么都不做。同时有多个客户端发送setn…

Easy-Es笔记

一、Easy-ES概述 Easy-Es&#xff08;简称EE&#xff09;是一款由国内开发者打造并完全开源的ElasticSearch-ORM框架。在原生 RestHighLevelClient 的基础上&#xff0c;只做增强不做改变&#xff0c;为简化开发、提高效率而生。Easy-Es采用和MP一致的语法设计&#xff0c;降低…

HDFS异构存储详解

异构存储 HDFS异构存储类型什么是异构存储异构存储类型如何让HDFS知道集群中的数据存储目录是那种类型存储介质 块存储选择策略选择策略说明选择策略的命令 案例&#xff1a;冷热温数据异构存储对应步骤 HDFS内存存储策略支持-- LAZY PERSIST介绍执行使用 HDFS异构存储类型 冷…

C# winform子窗口向父窗口传值

这里我使用一个简单的方法。只需要在父窗口定义一个静态变量就行。 父窗体为Form1,子窗体为Form2。 public static int get_num0; 子窗体直接给get_num赋值即可。 Form1.get_num2; 这样父窗体就能获得get_num修改后这个值了

[start] m40 test

software & update 470 drive version # cd /etc/apt # mv sources.list sources.list.bak # sudo vi /etc/apt/sources.list # 默认注释了源码镜像以提高 apt update 速度&#xff0c;如有需要可自行取消注释 deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ ja…

Flask 笔记

Flask 笔记 一、Flask介绍 1、学习Flask框架的原因 2020 Python 开发者调查结果显示Flask和Django是Python Web开发使用的最主要的两个框架。 2、Flask介绍 ​ Flask诞生于2010年&#xff0c;是Armin ronacher用Python 语言基于Werkzeug工具箱编写的轻量级Web开发框架。 ​…

Matlab 点云平面特征提取

文章目录 一、简介二、实现代码2.1基于k个邻近点2.2基于邻近半径参考资料一、简介 点云中存在这各种各样的几何特征,这里基于每个点的邻域协方差来获取该点的所具有的基础几何特征(如下图所示),这样的做法虽然不能很好的提取出点云中的各个部分,但却是可以作为一种数据预处…

SAP ABAP 用户状态锁定案例

一、前言 项目需求是根据当天及前两天的离职员工信息&#xff08;假设这是一个定时器任务每天下午5点执行程序&#xff0c;计算前两天的员工工号是为了将5点之后办理离职的员工工号找出来&#xff09;&#xff0c;将这些员工在用户表 USR02 中的锁定状态设置为 “64”&#xff…

Emacs之实现鼠标/键盘选中即拷贝外界内容(一百二十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

springboot整合ELK+kafka采集日志

一、背景介绍 在分布式的项目中&#xff0c;各功能模块产生的日志比较分散&#xff0c;同时为满足性能要求&#xff0c;同一个微服务会集群化部署&#xff0c;当某一次业务报错后&#xff0c;如果不能确定产生的节点&#xff0c;那么只能逐个节点去查看日志文件&#xff1b;lo…

SecureCRT如何将复制的内容粘贴到word中仍然保持原有字体颜色

SecureCRT如何将复制的内容粘贴到word中仍然保持原有字体颜色 QQ 109792317 说明&#xff1a;当SecureCRT加载了配色文件后&#xff0c;输出的关键字会被不同颜色高亮显示&#xff0c;但是如果复制粘贴到word中会发现成了纯文本&#xff0c;字体颜色消失了。 如何保留 &#x…

2.java语法

文章目录 2.1. 字符型常量和字符串常量的区别?2.2. 关于注释&#xff1f;2.3. 标识符和关键字的区别是什么&#xff1f;2.4. Java 中有哪些常见的关键字&#xff1f; 2.5. 自增自减运算符2.6. continue、break、和 return 的区别是什么&#xff1f; 2.1. 字符型常量和字符串常…

CCLINK转profinet与西门子PLC通讯

用三菱PLC的控制系统需要和西门子的PLC控制系统交互数据&#xff0c;捷米JM-PN-CCLK 是自主研发的一款 PROFINET 从站功能的通讯网关。该产品主要功能是将各种 CCLINK 总线和 PROFINET 网络连接起来。 捷米JM-PN-CCLK总线中做为从站使用&#xff0c;连接到 CCLINK 总线中做为…

商品分类新建,修改,删除。手机扫码开单打印进销存,商贸批发生产企业仓库条码管理软件系统

商品分类新建&#xff0c;手机扫码开单打印进销存&#xff0c;商贸批发生产企业仓库条码管理软件系统&#xff0c;超市便利店五金茶叶烟酒鞋帽门店零售手机收银管理软件APP_哔哩哔哩_bilibili本期视频讲解&#xff1a;商品分类新建, 视频播放量 1、弹幕量 0、点赞数 0、投硬币枚…

【VCS】(7)Fast Gate-level Verification

Fast Gate-level Verification VCS中SDF反标(Back-Annotation)Lab 门级网表的后仿真DC综合RTL级仿真波形后仿真 网表级的仿真可以验证综合后得到的门级网表和RTL代码是否一致。也可以验证&#xff0c;在加速时序信息&#xff08;SDF&#xff09;之后&#xff0c;设计的功能是否…

数字化采购平台:提升效率、降低成本的未来趋势

随着信息技术的不断发展和应用&#xff0c;数字化采购平台逐渐成为企业采购管理的未来趋势。数字化采购平台是指通过信息化技术在采购过程中实现数字化、自动化和智能化的管理平台。本文将围绕数字化采购平台的应用和优势&#xff0c;探讨其在提升效率、降低成本等方面的重要作…