Java - core design patterns and principles

(This design pattern is taken from Westward design patterns book knowledge, to explain in C #)

Simple factory pattern

  • Simple factory pattern belongs created schema, simple factory pattern is determined by a factory object which creates an instance of the class of product. Simple factory pattern is the factory model family is the most simple and practical model can be understood as a special mode of realization of different plants.
    Here Insert Picture Description

Strategy Mode

  • Introduction : Object-oriented programming is not better class, the class division is to package, but the classification is based on the abstract, an abstract class is a collection of objects with the same attributes and functions.
  • Strategy Mode: It defines a family of algorithms, encapsulate them, so that they can replace each other, this mode allows changes in the algorithm, will not affect customers using algorithms.
  • Strategy Mode Structure:
    Here Insert Picture Description
    Implications for the existence of this Context:
    Here Insert Picture Description
    The client may want to implement the method implemented by Context.
  • Strategy Pattern Analysis:
  1. Strategy Mode is a way to define a series of algorithms, from the conceptual point of view, all of these algorithms are identical to complete the work, but to achieve different, it can call all the algorithms in the same way, reducing the use of various algorithms class coupling between.
  2. The Strategy for the Context class hierarchy defines a set of algorithms for reuse or behavior, public inheritance analysis helps remove these algorithms.
  3. Strategy is the advantage of simplifying the model unit test, because each class has its own algorithm, can be tested individually by its own interface.
  4. Strategy mode is used to encapsulate the algorithm, but in practice, we can use it to find almost any type of packaging rules, whenever they hear during the analysis of different needs at different times apply business rules, you can consider using strategy pattern the possibility of this change process.

Single Responsibility Principle

  • Single Responsibility Principle On a category, it should only be one the cause of change.
  • ** Note: ** If a class too much to bear the blame, it means these functions coupled together, a change in responsibilities may weaken or inhibit the ability of the class to complete other duties, this coupling will lead to fragile design, when a change occurs, the design will suffer unexpected damage.
  • Software design really many things to do, is to find these duties and responsibilities separated from each other.

开放-封闭原则

  • 开放封闭原则是说软件实体(类,模块,函数等等)应该可以扩展,但是不可以修改。
  • 及:对于扩展是开放的,对于更改是封闭的。
  • 无论模块多么的“封闭”,都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。他必须先猜测出最优可能发生的变化种类,然后构造抽象来隔离这些变化。
  • 当我们最初编写代码时,假设变化不会发生。当变化发生时。我们就创建抽象来隔离以后发生的同类变化。
  • 面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有的代码。
    Here Insert Picture Description
  • 开放封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护、可扩展、可复用、灵活性好。开发人员应该仅对程序中呈现出频繁变化的那些部分做出抽象,然而,对于应用程序中的每个部分都刻意地进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要。切记,切记。

依赖倒置原则

  • 依赖倒转原则
    A.高层模块不应该依赖低层模块。两个都应该依赖抽象
    B.抽象不应该依赖细节。细节应该依赖抽象。
  • 说白了,就是针对接口编程,不要对实现编程。

里氏替换原则

  • 里氏代换原则(LSP):子类型必须能够替换掉它们的父类型。
  • 也正因为有了这个原则,使得继承复用成为了可能,只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。
  • 依赖倒转其实就是谁也不要依靠谁,除了约定的接口,大家都可以灵活自如。
    Here Insert Picture Description

迪米特法则

  • “迪米特法则(LoD)’ 也叫最少知识原则。
  • 迪米特法则(LoD),如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
  • 迪米特法则首先强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限。
  • 迪米特法则其根本思想,是强调了类之间的松耦合
  • 类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。

装饰模式

  • 装饰模式(Decorator), 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

  • 装饰模式结构图:
    Here Insert Picture Description
    Component是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent 是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator, 装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。”

  • 总结:装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。这样做更大的好处就是有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。


代理模式

  • 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问
  • 代理模式结构图:
    Here Insert Picture Description
  • 代理模式应用
  1. 远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
  2. 虚拟代理,是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。这样就可以达到性能的最优化。
  3. 安全代理,用来控制真实对象访问时的权限。
  4. 智能指引,是指当调用真实的对象时,代理处理另外一些事。

观察者模式

  • 观察者模式又叫做发布-订阅(Publish/Subscribe) 模式。
  • 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,
    会通知所有观察者对象,使它们能够自动更新自己。
  • 简单样例图:
    Here Insert Picture Description
  • 观察者模式结构图:
    Here Insert Picture Description
    解析:
  1. Subject类,可翻译为主题或抽象通知者, 一般用一个抽象类或者一个接口实现。它把所有对观察者对象的引用保存在一一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
  2. Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者一般用一个抽象类或者一个接口实现。更新接口通常包含一个Update()方法,这个方法叫做更新方法。
  3. ConcreteSubject类,叫做具体主题或具体通知者,将有关状态存入具体现察者对象;.在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
  4. ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。具体观察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。
  • 观察者模式特点
  1. 将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。 我们不希望为了维持一致性而使各类紧密耦合, 这样会给维护、扩展和重用都带来不便。
  2. 当一个对象的改变需要同时改变其他对象的时候 ,而且它不知道具体有多少对象有待改变,应该考虑使用观察者模式
  3. 当一个抽象模型有两个方面,其中一方面依赖于另一方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。总的来讲,观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
  • 观察者模式的不足
    尽管已经用了依赖倒转原则,但是‘抽象通知者’还是依赖‘抽象 观察者’,也就是说,万一没有 了抽象观察者这样的接口,我这通知的功能就完不成了。另外就是每个具体观察者,它不一定是‘更新’的方法要调用呀,就像我希望的是‘工具箱’是隐藏,‘自动窗口’
    是打开,这根本就不是同名的方法。这应该就是不足的地方吧。”

解决方案 -->> 事件委托实现

  • “抽象通知者”由于不希望依赖“抽象观察者”,所以“增加”和“减少”的方法也就没有必要了(抽象观察者已经不存在了)。
  • 事件委托说明
  1. 委托就是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值。委托可以看作是对函数的抽象,是函数的‘类’,委托的实例将代表一个具体的函数。
  2. 一个委托可以搭载多个方法,所有方法被依次唤起。更重要的是,它可以使得委托对象所搭载的方法并不需要属于同一个类。
  3. 委托也是有前提的,那就是委托对象所搭载的所有方法必须具有相同的原形和形式,也就是拥有相同的参数列表和返回值类型。

抽象工厂模式

前言:

  • 用了工厂方法模式的数据访问程序
    Here Insert Picture Description
  • 用了抽象工厂模式的数据访问程序
    Here Insert Picture Description
  • 抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
  • 抽象工厂模式结构图:
    Here Insert Picture Description
  • “AbstractProductA 和 AbstractProductB是两个抽象产品,之所以为抽象,是因为它们都有可能有两种不同的实现,就刚才的例子来说就是User和Department,而 ProductA1、ProductA2 和ProductB1,ProductB2就是对两个抽象产品的具体分类的实现,比如ProductA1可以理解为是SqlserverUser,而ProductB I是AccessUser。
  • 这么说,IFactory 是一个抽象工厂接口,它里面应该包含所有的产品创建的抽象方法。而ConcreteFactory1和ConcreteFactory2就是具体的工厂了。就像SqlserverFactory和AccessFactory一样。通常是在运行时刻再创建一个 ConcreteFactory类的实例,这个具体的工厂再创建具有特定实现的产品对象,也就是说,为创建不同的产品对象,客户端应使用不同的具体工厂。”
  • 抽象工厂模式的优点与缺点
  1. 最大的好处便是易于交换产品系列,由于具体工厂类,例如 IFactory factory = new AccessFactory(),在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。
  2. 我们的设计不能去防止需求的更改,那么我们的理想便是让改动变得最小,现在如果你要更改数据库访问,我们只需要更改具体工厂就可以做到。第二大好处是,它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
  3. 是个模式都是会有缺点的,都有不适用的时候,要辨证地看待问题哦。抽象工厂模式可以很方便地切换两个数据库访问的代码,但是如果你的需求来自增加功能,比如我们现在要增加项目表Project,那就至少要增加三个类,IProject、 SqIserverProject、 AccessProject, 还需要更改 IFactory、SqlserverFactory和 AccessFactory才可以完全实现。啊,要改三个类,这太糟糕了。
  • 编程是门艺术,大批量的改动,显然是非常丑陋的做法。

用简单工厂来改进抽象工厂

  • 结构图:
    Here Insert Picture Description
  • 抛弃了IFactory、 SqlserverFactory 和AccessFactory三个工厂类,取而代之的是DataAccess 类,由于事先设置了db的值(Sqlserver或Access),所以简单工厂的方法都不需要输入参数,这样在客户端就只需要 DatAccess.CreateUser和DataAccess.CreateDepartment()来生成具体的数据库访问类实例,客户端没有出现任何一个SQL Server或Access 的字样,达到了解耦的目的。

用反射+抽象工厂的数据访问程序

  • 结构图:
    Here Insert Picture Description

用反射+配置文件实现数据访问程序

  • 添加一个 config 文件:
    Here Insert Picture Description
  • 现在我们应用了反射+抽象工厂模式解决了数据库访问时的可维护、可扩展的问题。从这个角度上说,所有在用简单工厂的地方,都可以考虑用反射技术来去除 switch 或 if,解除分支判断带来的耦合

适配器模式

  • 适配器模式(Adapter),将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一
    起工作的那些类可以一起工作。
  • 在软件开发中,也就是系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况,比如在需要对早期代码复用一些功能等应用上很有实际价值。
  • 适配器模式(Adapter)结构图:
    Here Insert Picture Description
何时使用适配器模式?
  • 两个类所做的事情相同或相似,但是具有不同的接口时要使用它。客户代码可以统一调用同一接口就行了,这样可以更简单、更直接、更紧凑。
  • 并且,要在双方都不太容易修改的时候再使用适配器模式适配。
  • 样例结构图:
    Here Insert Picture Description
    尽管外籍球员曾经是不太懂英文,尽管教练和球员也不会学中文,但因为有了翻译者, 团队沟通合作成为了可能。
  • 需要注意的是
    如果能事先预防接口不同的问题,不匹配问题就不会发生;在有小的接口不统一问题发生时,及时重构,问题不至于扩大;只有碰到无法改变原有设计和代码的情况时,才考虑适配。事后控制不如事中控制,事中控制不如事前控制

单例模式

  • Singleton pattern (the Singleton) , to ensure that only one instance of a class, and it provides access to a global access point.
  • Usually we can make a global variable makes an object is accessed, but it can not prevent you from instantiating multiple objects. One of the best way is to make the class itself responsible for the preservation of its unique instance. This class can ensure that no other instances can be created, and it can provide a method to access the instance.
  • Singleton pattern (the Singleton) Structure:
    Here Insert Picture Description
  • Benefits include: such as Singleton Singleton class encapsulates its sole instance, so that it can strictly control the customer how to access it and when to access it. Simply put, is controlled access to the only instance.
  • When multiple threads access a single case, it is possible to solve the problem might cause multiple instances created with the lock. Or, use the static initialization method:
    Here Insert Picture Description
  • Because of this approach is static initialization will own instantiated when they have been loaded, it is figuratively referred starving formula singleton class , the original singleton approach is to when first referenced, examples of his will, so it is called lazy formula singleton class .
  • Singletons are many many implementations, starving and lazy single embodiment only single embodiment and comparison of two main conventional methods singleton . , Lazy style singleton pattern is a thread might be a security risk.

...... to be continued, continuously updated

Published 58 original articles · won praise 7 · views 9243

Guess you like

Origin blog.csdn.net/Mr_OO/article/details/102838329