设计模式学习——设计原则与设计模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Wengwuhua/article/details/84197848

设计原则和模式
一、设计原则
1、单一职责原则:就一个类而言,应该仅有一个引起它变化的原因。换句话说,一个类的功能要单一,只做与它有关的事。(android的四大组件)
2、开放封闭原则:一个软件实体应该对外扩展开放,对修改封闭。对扩展开放意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况;对修改封闭,意味着类一旦设计完成,就可以独立工作,而不要对类进行任何的修改。
(1)开放封闭原则是所有面向对象原则的核心。
(2)如何做到开放封闭原则?——封装变化,依赖接口和抽象类,而不要依赖具体实现类。要针对接口和抽象类编程,不要针对具体实现编程。
3、里氏代换原则(LSP):指一个软件实现如果使用的是基类,那么也一定适用于其子类,而且它根本察觉不出使用的是基类对象还是子类对象;反过来的代换是不成立的,即使用一个类的子类对象,那么它不能够适用于基类对象。也就是说,子类必须能够替代他们的基类。抽象
(1)里氏代换原则讲的是基类和子类的关系,是实现开放封闭原则的具体规范。
(2)违背了里氏代换原则就一定不符合开放封闭原则。
4、迪米特法则:又称最少知识原则(LKP),也就是说,一个对象应当对其他对象尽可能少地了解。(android的NDK开发)
(1)狭义的迪米特法则:如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
(2)广义的迪米特法则:一个模块设计好坏的一个重要标志就是该模块在多大程度上将自己内部数据与实现的有关细节隐藏起来。
(3)应用迪米特法则到系统的设计中,要注意一下几点:
A、在类的划分上,应当创建弱耦合的类,类与类之间的耦合越弱,就越利于实现可复用的目标;
B、在类的结构设计上,每个类都应该降低成员的访问权限;
C、在类的设计上,只要有可能,一个类应当写成不变的类;
D、在对其他类的应用上,一个对象对其他类的对象的应用应该降到最低;
E、尽量限制局部变量的有效范围。
5、依赖倒置原则:依赖倒置指代了一种特定的解耦方式,使得高层次的模块不依赖于低层次的模块的实现细节。模块间的依赖关系通过抽象实现,实现类之间不发生直接的依赖关系,其依赖关系通过接口或抽象产生。即面向抽象编程。
依赖倒置原则的几个关键点:
(1)高层模块不依赖低层模块,两者都应该依赖其抽象;
(2)抽象不应该依赖细节
(3)细节应该依赖抽象
6、接口隔离原则:客户端不应该依赖它不需要的接口。即类间的依赖关系应该建立在最小的接口上。
(1)接口隔离原则的目的是系统解开耦合,从而容易重构、更改和重新部署。

有些书把5,6并为下面原则:
合成聚合复用原则(CARP):又称合成复用原则(CRP)。是指在一个新的对象中使用原来已经存在的一些对象,使这些原来已经存在的对象成为新对象的一部分,新的对象通过向这些原来已经具有的对象委派相应的动作或者命令达到复用已有功能的目的。
(1)简洁的表述:要尽量使用合成和聚合,尽量不要使用继承。
(2)聚合是关联关系的一种,用来表示一种整体和部分的拥有关系。整体持有对部分的引用,可以调用部分的能够被访问的方法和属性等;作为部分可以同时被多个新的对象引用,同时为多个新的对象提供服务。
(3)合成也是关联关系的一种,但比聚合强得多。在合成关系里,部分和整体的生命周期是一样的。作为整体的新对象是完全拥有对作为部分的支配权。一个合成关系中的成员对象是不能和另外的一个合成关系 共享的。

二、设计模式
1、简单工厂模式:属于类的创新型模式,又称静态工厂方法模式,通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
(1)包含的角色及其职责:
A、工厂角色:这是简单工厂模式的核心,由它负责创建所有类的内核逻辑。能够被外界调用,创建所需的产品对象。
B、抽象产品角色:简单工厂模式所创建的所有对象的父类(可以是接口也可以是抽象类),负责描述所有实例所共有的公共接口。
C、具体产品角色:简单工厂所创建的具体实例对象。
(2)核心思想:有一个专门的类来负责创建实例的过程。
(3)优缺点
优点:用户无需了解对象是如何创建及如何组织的,有利于整个软件体系结构的优化。
缺点:违背单一职责原则和开放封闭原则。
(4)android中简单工厂模式之一就是获取服务的系统方法“getSystemService”
(5)实质是选择实现的过程。
2、工厂方法模式:同样属于类的创建型模式,又称多态工厂模式。意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
(1)包含的角色及其职责:
A、抽象工厂角色:这是工厂方法模式的核心,任何工厂类都必须实现这个接口。
B、具体工厂角色:具体工厂类是抽象工厂的一个实现,负责实例化产品对象。
C、抽象产品角色:简单工厂模式所创建的所有对象的父类(可以是接口也可以是抽象类),负责描述所有实例所共有的公共接口。
D、具体产品角色:简单工厂所创建的具体实例对象。
(2)工厂方法模式解决的是同一系列产品的创建问题。
(3)优缺点
优点:当系统拓展需要添加新的产品对象时,仅需添加一个具体对象以及一个具体工厂对象,原有工厂对象不需修改。很好符合开放封闭原则。
缺点:把简单工厂模式的内部判断逻辑转移到了客户端,客户端需要决定实例化哪一个具体的工厂。
(4)android的activity和service等核心组件中都定义了onCreate()方法。

3、抽象工厂模式:是所有形态 的工厂模式中最为抽象和最具一般性的。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品类型的情况下,能够创建多个产品族的产品对象。
(1)包含的角色及其职责:
A、抽象工厂角色:这是工厂方法模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。
B、具体工厂角色:具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。
C、抽象产品角色:抽象模式所创建的所有对象的父类(可以是接口也可以是抽象类),负责描述所有实例所共有的公共接口。
D、具体产品角色:抽象模式所创建的具体实例对象。
(2)工厂方法模式针对的是一个产品等级结构;而抽象工厂模式针对的是多个产品等级结构。
(3)优缺点
优点:客户端不再负责对象的具体创建,而是把这个任务交给了具体工厂类,客户端只负责对对象的调用。
缺点:新产品加入时,需要修改抽象工厂类的设计,导致要修改所有具体工厂类。
(4)android应用开发中涉及到的IPC通信就是抽象工厂模式很好的说明。

4、单例模式:是一种对象创建型模式。保证一个类只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。
(1)单例模式的要点:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
(2)单例模式的版本:
A、饿汉式:即当类加载进来时就立即实例化对象,但这种方式比较消耗计算机资源。
B、懒汉式:要使用时才实例化,但多线程下存在线程安全问题。
C、在懒汉式的基础上对函数进行同步的方式。

如何实现懒汉式的线程安全?

加上synchronized即可

public static synchronized Singleton getInstance(){}
但这样会降低整个访问的速度,而且每次都要判断。可以用双重检查加锁。

双重加锁机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例。这是第二重检查。

双重加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。

/**

  • 双重检查加锁的单例模式
  • @author dream

*/
public class Singleton {

/**
 * 对保存实例的变量添加volitile的修饰
 */
private volatile static Singleton instance = null;
private Singleton(){

}

public static Singleton getInstance(){
    //先检查实例是否存在,如果不存在才进入下面的同步块
    if(instance == null){
        //同步块,线程安全的创建实例
        synchronized (Singleton.class) {
            //再次检查实例是否存在,如果不存在才真正的创建实例
           if(instance==null) instance = new Singleton();
        }
    }
    return instance;
}

}

(3)优缺点
优点:只需要调用一个单一的方法即可生成一个唯一的实例,有利于节约资源。
缺点:很难实现序列化,导致难以被持久化,难以通过网络传输;无法在继承结构中使用。
(4)android中单例模式无处不在,例如对服务的管理者ServiceManager就采用了单例模式。

5、原型模式:是一种对象创建型模式,它采取负责原型对象的方法来创建对象的实例。使用原型模式创建的实例,具有与原型一样的初始化数据。
(1)原型模式涉及角色:
A、客户端角色:客户端提供创建对象的请求。
B、抽象原型角色:通常由一个java接口或者java抽象类来实现, 为具体原型设立好规范。
C、具体原型角色:被复制的具体对象,此具体角色实现了抽象原型角色所要求实现的方法。
(2)java在语言级别时直接支持原型模式的,java.lang.Object是一切类和接口的父类,它提供了一个clone()方法来支持原型模式。一个有被复制能力的对象要实现Cloneable接口。
复制有浅复制和深复制之分,浅复制是对基本数据类型和string类型而言的,深复制是对其他引用类型而言的。
(3)优缺点
优点:允许动态地增加或减少产品类;提供简化的创建结构;具有给一个应用软件动态加载新功能的能力;产品类不需要事先确定等级结构,因为原型模式适用于任何的等级结构。
缺点:每个类都要配备一个复制方法,对已有的类来说不一定容易,对深层的复制也要编写不少代码。

6、建造者模式:又称生成器模式。是一种对象创建型模式,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。
(1)建造者模式涉及角色:
A、抽象建造者角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。
B、具体建造角色:这个角色产品实现了抽象建造者接口,主要完成分步创建产品并提供产品对象的实例。是一些与应用程序紧密相关的一些类。
C、导演者角色:具有指挥使用哪个具体创造者来完成产品的创建,是创建工作的调用者。
D、产品角色:就是建造中的复杂对象,一般只有对于复杂对象的创建才使用建造者模式。
(2)建造者模式将复杂对象的构建与对象的表现分离开来,这样使同样的构建过程可以创建出不同的表现。
(3)优缺点
优点:客户端不用再直接负责对象的创建,而是把这些任务交给了具体的创建者类,把具体的如何组装的责任交给了导演者类,客户端之负责对象的调用即可。
缺点:如果产品差别较大,会导致非常多的具体的创建者。
(4)在android中AlertDialog的构造是建造者模式的一个非常经典的实现。

7、装饰模式:又称包装模式。通过一种对客户端透明的方式来扩展对象的功能,是继承关系的一个替代方案。
(1)装饰模式涉及角色:
A、抽象组件角色:一个抽象接口,是被修饰类和修饰类的父接口。
B、具体组件角色:为抽象组件的实现类。
C、抽象装饰角色:包含一个组件的引用,并定义了与抽象组件一致的接口。
D、具体装饰角色:为抽象装饰角色的实现类,负责具体的装饰。
(2)优缺点
优点:比继承关系更灵活地扩展对象的功能,可以构造出很多种不同种类的修饰结果。
缺点:很多修饰类,产生管理问题;产生不合逻辑的对象;比较容易出错,且出错后不易排查。
(3)java的IO库中很好地使用了这种模式,如DataOutputStream等等。

猜你喜欢

转载自blog.csdn.net/Wengwuhua/article/details/84197848
今日推荐