ためすう
PHP でデザインパターン (シングルトン)
2018-03-11Singleton の目的
- 指定したクラスのインスタンスが絶対に1個しか存在しないことを保証したい
- インスタンスが1個しか存在しないことをプログラム上で表現したい
また、
たとえば、システムの設定を表現するクラスや、システム全体で一度読み込んだデータをキャッシュしておくクラスで利用する。
Singleton の実装に関して
Singleton クラスのコンストラクタは private にする。
Singleton クラス外からコンストラクタを呼ぶことを防ぐため。
下記の方法でインスタンス生成できないようにする
- 自身を外部から new する
- 外部から clone する
- 派生クラスを new する(派生クラスを作ることができないようにする)
Singleton の実装例
<?php
// final で派生クラスを作ることができないようにする
final class Singleton
{
private static $instance;
private $id;
private function __construct()
{
$this->id = time();
}
private function __clone()
{
}
public static function getInstance()
{
if (is_null(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
public function getId()
{
return $this->id;
}
}
$ins1 = Singleton::getInstance();
sleep(3);
$ins2 = Singleton::getInstance();
print($ins1 === $ins2);
print "\n";
print($ins1->getId() === $ins1->getId());
print "\n";
出力結果
1
1
エラーパターンの確認
- 自身を外部から new する
$ins0 = new Singleton();
// Fatal error: Call to private Singleton::__construct() が発生
- 外部から clone する
$clone_class = clone $ins1;
// Fatal error: Call to private Singleton::__clone() が発生
- 派生クラスを new する(派生クラスを作ることができないようにする)
class ChildSingleton extends Singleton
{
public function __construct()
{
}
}
$ins3 = new ChildSingleton();
// Fatal error: Class ChildSingleton may not inherit from final class (Singleton) が発生
参考
gmailのメールアドレスをOutlook 2007で使う
2018-03-10目的
html メールの作成をした時
動作確認で Outlook で受信メールを見ることができるようにすることです。
方法
Outlook の設定にて
受信メールサーバー、送信メールサーバーに gmail のメールサーバーの情報を入力します。
メールサーバーへのログオン情報には gmail のアカウント情報を入力します。
これで gmail のメールアドレスに来たメールを Outlook で見ることができるようになりました。
受信メールサーバーとは
- 「POP」は「Post Office Protocol(ポスト・オフィス・プロトコル)」の略
送信メールサーバーとは
- 「SMTP」とは「Simple Mail Transfer Protocol(シンプル・メール・トランスファー・プロトコル)」の略
参考URL
git リポジトリの移行をする
2018-03-04目的
個人の git リポジトリをチームで使うリポジトリへ移すことが必要になりました。
方法
$ git clone --mirror <SOURCE_REPOSITORY_URL>
$ cd <REPOSITORY>
$ git push --mirror <DESTINATION_REPOSITORY_URL>
ちょっと補足
$ git clone --help
> --mirror
> Set up a mirror of the source repository. This implies --bare. Compared to --bare, --mirror not only maps local branches of the
> source to local branches of the target, it maps all refs (including remote-tracking branches, notes etc.) and sets up a refspec
> configuration such that all these refs are overwritten by a git remote update in the target repository.
$ git push --help
> --mirror
> Instead of naming each ref to push, specifies that all refs under refs/ (which includes but is not limited to refs/heads/,
> refs/remotes/, and refs/tags/) be mirrored to the remote repository. Newly created local refs will be pushed to the remote end,
> locally updated refs will be force updated on the remote end, and deleted refs will be removed from the remote end. This is the
> default if the configuration option remote.<remote>.mirror is set.
参考URL
bowerでc3のインストール
2018-02-28目的
bower を使って、 c3 のインストールを行いました。
bower とは
フロントエンド用パッケージ管理ツールであり、依存関係も管理してくれるものです。
c3 とは
d3 を元にグラフを扱いやすくしたものです。
インストール手順
$ bower install c3
bower_components 以下に d3、c3 がインストールされました。
今後
bower_components 以下のファイルをそのまま呼び出しても使えますが
gulp などのビルド自動化ツールを使って、bower_components を呼び出すようにしてみたいと思います。
参考
Python ライブラリ・モジュールの場所を見つける
2018-02-25目的
python でファイルを実行するときに、module の場所を見つける必要がありました。
解決策
#### 確認環境
$ python himejima$ python –version Python 3.6.2 :: Anaconda custom (64-bit)
test.py
import datetime import json
print(datetime.file) print(json.file)
出力結果
/anaconda3/lib/python3.6/datetime.py /anaconda3/lib/python3.6/json/init.py ```
※ 環境により異なります。
参考
DIとDIコンテナとサービスロケータ その3
2018-02-22本記事の範囲
本記事では、サービスロケータ を記事の範囲とします。 DI 、DI コンテナについては別記事で書いています。
サービスロケータとは
「サービスロケータ」とは、サービス(オブジェクト)の取得を抽象化するデザインパターンです。
サービスロケータの例
<?php
require_once './vendor/autoload.php';
use Pimple\Container;
class Client
{
private $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function log($messgae)
{
$this->container['service_interface']->log();
}
}
interface ServiceInterface
{
public function log();
}
class Service implements ServiceInterface
{
public function log($message)
{
echo $message . "\n";
}
}
// Client呼び出し
$container = new Container();
$container['service_interface'] = function ($container) {
$service = new Service();
return $service;
};
$container['client'] = function ($container) {
$client = new Client($container);
return $client;
};
$client = $container['client'];
$client->log('ssssss');
ここでは、$container
がサービスロケータとなります。
依存するものが DIとサービスロケータで異なります。
DIの場合
- ServiceInterface を実装しているオブジェクト
サービスロケータの場合
- DIコンテナ (Pimple)
$this->container['service_interface']
これによって、Client クラスが DIコンテナ (Pimple)の依存が強くなり、Client を利用するときは DIコンテナも必要とされるようになってしまいました。
DIコンテナについてまず知っておくべきなのは、DIコンテナを使ってさえいれば「依存性の注入」ができるわけではないってことだ。 DIコンテナは、依存性の注入を実現するための便利な道具として使える。 でも、使い方をミスって、サービスロケーションというアンチパターンを作ってしまっていることも多い。 DIコンテナをサービスロケーターとしてクラスに組み込んでしまうと、 依存関係を別の場所に移そうとしていたはずなのに、よりきつい依存関係を作り込むことになる。 おまけにそのコードはわかりにくくなってしまうし、テストもしづらくなる。
結局のところ、サービスロケータはアンチパターンのようです。
参考
DIとDIコンテナとサービスロケータ その2
2018-02-18本記事の範囲
本記事では、DI コンテナについて書きます。 サービスロケータは別記事で。
DI コンテナとは
DIを楽にしたり、オブジェクト生成のコードをまとめるための便利なツール
DI コンテナ の例
Main.php ( 1 ファイルに全部まとめました)
<?php
require_once './vendor/autoload.php';
use Pimple\Container;
class Service
{
public function log($message)
{
echo $message . "\n";
}
}
class Client
{
private $service;
public function __construct(Service $service)
{
$this->service = $service;
}
public function log($message)
{
$this->service->log($message);
}
}
$container = new Container();
$container['service_interface'] = function ($container) {
$service = new Service();
return $service;
};
$container['client'] = function ($container) {
$client = new Client($container['service_interface']);
return $client;
};
$client = $container['client'];
$client->log('ssssss');
今回は Pimple を使用して、依存性について定義しました。
これによって、呼び出し元で依存性の注入を直接記述しなくても良くなりました。
(Client に渡すクラスが インターフェースになったら、一工夫が必要そうです。)
参考
DIとDIコンテナとサービスロケータ その1
2018-02-17本記事の範囲
本記事では、DI までを記事の範囲とします。 DI コンテナ、サービスロケータは別記事で書きます。
DI とは
依存性の注入(いそんせいのちゅうにゅう、英: Dependency injection)とは、コンポーネント間の依存関係をプログラムのソースコードから排除し、外部の設定ファイルなどで注入できるようにするソフトウェアパターンである。英語の頭文字からDIと略される。
依存性の注入の方法
注入の方法は下記のような手法がある。
- インタフェース注入
- setter注入
- コンストラクタ注入
DI の例
Main.php
<?php
require_once './LoggerInterface.php';
require_once './ExampleLogger.php';
require_once './DummyLogger.php';
require_once './Application.php';
// $logger = new ExampleLogger();
$logger = new DummyLogger();
$app = new Application($logger);
$app->error('エラーが発生');
Application.php
<?php
class Application
{
protected $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function error($message)
{
$this->logger->log($message);
}
}
LoggerInterface.php
<?php
interface LoggerInterface
{
public function log($log);
}
ExampleLogger.php
<?php
class ExampleLogger implements LoggerInterface
{
public function log($log)
{
echo $log . "\n";
return $this;
}
}
DummyLogger.php
<?php
class DummyLogger implements LoggerInterface
{
public function log($log)
{
return $this;
}
}
DI の特徴
- オブジェクトの生成と使用が分離されている
- クライアントがサービスを呼ぶのではなく、サービスが外部からクライアントに注入される。つまり、制御が反転している
また、この例では、 - ExampleLogger、DummyLogger の実装が完了していなくても、Application の実装ができます。 - LoggerInterface を実装した新しいクラスに切り替えるとき、呼び出し元の変更だけでokです。
参考
オブジェクト指向について
2018-02-15本記事の概要
参考URLに良いまとめがあったので、自分用のメモとして抜粋させて頂きました。
オブジェクト指向の特徴
- 継承
- カプセル化
- ポリモーフィズム (多態性)
継承
継承の本質はインターフェイスです。
継承は機能を受け継ぐためのものではありません。継承の本質は、犬や猫を「動物」という抽象概念としてまとめ上げられるインターフェイスなのです。
継承は親クラスの機能を受け継ぎますが、これは開発効率を上げるための優しさ的仕様であり、継承の本質はインターフェイスなのです。
継承を親クラスの機能を受け継ぐ目的で使って、失敗した記憶があります。
継承をインターフェースとして捉えて、抽象概念の抽出という目的で使うのが大切なようです。
カプセル化
カプセル化は、外から見てそのものが複雑でない状態を作るということ
クラスの役割は一つにする
これはクラスの利用者とクラスとの接点で、意識するべきところを理解しやすくするためかなと考えています。
ポリモーフィズム (多態性)
ポリモーフィズムはそのインターフェイス(抽象)に対してプログラムするということです
ここで衝撃的な事実をお伝えしましょう!実は「new」は具象です!ですから、ポリモーフィズムを意識する上でnewの扱いには最大限の注意を払う必要があります。
ポリモーフィズムは自分の中でしっくり来ていなかったのですが、腑に落ちた気がします。
デザインパターンでオブジェクトの生成と利用を分けているものがある理由もそこにあるのかもしれません。
(Factory Method パターンとか)
まとめ
自信を持って、クラス設計がしていけるように上記を頭に入れてやっていきたいと思います。
参考
composerをインストールする
2018-02-12目的
Pimple という DIコンテナ(Dependency Injection Container)を使いたかったため、
手元の Mac にて composer 経由でインストールします。
解決策
1. composer をインストール
$ curl -sS https://getcomposer.org/installer | php
2. path の設定
$ mv composer.phar /usr/local/bin/composer
3. Pimple を composer 経由でインストール
$ composer require pimple/pimple ~3.0
4. ライブラリを autoload する
例えば Pimple を利用したい場合は、下記のようにして autoload します。
<?php
require_once './vendor/autoload.php';
use Pimple\Container;
$container = new Container();