设计模式的七大原则
1、开闭原则(Open Closed Principle)
对类的扩展是开放,对修改关闭。在程序需要扩展的时候,对于一个类,不要去修改原来的代码,而是通过继承的方式去扩展这个类。
目的:降低维护风险。
2、单一职责原则(Single Responsiblity Principle)
每个类应该有且只有一个职责。
目的:提高可读性。
3、里式替换原则(Liskov Substitution Principle)
子类继承父类时,可以实现父类的抽象方法,不重写父类的方法,子类增加自己特有的方法。
目的:防止继承带来的问题。
4、依赖倒转原则(Dependency Inversion Principle)
程序要依赖于抽象接口,不要依赖于具体实现,针对接口编程。
目的:利于代码升级。
5、接口隔离原则(Interface Segregation Principle)
庞大的接口拆分成更小的和更具体的接口,一个接口只用于一个业务逻辑。
目的:使功能解耦,高内聚、低耦合。
6、迪米特原则(Principle of Least Knowledge)
一个对象应当对 其他 对象尽可能少的了解。
目的:自己做自己的事情。
7、合成复用原则(Composite Reuse Principle)
使用对象组合,而不是继承来达到复用的目的。继承破坏了封装性,父类的任何改变,都可能导致子类出问题。优先考虑 合成复用,A类和B类的合成使用,而不是B继承A的使用。
目的:少用继承 降低耦合。
23种设计模式
23种设计模式分为三类:
创建型模式、结构型模式、行为型模式。
顾名思义,创建型 就是怎么创建对象的。结构型就是对象与对象的关系,变成更大的结构。行为型 就是运行时复杂流程的 控制。
创建型
1、单例模式(Singleton Pattern)
目的:主要就是一个类,频繁的创建,销毁。
优点:内存中只有一个实例,减少开销。
缺点:没有接口,不能继承,违背了单一职责原则。
实现:
1.懒汉式 静态方法,用到的时候再创建对象。
2.饿汉式 静态变量,直接new出对象。
3.双重锁 两个if判断,第一个if是为了防止不必要的线程同步,第二个if判断是为了避免 第二个线程 重复创建对象,volatile 为了防止指令重排。
4.kotlin关键字object也可以创建单例,原理和懒汉式类似,在static块中创建。
5.枚举的方式,枚举编译后,也是在static块中new出对象。
//双重锁
public class Singleton{
private volatile static Singleton instance;
private Singleton(){};
public static Singleton getInstance(){
if(instance==null){
sychronized(Singleton.class){
if(instance==null)
instance=new Singleton();
}
}
return instatnce;
}
}
在Android中有个隐藏抽象类。
public abstract class Singleton<T> {
public Singleton() {
}
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};
这里用来获取了AMS对象,如果获取不到,就通过ServiceManager去获取。这个Singleton是隐藏类,直接用不了,可以直接copy出来用。
2、工厂模式(Factory Pattern)
目的:解决接口选择问题。
优点:想要创建对象,只要知道名字就行,屏蔽了内部实现,只要关心接口。
缺点:增加一个产品的时候,需要增加一个实现类 和 一个工厂,比如Dagger2,新增一个注入的Bean,Dagger2就会为我们生成一个Factory类。空间增大了。
实现:
public interface Clothes {
void getClothes();
}
public class Jacket implements Clothes {
@Override
public void getClothes() {
System.out.println("夹克衫");
}
}
public class Sweater implements Clothes {
@Override
public void getClothes() {
System.out.println("毛衣");
}
}
工厂 假设他是衣柜
public class WardrobeFactory {
public Clothes getShape(String shape) {
switch (shape) {
case "Jacket":
return new Jacket();
case "Sweater":
return new Sweater();
}
return null;
}
}
衣柜假设是个工厂,衣柜里有衣服,抽象出衣服,衣服可以有夹克衫或者是毛衣。
在Android中根据名字去拿对象,比如获取系统服务。
context.getSystemService(Service.ALARM_SERVICE)
String ALARM_SERVICE = "alarm"
3、抽象工厂模式(Abstract Factory Pattern)
目的:解决接口选择问题。
优点:当产品种类很多的时候 ,根据名字拿到的当前产品种类的对象。
缺点:扩展非常困难,增加一个同类新的产品,就需要增加一个新的工厂。
实现:
//裤子
public interface Trousers {
void getTrousers();
}
//牛仔裤
public class Jeans implements Trousers {
@Override
public void getTrousers() {
System.out.println("牛仔裤");
}
}
//短裤
public class Shorts implements Trousers {
@Override
public void getTrousers() {
System.out.println("短裤");
}
}
//衣服
public interface Clothes {
void getClothes();
}
//毛衣
public class Sweater implements Clothes {
@Override
public void getClothes() {
System.out.println("毛衣");
}
}
//夹克衫
public class Jacket implements Clothes {
@Override
public void getClothes() {
System.out.println("夹克衫");
}
}
//衣服和裤子都有了,抽象工厂
//抽象工厂,这个工厂需要完成 那衣服 和 裤子
public abstract class AbsFactory {
public abstract Trousers getTrousers(String trousers);
public abstract Clothes getClothes(String clothes);
}
//生产衣服
public class ClothesFactory extends AbsFactory{
@Override
public Trousers getTrousers(String trousers) {
return null;
}
@Override
public Clothes getClothes(String clothes) {
switch (clothes){
case "Jacket":
return new Jacket();
case "Sweater":
return new Sweater();
}
return null;
}
}
//生产裤子
public class TrousersFactory extends AbsFactory {
@Override
public Trousers getTrousers(String trousers) {
switch (trousers){
case "Shorts":
return new Shorts();
case "Jeans":
return new Jeans();
}
return null;
}
@Override
public Clothes getClothes(String shape) {
retu