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;
}
八、责任链模式:
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。