Java23种设计模式详解(一)「终于解决」

Java23种设计模式详解(一)「终于解决」今天起为大家带来Java的23种设计模型详解,共分为6篇教程,今天带来第1篇。Java的设计模式三大类创建型模式:工厂方法模式,抽象工厂模式,单

欢迎大家来到IT世界,在知识的湖畔探索吧!

Java23种设计模式详解(一)「终于解决」

今天起为大家带来Java的23种设计模型详解,共分为6篇教程,今天带来第1篇。

首先,了解23种设计模式的基本概念。

Java的设计模式三大类

创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。

结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。

行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

设计模式遵循的原则有6个

1、开闭原则(Open Close Principle)对扩展开放,对修改关闭。

2、里氏代换原则(Liskov Substitution Principle)只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。

3、依赖倒转原则(Dependence Inversion Principle)这个是开闭原则的基础,对接口编程,依赖于抽象而不依赖于具体。

4、接口隔离原则(Interface Segregation Principle)使用多个隔离的接口来降低耦合度。

5、迪米特法则(最少知道原则)(Demeter Principle)一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

6、合成复用原则(Composite Reuse Principle)原则是尽量使用合成/聚合的方式,而不是使用继承。继承实际上破坏了类的封装性,超类的方法可能会被子类修改。

接下来,23种设计模式详解开始。

1.策略模式(Strategy Pattern)

策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。

相互替换:也就是说它们具有共性,而它们的共性就体现在策略接口的行为上,另外为了达到最后一句话的目的,也就是说让算法独立于使用它的客户而独立变化,我们需要让客户端依赖于策略接口。

我们先定义一个场景:ˈ刘备去江东娶媳妇,走之前诸葛亮给赵云(伴郎)了一个锦囊,里面有三个妙计,这三个妙计能帮刘备顺利取上媳妇。

妙计模板:

public interface Strategy {
 public void operate();
}

欢迎大家来到IT世界,在知识的湖畔探索吧!

A妙计:

欢迎大家来到IT世界,在知识的湖畔探索吧!public class AStrategy implements Strategy{
 @Override
 public void operate() {
 System.out.println("找乔国老帮忙,让吴国太给孙权施加压力");
 }
}

B妙计:

public class BStrategy implements Strategy{
 @Override
 public void operate() {
 System.out.println("求吴国太开个绿灯,放行");
 }
}

C妙计:

欢迎大家来到IT世界,在知识的湖畔探索吧!public class CStrategy implements Strategy{
 @Override
 public void operate() {
 System.out.println("孙夫人断后,挡住追兵");
 }
}

装妙计的锦囊即策略的应用场景:

public class Kit {
 private Strategy straegy;
 //构造函数,你要使用那个妙计
 public Kit(Strategy straegy) {
 this.straegy = straegy;
 }
 //使用计谋
 public void operate(){
 this.straegy.operate();
 }
}

使用者赵云:

public class zhaoYun {
 public static void main(String[] args){
 Kit kit;
 //使用第一个妙计
 kit=new Kit(new AStrategy());
 kit.operate();
 //使用第二个妙计
 kit=new Kit(new BStrategy());
 kit.operate();
 //使用第三个妙计
 kit=new Kit(new CStrategy());
 kit.operate();
 }
}

结果:

Java23种设计模式详解(一)「终于解决」

结论:

策略模式的第一个特点就是扩展性,即OCP,可以继续增加,只要修改应用场景即可;其次,策略模式决定权在用户,系统本身提供不同方法的实现,对各种方法做封装。因此,策略模式多用在算法决策系统中,外部用户只需要决定用哪个算法即可。

2.代理模式(Proxy Pattern)

代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候会去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做,此处的代理就是这个意思。再如我们有的时候打官司,我们需要请律师,因为律师在法律方面有专长,可以替我们进行操作,表达我们的想法。

我们假设一个场景:梁山伯看上了祝英台,他就请媒婆去祝英台家提亲;前提是媒婆得知道梁山伯有什么没有什么吧,不然祝英台他们家要彩礼,梁山伯拿不出来咋整,所以梁山伯和媒婆要实现同一个接口(familyStatus);

public interface familyStatus {
 public void marriagePropose();
}

梁山伯:

public class liangShanBo implements familyStatus {
 @Override
 public void marriagePropose() {
 System.out.print("我想娶英台");
 }
}

媒婆:

public class Matchmaker implements familyStatus{
 private familyStatus familyStatus;
 public Matchmaker() {
 //默认无参构造是梁山伯的代理
 this.familyStatus = new liangShanBo();
 }
 public Matchmaker(familyStatus familyStatus) {
 //也可以是任何人的代理
 this.familyStatus = familyStatus;
 }
 @Override
 public void marriagePropose() {
 this.familyStatus.marriagePropose();
 }
}

祝英台:

public class zhuYingtai {
 public static void main(String[] args){
 Matchmaker mm=new Matchmaker();
 mm.marriagePropose();
 }
}

结果:

Java23种设计模式详解(一)「终于解决」

结论:看似媒人在做,其实是梁山伯的想法。

代理模式主要实现了Java的多态,干活的是被代理类,代理类主要是跑腿。那怎么能知道被代理类能不能干活,简单,同根就成,实现同一个接口,大家知根知底,你能做啥我清楚的很。

在开发过程中,如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:

1、修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。

2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。

使用代理模式,可以将功能划分的更加清晰,有助于后期维护!

3.单例模式(Singleton Pattern)

单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:

1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。

2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。

3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。

我们假设一个场景:大臣参拜皇帝,今天肯定只有一个皇帝,明天也肯定只有一个皇帝,皇帝绝对不可能出现两个,这就是妥妥的单例模式。

皇帝:

public class Emperor {
 //先定义一个皇帝放在这儿
 private static Emperor emperor=null;
 public Emperor() {
 //世俗和道德约束,不产生第二个皇帝
 }
 public static Emperor getInstance(){
 //如果没有定义皇帝,定义一个
 if (emperor==null){
 emperor=new Emperor();
 }
 return emperor;
 }
 public static void EmperorInfo(){
 //皇帝是谁
 System.out.println("唐玄宗");
 }
}

大臣:

public class Minister {
 public static void main(String[] args){
 Emperor emperor1= Emperor.getInstance();
 //昨天的皇帝是谁
 emperor1.EmperorInfo();
 Emperor emperor2= Emperor.getInstance();
 //今天的皇帝是谁
 emperor2.EmperorInfo();
 }
}

结果:

Java23种设计模式详解(一)「终于解决」

像这样毫无线程安全保护的类,如果我们把它放入多线程的环境下,肯定就会出现问题了,如何解决?我们先写一个通用的单例程序分析一下:

public class Emperor {
 //先定义一个皇帝放在这儿
 private static Emperor emperor=null;
 public Emperor() {
 //世俗和道德约束,不产生第二个皇帝
 }
 public Emperor getInstance(){
 //如果没有定义皇帝,定义一个
 if (this.emperor==null){
 this.emperor=new Emperor();
 }
 return this.emperor;
 }
 public static void EmperorInfo(){
 //皇帝是谁
 System.out.println("唐玄宗");
 }
}

假如现在两个线程A.B,A执行到this.emperor=new Emperor()正在申请内存分配,这时候B执行到了if (this.emperor==null),这时候是true还是false?如果是true,线程往下走,是不是就出现两个实例了?如果在程序中出现这样的问题会如何呢?最可怕的是你觉得代码并没问题,这是最可怕的;怎么解决呢?最简单的一种解决方式:

直接new一个对象传递给类的成员变量,用的时候getInstance()直接给你返回来:

public class Emperor {
 //先定义一个皇帝放在这儿
 private static final Emperor emperor=new Emperor();
 public Emperor() {
 //世俗和道德约束,不产生第二个皇帝
 }
 public synchronized static Emperor getInstance(){
 return emperor;
 }
 public static void EmperorInfo(){
 //皇帝是谁
 System.out.println("唐玄宗");
 }
}

以上代码也可以这样实现:

public class Emperor {
 //先定义一个皇帝放在这儿
 private static Emperor emperor=null;
 public Emperor() {
 //世俗和道德约束,不产生第二个皇帝
 }
 private static synchronized void syncInit() {
 if(emperor ==null){
 emperor=new Emperor();
 }
 }
 public static Emperor getInstance(){
 if(emperor==null){
 syncInit();
 }
 return emperor;
 }
 public static void EmperorInfo(){
 //皇帝是谁
 System.out.println("唐玄宗");
 }
}

通过单例模式的学习告诉我们:

1、单例模式理解起来简单,但是具体实现起来还是有一定的难度。

2、synchronized关键字锁定的是对象,在用的时候,一定要在恰当的地方使用(注意需要使用锁的对象和过程,可能有的时候并不是整个对象及整个过程都需要锁)。

4.多例模式(Multition Pattern)

没上限的多例模式太简单,和你随便new没差别,咱们来一个有上限的;历史上有没有两个皇帝过,有!明英宗朱祁镇和明景帝朱祁钰,大臣们都懵逼了。

皇帝:

public class Emperor {
 //最多两皇帝
 private static int maxNumOfEmperor=2;
 //皇帝列表
 private static ArrayList EmperorList=new ArrayList(maxNumOfEmperor);
 //皇帝叫什么名字
 private static ArrayList EmperorInfoList=new ArrayList(maxNumOfEmperor);
 //那个皇帝掌着权
 private static int countOfEmperor=0;
 //先把皇帝产出来
 static{
 for(int i = 0; i<maxNumOfEmperor; i++){
 EmperorList.add(new Emperor("皇"+(i+1)+"帝"));
 }
 }
 private Emperor(){
 //约束最多两个皇帝
 }
 private Emperor(String info){
 EmperorInfoList.add(info);
 }
 public static Emperor getInstance(){
 Random random=new Random();
 countOfEmperor=random.nextInt(maxNumOfEmperor);
 return (Emperor) EmperorList.get(countOfEmperor);
 }
 public static void EmperorInfo(){
 //皇帝是谁
 System.out.println(EmperorInfoList.get(countOfEmperor));
 }
}

大臣:

public class Minister {
 public static void main(String[] args){
 //10个大臣
 int ministerNum=10;
 for(int i=0;i<10;i++){
 Emperor emperor= Emperor.getInstance();
 System.out.print("第"+(i+1)+"个大臣参拜的是:");
 emperor.EmperorInfo();
 }
 }
}

结果:

Java23种设计模式详解(一)「终于解决」

如果就只想拜哪一个皇帝,怎么办呢?

getInstance(param);

关注微信公众号「Java大联盟」,关注即可获取海量学习干货,同时还有不定期送书,键盘,鼠标等粉丝福利。

Java23种设计模式详解(一)「终于解决」

赶快来关注一波,海量资源拿到手软。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/13304.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信