1. 程式人生 > >php實現設計模式————單例模式

php實現設計模式————單例模式

  php實現設計模式————單例模式
  
  什麼是單例模式
  
  為什麼要使用單例模式
  
  php中有哪些方式實現新建一個物件例項
  
  如何阻止這種例項化實現理想的單例模式
  
  程式碼實現
  
  什麼是單例模式
  
  為什麼要使用單例模式
  
  php中有哪些方式實現新建一個物件例項
  
  1. new test();//通過new例項化物件
  
  2. 通過clone複製物件
  
  3. 通過序列化反序列化得到物件例項
  
  4. 通過類的反射例項化物件
  
  1
  
  2
  
  3
  
  4
  
  如何阻止這種例項化實現理想的單例模式
  
  1. new test();//通過new例項化物件 : 通過更改構造方法為private 阻止使用方直接new 物件
  
  3. 通過clone複製物件 : 通過定義private __clone()阻止複製操作
  
  4. 通過序列化反序列化得到物件例項 :通過定義__wakeup()阻止物件的反序列化。
  
  5. 通過類的反射例項化物件:暫時還沒有相應的方法去阻止使用此方法實現物件多例
  
  1
  
  2
  
  3
  
  4
  
  程式碼實現
  
  <?php
  
  /**
  
  * Created by PhpStorm.
  
  * User: Uasier
  
  * Date: 2018/10/17
  
  * Time: 15:10
  
  */
  
  /**
  
  * 單例模式例項
  
  */
  
  class Singleton
  
  {
  
  /**
  
  * 私有變數存例項
  
  * @var Singleton
  
  */
  
  private static $instance;
  
  /**
  
  * 私有建構函式
  
  * Singleton constructor.
  
  */
  
  private function __construct()
  
  {
  
  var_dump('構造了物件');
  
  }
  
  /**
  
  * clone 魔術方法
  
  */
  
  private function __clone()
  
  {
  
  var_dump('複製了物件');
  
  }
  
  /**
  
  * sleep 魔術方法
  
  * @return array
  
  */
  
  public function __sleep(){
  
  //todo 如何阻止
  
  var_dump('序列化了物件');
  
  return [];
  
  }
  
  /**
  
  * wakeup 魔術方法
  
  */
  
  public function __wakeup(){
  
  //todo 如何阻止
  
  var_dump('反序列化了物件');
  
  }
  
  /**
  
  * 公有獲取例項方法
  
  * @return Singleton
  
  */
  
  public static function getInstance()
  
  {
  
  if (!(self::$instance instanceof self)) {
  
  self::$instance = new self();
  
  }
  
  var_dump('返回了物件');
  
  return self::$instance;
  
  }
  
  }
  
  //*******************************單例模式測試****************************
  
  //①在Singleton沒有例項的情況下獲取例項
  
  $a = Singleton::getInstance();
  
  var_dump($a);
  
  //在Singleton已經有例項的情況下獲取例項
  
  $b = Singleton::getInstance();
  
  var_dump($b);
  
  //②通過克隆來得到例項
  
  $c = clone $a;
  
  var_dump($c);
  
  //③通過序列化再反序列化得到例項
  
  $d = serialize($a);//序列化
  
  $e = unserialize($d);//反序列化
  
  $e->name = '反序列化';
  
  var_dump($e);
  
  //④php 反射來的到例項
  
  $obj = new ReflectionObject('Singleton');
  
  $f = $obj->newInstanceWithoutConstructor();
  
  var_dump($f);
  
  相對而言,php中四種例項物件的方式,但是我們能(合理)阻止的只有3種,
  
  如程式碼體現的,php的反射來獲得例項是我們阻止不了的一種方式(然而java卻可以),
  
  但是怎麼說呢,php 的反射也不是為了讓你去破解單例模式的,
  
  簡而言之,我們其實不用捨本求末過分追求單例模式的完美性,畢竟實現單例模式的是程式設計師,使用單例模式的也是程式設計師。程式
  
  複製程式碼
  
  1 using System;
  
  2 using System.Threading.Tasks;
  
  3
  
  4 using Quartz;
  
  5 using Quartz.Impl;
  
  6 using Quartz.Logging;
  
  7
  
  8 namespace QuartzSampleApp
  
  9 {
  
  10 public class Program
  
  11 {
  
  12 private static void Main(string[] args)
  
  13 {
  
  14 LogProvider.SetCurrentLogProvider(new ConsoleLogProvider());
  
  15
  
  16 RunProgram(www.gcyl159.com).GetAwaiter().GetResult();
  
  17
  
  18 Console.WriteLine("Press any key to close the application");
  
  19 Console.ReadKey(www.gcyl152.com/ );
  
  20 }
  
  21
  
  22 private static async Task RunProgram()
  
  23 {
  
  24 try
  
  25 {
  
  26 // Grab the Scheduler instance from the Factory
  
  27 NameValueCollection props =www.michenggw.com new NameValueCollection
  
  28 {
  
  29 { "quartz.serializer.type", "binary" }
  
  30 };
  
  31 StdSchedulerFactory factory = new StdSchedulerFactory(props);
  
  32 IScheduler scheduler = await factory.GetScheduler();
  
  33
  
  34 // and start it off
  
  35 await scheduler.Start();
  
  36
  
  37 // define the job and tie it to our HelloJob class
  
  38 IJobDetail job = JobBuilder.Create<HelloJob>(www.yigouyule2.cn)
  
  39 .WithIdentity("job1", "group1")
  
  40 .Build();
  
  41
  
  42 // Trigger the job to run now, and then repeat every 10 seconds
  
  43 ITrigger trigger = TriggerBuilder.Create()
  
  44 .WithIdentity("trigger1", "group1")
  
  45 .StartNow()
  
  46 .WithSimpleSchedule(x => x
  
  47 .WithIntervalInSeconds(10)
  
  48 .RepeatForever(www.leyouzaixian2.com))
  
  49 .Build(www.365soke.com);
  
  50
  
  51 // Tell quartz to schedule the job using our trigger
  
  52 await scheduler.ScheduleJob(job, trigger);
  
  53
  
  54 // some sleep to show what's happening
  
  55 await Task.Delay(TimeSpan.FromSeconds(60));
  
  56
  
  57 // and last shut down the scheduler when you are ready to close your program
  
  58 await scheduler.Shutdown();
  
  59 }
  
  60 catch (SchedulerException se)
  
  61 {
  
  62 Console.WriteLine(se);
  
  63 }
  
  64 }
  
  65
  
  66 // simple log provider to get something to the console
  
  67 private class ConsoleLogProvider : ILogProvider
  
  68 {
  
  69 public Logger GetLogger(string name)
  
  70 {
  
  71 return (level, func, exception, parameters) =>
  
  72 {
  
  73 if (level >= LogLevel.Info && func != null)
  
  74 {
  
  75 Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] [" + level + "] " + func(), parameters);
  
  76 }
  
  77 return true;
  
  78 };
  
  79 }
  
  80
  
  81 public IDisposable OpenNestedContext(string message)
  
  82 {
  
  83 throw new NotImplementedException();
  
  84 }
  
  85
  
  86 public IDisposable OpenMappedContext(string key, string value)
  
  87 {
  
  88 throw new NotImplementedException();
  
  89 }
  
  90 }
  
  91 }
  
  92
  
  93 public class HelloJob : IJob
  
  94 {
  
  95 public async Task Execute(IJobExecutionContext context)
  
  96 {
  
  97 await Console.Out.WriteLineAsync("Greetings from HelloJob!");
  
  98 }
  
  99 }
  
  100 }
  
  複製程式碼