第七章 设计模式

时间:2022-10-13 19:21:43

  • 架构:简单的说架构就是一个蓝图,是一种设计方案,将客户的不同需求抽象成为抽象组件,并且能够描述这些抽象组件之间的通信和调用。
  • 框架:软件框架是项目软件开发过程中提取特定领域软件的共性部分形成的体系结构,不同领域的软件项目有着不同的框架类型。框架不是现成可用的应用系统。而是一个半成品,提供了诸多服务,开发人员进行二次开发,实现具体功能的应用系统。
  • 设计模式:是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,它强调的是一个设计问题的解决方法。
设计模式( Design Pattern) 是一套被反复使用、为多数人知晓、经过分类编目的、代码设计经验的总结。使用设计模式的目的是为了代码重用,避免程序大量修改,同时使代码更易于理解,并且保证代码可靠性。
  • GoF(Gang of Four)23种经典设计模式
第七章 设计模式

 

7.1 什么是单例模式
  • https://www.cnblogs.com/aspirant/p/6878555.html
  • 单例模式(也叫单件模式)的作用就是保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个(当然也可以不存在)。
  • 懒汉式
    • 类加载时不初始化 
    • 需要考虑多线程问题
  • 饿汉式
    • 在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快
    • 不需要考虑多线程问题
7.2 什么是工厂模式
  • https://www.cnblogs.com/zhangchenliang/p/3700820.html
  • 工厂模式专门负责实例化有大量公共接口的类。工厂模式可以动态块决定将哪一个 类实例化,而不必事先知道每次要实例化哪一个类。 客户类和工厂类是分开的。消费者无论什么时候需要某种产品,需要做的只是向工厂提出请求即可。
  • 工厂模式的几种形态
    • 1)简单工厂(Simple Factory) 模式。简单工厂模式的工厂类是根据提供给它的参数,返回的是几个可能产品中的一一个类的实例,通常情况下,它返回的类都有一一个公共的父类和公共的方法。
    • java代码
      • //简单工厂  
      • class Driver{  
      •     public static Car createCar(String car){  
      •         Car c = null;  
      •         if("Benz".equalsIgnoreCase(car))  
      •             c = new Benz();  
      •         else if("Bmw".equalsIgnoreCase(car))  
      •             c = new Bmw();  
      •         return c;  
      •     }  
      • }  
      •   
      • //老板  
      • public class BossSimplyFactory {  
      •   
      •     public static void main(String[] args) throws IOException {  
      •         //老板告诉司机我今天坐奔驰  
      •         Car car = Driver.createCar("benz");  
      •         car.setName("benz");  
      •          //司机开着奔驰出发  
      •         car.drive();  
      •     }  
      • }
    • 2)工厂方法( Factory Method)模式。工厂方法模式是类的创建模式,其用意是定义一个用于创建产品对象的工厂的接口,而将实际创建工作推迟到工厂接口的子类中。它属于简单工厂模式的进一步抽象和推广。多态的使用,使得工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。
    • java代码
      • //抽象工厂  
      • abstract class Driver{  
      •     public abstract Car createCar(String car) throws Exception;  
      • }  
      • //具体工厂(每个具体工厂负责一个具体产品)  
      • class BenzDriver extends Driver{  
      •     public Car createCar(String car) throws Exception {  
      •         return new Benz();  
      •     }  
      • }  
      • class BmwDriver extends Driver{  
      •     public Car createCar(String car) throws Exception {  
      •         return new Bmw();  
      •     }  
      • }  
      •   
      • //老板  
      • public class Boss{  
      •   
      •     public static void main(String[] args) throws Exception {  
      •         Driver d = new BenzDriver();  
      •         Car c = d.createCar("benz");   
      •         c.setName("benz");  
      •         c.drive();  
      •     }  
      • }  
    • 3)抽象工厂( Abstract Factory)模式。抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时使用的一种工厂模式,抽象工厂模式可以向客户端提供-一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据LSP原则(即Liskov替换原则),任何接受父类型的地方,都应当能够接受子类型,因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换句话说,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。
    • java代码
      • //抽象工厂  
      • abstract class Driver3{  
      •     public abstract BenzCar createBenzCar(String car) throws Exception;  
      •       
      •     public abstract BmwCar createBmwCar(String car) throws Exception;  
      •       
      •     public abstract AudiCar createAudiCar(String car) throws Exception;  
      • }  
      • //具体工厂  
      • class SportDriver extends Driver3{  
      •     public BenzCar createBenzCar(String car) throws Exception {  
      •         return new BenzSportCar();  
      •     }  
      •     public BmwCar createBmwCar(String car) throws Exception {  
      •         return new BmwSportCar();  
      •     }  
      •     public AudiCar createAudiCar(String car) throws Exception {  
      •         return new AudiSportCar();  
      •     }  
      • }  
      • class BusinessDriver extends Driver3{  
      •     public BenzCar createBenzCar(String car) throws Exception {  
      •         return new BenzBusinessCar();  
      •     }  
      •     public BmwCar createBmwCar(String car) throws Exception {  
      •         return new BmwBusinessCar();  
      •     }  
      •     public AudiCar createAudiCar(String car) throws Exception {  
      •         return new AudiBusinessCar();  
      •     }  
      • }  
      •   
      • //老板  
      • public class BossAbstractFactory {  
      •   
      •     public static void main(String[] args) throws Exception {  
      •           
      •         Driver3 d = new BusinessDriver();  
      •         AudiCar car = d.createAudiCar("");  
      •         car.drive();  
      •     }  
      • }  
7.3 什么是适配器模式
  • https://blog.csdn.net/zhangjg_blog/article/details/18735243
  • 将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
  • java代码
    • public static class ThinAdapter implements Fatty {
    • private Thin thin;
    • public ThinAdapter(Thin thin) {
    • this.thin = thin;
    • }
    • public void hitOtherPeople() {
    • thin.beHit();
    • }
    • public void dodge() {
    • thin.dodge();
    • }
    • }
7.4 什么是观察者模式
  • https://blog.csdn.net/hu_wenpeng/article/details/52988822
  • 观察者模式( 也被称为发布/订阅模式)提供了避免组件之间紧密耦合的另一种方法,它将观察者和被观察的对象分离开来。在该模式中,一个对象通过添加一个方法( 该方法允许另一个对象,即观察者注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关,结果是对象可以相互对话,而不必了解原因。Java与C#的事件处理机制就是采用的此种设计模式。
  • 观察者接口:

  • package Interface;
     
    /**
    * 观察者接口
    * @author hu
    *
    */
    public interface Watcher {
     
        public void updata(String str);
    }
     
  • 被观察者接口:

  • package Interface;
     
    /**
    * 被观察者接口
    * @author hu
    *
    */
    public interface Watchered {
     
        public void addWatcher(Watcher watcher);
        public void removeWatcher(Watcher watcher);
        public void notifyWatcher(String str);
    }
  • 观察者类:

  • package founction;
     
    import Interface.Watcher;
     
    public class CreaterWatcher implements Watcher {
     
        //这个方法其实是供 被 被观察者 形参 CreateWather调用  到后来 还会回调当前这个方法
        @Override
        public void updata(String str) { //接收被监听者发过来的消息
            System.out.println(str);
        }
     
    }
  • 被观察者类:

  • package founction;
     
    import java.util.ArrayList;
    import java.util.List;
     
    import Interface.Watcher;
    import Interface.Watchered;
     
    /**
    * 被观察者的类
    * @author hu
    *
    */
    public class CreaterWatchered implements Watchered {
     
        //定义一个集合存储 观察者  这里的泛型类型我们使用接口 父引用指向子类
        List<Watcher> list = new ArrayList<>();
     
     
        @Override
        public void addWatcher(Watcher watcher) {
     
            list.add(watcher);
        }
     
        @Override
        public void removeWatcher(Watcher watcher) {
            list.remove(watcher);
        }
     
        @Override
        public void notifyWatcher(String str) {
     
            //通过这个方法通知观察者  我要偷东西了
                //通过循环通知每位观察者  for循环  都可以的
     
            /**
             * 方法1: 迭代器循环
             */
            /*Iterator<Watcher> it = list.iterator();
            while(it.hasNext()){
     
                CreaterWatcher watcher = (CreaterWatcher) it.next();
                watcher.updata(str);
            }*/
     
     
            /**
             * 方法2:增强for
             */
     
            /*for (Watcher watcher : list) {
     
                watcher.updata(str);
            }*/
     
            /**
             * 方法3:普通for循环
             */
            for (int i = 0; i < list.size(); i++) {
     
                list.get(i).updata(str);
            }
        }
     
    }
  • 测试类:

  • package Test;
     
    import founction.CreaterWatcher;
    import founction.CreaterWatchered;
    /**
    * 测试类
    * @author hu
    *
    */
    public class TestRxjava {
     
        public static void main(String[] args) {
     
            //创建观察者
     
            CreaterWatcher watcher1 = new CreaterWatcher();
            CreaterWatcher watcher2 = new CreaterWatcher();
            CreaterWatcher watcher3 = new CreaterWatcher();
            CreaterWatcher watcher4 = new CreaterWatcher();
            //创建被观察者
     
            CreaterWatchered watchered = new CreaterWatchered();
            watchered.addWatcher(watcher1);
            watchered.addWatcher(watcher2);
            watchered.addWatcher(watcher3);
            watchered.addWatcher(watcher4);
     
            //被观察者开始 发消息了  也就像 小偷开始偷东西了,警察(观察者)一直在监视者  这个时候警察 就是接收到消息了
            watchered.notifyWatcher("我开始偷东西了");
     
     
        }
     
    }
 
策略模式:
a)      提供公共接口或抽象类,定义需要使用的策略方法。(策略抽象类)
b)      多个实现的策略抽象类的实现类。(策略实现类)
c)       环境类,对多个实现类的封装,提供接口类型的成员量,可以在客户端中切换。
d)      客户端 调用环境类 进行不同策略的切换。
注:Jdk中的TreeSet和 TreeMap的排序功能就是使用了策略模式。

策略模式的优点

  (1)策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。
  (2)使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。

策略模式的缺点

  (1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。
  (2)由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。
 
 
装饰模式:
实现方式:
a)       抽象的被装饰角色 (所有的角色都要直接或间接的实现本角色)
b)       具体的被装饰角色,实现或继承a (被功能扩展的角色)
c)       装饰角色,实现或继承a (本类有对a的引用,所有的具体装饰角色都需要继承这个角色)
d)       多个具体修饰角色 ,继承c(对被装饰角色的功能扩展,可以任意搭配使用)
意图: 
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。该模式以对客 户端透明的方式扩展对象的功能。
适用环境:
(1)在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
(2)处理那些可以撤消的职责。
(3)当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的 子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
 
代理设计模式
       指由一个代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关业务的处理。比如生活中的通过代理访问网络,客户通过网络代理连接网络(具体业务),由代理服务器完成用户权限和访问限制等与上网相关的其他操作(相关业务)。
      示例代码如下:
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
interface Network { // 定义Network接口 
    public void browse(); // 定义浏览的抽象方法 
}  
   
class Real implements Network { // 真实的上网操作 
    public void browse() { // 覆写抽象方法 
        System.out.println("上网浏览信息!");  
    }  
}  
   
class Proxy implements Network { // 代理上网 
    private Network network;  
   
    public Proxy(Network network) {// 设置代理的真实操作 
        this.network = network; // 设置代理的子类 
    }  
   
    public void check() { // 身份验证操作 
        System.out.println("检查用户是否合法!");  
    }  
   
    public void browse() {  
        this.check(); // 调用具体的代理业务操作 
        this.network.browse(); // 调用真实的上网操作 
    }  
}  
   
public class ProxyDemo {  
    public static void main(String args[]) {  
        Network net = null; // 定义接口对象 
        net = new Proxy(new Real()); // 实例化代理,同时传入代理的真实操作 
        net.browse(); // 调用代理的上网操作  
    }