前篇:
1.公共技术点之面向对象六大原则
解决:你是不是经常遇到一个类自己都不知道里面有什么方法。用封装的方法时都不知道在那个类里找。更有甚者,随着项目的复杂,迭代后,一个同样的功能,写了多个不同方法在不同类中。这个时候你就要看看1.单一职责原则。
1.单一职责原则
单一职责原则的英文名称是Single Responsibility Principle,简称是SRP,也就是一个类只做一件事。
如:接口名定义类只写接口的参数
public class HttpConstants {
/* 用户登录,可用QQ,微信,微博等第三方帐号一键登录。 /
public static final byte LOGIN = 0x01;
/* ·新用户需要注册,成功后返回登录页面。 /
public static final byte REGISTERED = 0x03;/* ·4.[编号1.3] 版本更新接口 。 /
public static final byte GETVERSION = 0x04;/* ·5.[编号1.4] 帐号关联接口 /
public static final byte RELATEDACCOUNT = 0x05;/* ·忘记密码,发送验证码到手机端 /
public static final byte SMSVALIDATE = 0x06;
最简单的例子:
每次我们要用Textview属性的时候,会直接“.”(tv.setText(“”));因为TextView的方法都在TextView类里。简单的理解也就是:
建议以下几个类,遵循这一原则的类:
工具类如:网络求请求封类,项目特定限制类,特定功能性类。
2.里氏替换原则 ( Liskov Substitution Principle)
面向对象的语言的三大特点是继承、封装、多态,里氏替换原则就是依赖于继承、多态这两大特性。简单的来说:善写基类,使用统一方法调用。
例子:几乎每一Activity都要有网络请求,有网络请求的地方,都需要处理3种状况。这时我们就要在基类里用统一的方法名定义。
第一步:接口类
public interface HttpCallback {
/**
*
* @param result
* 回调参数
* @param code
* 回调标记位
*/
abstract void onSuccess(String result, int code);
/**
*
* @param code
* 回调标记位
*/
abstract void onStart(int code);
/**
*
* @param code
* 回调标记位
*/
abstract void onFailure(int code);
}
第二步:基类实现接口
public abstract class BaseActivity extends FragmentActivity implements
HttpCallback {
第三步:继承基类方法
public class MainActivity extends BaseActivity
最终效果就是:
- 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
- 提高代码的重用性;
- 提高代码的可扩展性,实现父类的方法就可以“为所欲为”了,很多开源框架的扩展接口都是通过继承父类来完成的;
- 提高产品或项目的开放性。
建议以下几种情况,遵循这一原则:
- 网络请求
- 刷新 ResetDate
- 清空图片缓存 ClearDate
- 设置监听事件 public abstract void setListener();
3.依赖倒置原则 (Dependence Inversion Principle)
解决:不同的对象需要做同样的事。
定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。
解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。
依赖倒置原则基于这样一个事实:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定的多。在java中,抽象指的是接口或者抽象类,细节就是具体的实现类,使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
依赖倒置原则的核心思想是面向接口编程
举一个具体的例子:
上面我们说到要实现里氏替换原则。整个项目用网络请求成功,失败,取消。用统一的方法名。上面我们继承的是BaseActivity。但是我们现在又有了Fragment里面也有网络请求时怎么办。同样的。我们
public abstract class BaseFragment extends Fragment implements FramentAction,
就能实现。这就是叫做:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。也就是依赖倒置原则。
建议以下几种情况,遵循这一原则
实现接口用法:设置按钮事件。implements OnClickListener
4.开闭原则 ( Open-Close Principle )
开闭原则的核心是:对扩展开放,对修改关闭
解决:接收旧项目,如果不想大动代码。
例子:
老项目:
定义一个接口,寻找美女
package com.loulijun.chapter6;
public interface IFindGirl
{
//年龄
public int getAge();
//姓名
public String
getName();
//长相
public String
getFace();
//身材
public String
getFigure();
}
实现这个接口
package com.loulijun.chapter6;
public class FindGirl
implements IFindGirl
{
private String
name;
private int age;
private String
face;
private String
figure;
public FindGirl(String
name, int age,
String face, String figure)
{
this.name= name;
this.age
= age;
this.face
= face;
this.figure
= figure;
}
@Override
public int getAge()
{
return age;
}
@Override
public String
getFace() {
return face;
}
@Override
public String
getFigure() {
return figure;
}
@Override
public String
getName() {
return name;
}
#} #
场景:大街上
package com.loulijun.chapter6;
import java.text.NumberFormat;
import java.util.ArrayList;
public class Street
{
private final static ArrayList<IFindGirl>
girls = new ArrayList<IFindGirl>();
//静态初始化块
static
{
girls.add(new FindGirl("张含韵",23,"可爱型","165cm/47kg"));
girls.add(new FindGirl("高圆圆",33,"时尚型","165cm/48kg"));
girls.add(new FindGirl("章泽天",19,"清纯型","168cm/47kg"));
}
public static void main(String
args[])
{
System.out.println("----------美女在这里----------");
for(IFindGirl
girl:girls)
{
System.out.println("姓名:"+girl.getName()+"
年龄:"+girl.getAge()+
"
长相:"+girl.getFace()+"
身材:"+girl.getFigure());
}
}
}
运行结果:
———-美女在这里———-
姓名:张含韵 年龄:23 长相:可爱型 身材:165cm/47kg
姓名:高圆圆 年龄:33 长相:时尚型 身材:165cm/48kg
姓名:章泽天 年龄:19 长相:清纯型 身材:168cm/47kg
但是如果想独立分出一个外国美女的类别的话(比如增加一个国籍),可以通过修改接口、修改实现类、通过扩展来实现。
如果修改接口,也就意味着修改实现类,这样对项目的变动太大了,所以不推荐
如果修改实现类,这样虽能解决问题,但是明显有些牵强,如果需要其他变动的时候会显得逻辑混乱
所以,通过扩展来实现是最简单的方式
如何扩展:
可以定义一个IForeigner接口继承自IFindGirl,在IForeigner接口中添加国籍属性getCountry(),然后实现这个接口即可,然后就只需要在场景类中做稍微修改就可以了
package com.loulijun.chapter6;
public interface IForeigner
extends IFindGirl
{
//国籍
public String
getCountry();
}
实现接口
# # package com.loulijun.chapter6;
public class ForeignerGirl
implements IForeigner
{
private String
name;
private int age;
private String
country;
private String
face;
private String
figure;
public ForeignerGirl(String
name, int age,
String country, String face, String figure)
{
this.name
= name;
this.age
= age;
this.country
= country;
this.face
=face;
this.figure
= figure;
}
@Override
public String
getCountry() {
//
TODO Auto-generated method stub
return country;
}
@Override
public int getAge()
{
//
TODO Auto-generated method stub
return age;
}
@Override
public String
getFace() {
//
TODO Auto-generated method stub
return face;
}
@Override
public String
getFigure() {
//
TODO Auto-generated method stub
return figure;
}
@Override
public String
getName() {
//
TODO Auto-generated method stub
return name;
}
}
然后在场景类中只需要修改如下代码即可,其他不变
girls.add(new ForeignerGirl(“Avirl”,28,”美国”,”性感型”,”160cm/45kg”));
不过这些设计原则到不是绝对的,而是根据项目需求,实际需求来定夺使用
来源:http://blog.youkuaiyun.com/chary8088/article/details/38454247
5.接口隔离原则 (Interface Segregation Principle)
解决:处女座的感观,只用所需。
接口隔离原则的含义是:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。本文例子中,将一个庞大的接口变更为3个专用的接口所采用的就是接口隔离原则。在程序设计中,依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
例子:就拿上面的网络请求来说吧。
第一步:接口类
public interface HttpCallback {
/**
*
* @param result
* 回调参数
* @param code
* 回调标记位
*/
abstract void onSuccess(String result, int code);
/**
*
* @param code
* 回调标记位
*/
abstract void onStart(int code);
/**
*
* @param code
* 回调标记位
*/
abstract void onFailure(int code);
}
如果实现这个接口。就必须实现接口的所有方法。但是有的界面只需要请求成功,和失败的标记。不需要onStart(),怎么办呢?
这个时候我们就需要
interface I1 {
public void onFailure(int code);
}
interface I2 {
public void onSuccess(String result, int code);
public void onFailure(int code);
}
怎么用呢。
之前是:
public abstract class BaseActivity extends FragmentActivity implements
HttpCallback {
现在是。
public abstract class BaseActivity extends FragmentActivity implements
I1, I2 {
6.迪米特原则 ( Law of Demeter )
定义:一个对象应该对其他对象保持最少的了解。
解决:多人开发过程中,B以为A做了。A以为B做了。实际上都没做。
如何解决。尽量降低类与类之间的耦合。
我是A。我需要数据m。但是B穿过来的,是(m-2).这个时候B就违反了这一原则。
B就的把值改成(m-2)+2传过来;