js单例_简单工厂模式是静态的工厂模式

js单例_简单工厂模式是静态的工厂模式学好设计模式,让你的逻辑活起来

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

? 工厂模式

  • 工厂模式的原理
  • 作用: 就是你只要传你需要的类进去,你就能得到他的实例化对象
  • 其实工厂就是帮你实例化你所需要的类
<?php
/**
* 工厂类
*/
class factory
{
    public static function create($className) {
        return new $className();
    }
}
 
class A {}
class B {}
 
$a = factory::create('A');
$b = factory::create('B');
 
var_dump($a); // object(A)#1 (0) {}
var_dump($b); // object(B)#2 (0) {}
  • 工厂模式的应用
  • 实例化多个类来处理不同业务时候使用,这里以求矩形和圆形的周长和面积为案例
<?php
/**
 * Interface shape
 */
interface shape
{
    public function area();
    public function perimeter();
}
 
/**
 * 矩形
 * Class rectangle
 */
class rectangle implements shape
{
    private $width;
    private $height;
 
    public function __construct($width, $height) {
        $this->width = $width;
        $this->height = $height;
    }
 
    public function area() {
        return $this->width * $this->height;
    }
 
    public function perimeter() {
        return 2 * ($this->width + $this->height);
    }
}
 
/**
 * 圆
 * Class circle
 */
class circle implements shape
{
    private $radius;
 
    public function __construct($radius) {
        $this->radius = $radius;
    }
 
    public function area() {
        return M_PI * pow($this->radius, 2);
    }
 
    public function perimeter() {
        return 2 * M_PI * $this->radius;
    }
}
 
/**
 * 工厂类
 * Class factory
 */
class factory
{
    public static function create() {
        switch (func_num_args()) {
            case 1:
                return new circle(func_get_arg(0));
                break;
            case 2:
                return new rectangle(func_get_arg(0), func_get_arg(1));
                break;
        }
    }
}
 
$a = factory::create(4, 5);
$b = factory::create(2);
 
echo '矩形的周长为:' . $a->perimeter();
echo '矩形的面积为:' . $a->area();
echo '圆的周长为:' . $a->perimeter();
echo '圆的面积为:' . $a->area();

? 单例模式

  • 单例模式的原理
  • 作用: 当你实例化多次类的时候,让其只存在在唯一的内存空间中,减少资源的消耗
  • 普通类的实例化,一个 new 将会创建一个实例化内存空间,因为空间不同,这将会导致系统内存开销增大
  • 但是同一个类,功能都一样,没必要放在不同的内存空间中
<?php
/**
 * Class A
 */
class A {}
 
$a = new A();
$b = new A();

// 非单例模式中可以看到其中#1,#2分属不同的内存空间
var_dump($a); // object(A)#1 (0) {}
var_dump($b); // object(A)#2 (0) {}
  • 单例模式的定义
  • 单例模式的入门口诀是:三私一公
  • 私有的构造方法: 防止人为外部使用 new 进行创建这就是上面普通内的实例化了
  • 私有的克隆方法: 防止人为外部使用 clone 方法后进行实例化
  • 私有的静态属性: 用来存储单一的实例化对象
  • 公有的静态方法: 用来实现单一的实例化逻辑
  • 从结果来看﹕两个类的对象内存空间都指向了 #1,实现了单例模式的基础构建
<?php
/**
 * Class database
 */
class database
{
    /**
     * @var $instance
     */
    private static $instance;
 
    /**
     * 私有的构造方法,禁止外部实例化
     * database constructor.
     */
    private function __construct() {}
 
    /**
     * 私有的克隆方法,禁止外部克隆
     */
    private function __clone() {}
 
    /**
     * 获取单例
     * @return database
     */
    public static function getInstance()
    {
        if(!self::$instance instanceof self) {
            self::$instance = new self();
        }
 
        return self::$instance;
    }
}
 
$a = database::getInstance();
$b = database::getInstance();

var_dump($a); // object(database)#1 (0) {}
var_dump($b); // object(database)#1 (0) {}
  • 单例模式的应用
  • 其实在项目中单例模式的应用很多,无非就是有些东西只需要实例化一个对象就行了,不需要多次进行实例化
  • 这其中的应用场景常见的就包括PDO连接数据库,Redis的连接等等
<?php
/**
 * Class mysql
 */
class mysql
{
    /**
     * @var \PDO
     */
    private $pdo;
 
    /**
     * @var $instance
     */
    private static $instance;
 
    /**
     * @var array
     */
    private $_config = [
        'host' => '127.0.0.1',
        'post' => 3306,
        'user' => 'root',
        'password' => '',
        'charset' => 'utf8',
        'dbname' => 'autofelix',
        'except' => 'PDO::ERRMODE_EXCEPTION'
    ];
 
    /**
     * mysql constructor.
     */
    private function __construct() {}
 
    /**
     * 数据库链接
     */
    public function connect()
    {
        try {
            $dsn = "mysql:host={$this->_config['host']};port={$this->_config['post']};dbname={$this->_config['dbname']};charset={$this->_config['charset']}";
            $this->pdo = new PDO($dsn, $this->_config['user'], $this->_config['password']);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, $this->_config['except']);
        } catch (PDOException $e) {
            exit('数据库连接失败:' . $e->getMessage());
        }
    }
 
    /**
     * @param $sql
     * @return array
     */
    public function getAll($sql)
    {
        $this->sql = $sql;
        $pdostatement = $this->pdo->query($sql);
        return $pdostatement->fetchAll(PDO::FETCH_ASSOC);
    }
 
    /**
     * @return mysql
     */
    public static function getInstance()
    {
        if(!self::$instance instanceof self) {
            self::$instance = new self();
        }
        return self::$instance;
    }
 
    private function __clone() {}
}
 
$mysql = mysql::getInstance();
$mysql->connect();
 
$sql = 'select * from autofelix_users where 1';
$result = $mysql->getAll($sql);
echo json_encode($result);

? 策略模式

  • 策略模式的原理
  • 作用: 比如你去淘宝上买东西,如果你是男生,它的首页会给你推荐男生喜欢的物品,如果你是女生呢,它会给你推荐女生常用的物品,策略模式其实就是给对象进行分类
  • 由上面可知,编程中的策略模式,就是会知道你是什么人,然后给你推荐你喜欢的东西,让营销最大化
  • 这里必然涉及到,程序在运行的时候,给你这个人进行分门别类,然后执行了不同的方法导致的
  • 这里我们定义两个类,拥有相同的方法,执行的内容却不同
  • 策略模式需要做的就是当用户进来时候,同一个入口让他根据这个人的行为去执行其中某一个类中的方法
<?php
/**
 * Class A
 */
class A {
    public function name()
    {
        echo "我是A类";
    }
}
 
/**
 * Class B
 */
class B {
    public function name()
    {
        echo "我是B类";
    }
}
 
/**
 * Class strategy
 */
class strategy
{
    /**
     * @var $obj
     */
    private $obj;
 
    /**
     * @return mixed
     */
    public function getName()
    {
        return $this->obj->name();
    }
 
    /**
     * @param $class
     */
    public function setClass($class)
    {
        $this->obj = $class;
    }
}
 
$strategy = new strategy();
// 分门别类
// $strategy->setClass(new A());
$strategy->setClass(new B());
// 同一个入口
$strategy->getName(); // 我是B类
  • 策略模式的应用
  • 情景: 一个用户去某酒店网站定住宿为例,页面上根据你的历史消费记录,会为你显示高等住宿和丰富的晚餐,或者仅仅显示大众住宿和廉价的自助餐
  • 我们先定义接口去实现住房和晚餐的方法
  • 然后定义两个群里的类去实现这个接口,分别是尊贵的人群和普通的人群
  • 当有个autofelix用户去订房间,给他注入大众用户的类
<?php
/**
 * 定义接口
 * Interface userStrategy
 */
interface userStrategy
{
    public function hotel();
    public function dinner();
}
 
/**
 * 尊贵的客人享有的待遇
 * Class rich
 */
class rich implements userStrategy
{
    public function hotel()
    {
        return "你是高贵的客人,为你推荐了高级住宿";
    }
 
    public function dinner()
    {
        return "你是高贵的客人,为你推荐了烛光晚餐";
    }
}
 
/**
 * 普通的客人享有的待遇
 * Class poor
 */
class poor implements userStrategy
{
    public function hotel()
    {
        return "你是普通的客人,为你推荐了大众住宿";
    }
 
    public function dinner()
    {
        return "你是普通的客人,为你推荐了自助餐";
    }
}
 
/**
 * Class user
 */
class user
{
    private $_userClass;
 
    public function getHotel() {
        return $this->_userClass->hotel();
    }
 
    public function getDinner() {
        return $this->_userClass->dinner();
    }
 
    public function setUserClass(userStrategy $userStrategy) {
        $this->_userClass = $userStrategy;
    }
}
 
/**
 * 这时候有个autofelix用户过来网站预定房间
 * Class autofelix
 */
class autofelix extends user {}
 
$people = new autofelix();
 
//设置群体
$people->setUserClass(new poor());
 
//获取该群体的住宿和晚餐
$hotel = $people->getHotel();
$dinner = $people->getDinner();
 
echo json_encode([
    'hotel' => $hotel,
    'dinner' => $dinner
]);

// 结果如下
{
    hotel: "你是普通的客人,为你推荐了大众住宿",
    dinner: "你是普通的客人,为你推荐了自助餐"
}

? 适配器模式

  • 适配器模式的原理
  • 作用: 将一个类的接口转换成客户希望的另一个接口,适配器模式使得原本的由于接口不兼容而不能一起工作的那些类可以一起工作
  • 比如:在某个场景中,老项目写了很多接口公你调用,但突然有一天,上司说要换个接口方法名调用,需要你用另一个方法名去实现相同的功能
  • 你是直接改后端代码的方法名称?这肯定行不通,因为项目不止你这一个地方调用这个接口,一旦修改,其他地方就崩了,还是去重新复制那段逻辑代码,改个名字,这样不是不行,只是写了重复代码,显得臃肿了
<?php
 
class A
{
    private $str;
 
    public function __construct($str)
    {
        $this->str = $str;
    }
 
    public function getStr()
    {
        return $this->str;
    }
 
    // 错误示范,直接复制 getStr 中的代码改个方法名,臃肿
    public function getString()
    {
        return $this->str;
    }
}
 
//适配器模式前
$a = new A('i am autofelix');
$result = $a->getStr();
var_dump($result);
  • 适配器模式的应用
  • 而正确的常见,应该是使用适配器模式处理这类问题
  • 通过定义统一接口,然后通过实现接口去实现
<?php
// 项目原本代码
class A
{
    private $str;
 
    public function __construct($str)
    {
        $this->str = $str;
    }
 
    public function getStr()
    {
        return $this->str;
    }
}

// 定义统一接口
interface AInterface {
    function getString();
}
 
class B implements AInterface
{
    /**
     * @var A
     */
    private $_A;
 
    public function __construct($class)
    {
        $this->_A = $class;
    }
 
    public function getString()
    {
        return $this->_A->getStr();
    }
}
 
// 适配器模式前
$a = new A('i am autofelix');
$result = $a->getStr();
var_dump($result);

// 适配器模式后
$b = new B($a);
$result = $b->getString();
var_dump($result);

? 观察者模式

  • 观察者模式的原理
  • 作用: 用来监控用户的某些操作,然后根据用户这些操作来处理一些后续的事情
  • 举个例子:一个用户去网上购买电影票,付款成功后,系统需要发短信给用户,顺便记录用户购票的日志等其他多个逻辑操作
<?php
// 系统自带的观察者接口
// 默认需要实现 onListen 和 getObserverName 这两个方法
// 如果是自定义观察者接口名,一定要实现onListen同功能的方法
// onListen 注册监听行为
interface InterfaceObserver
{
    public function onListen($sender, $args);
    public function getObserverName();
}

// 定义可被观察者的接口
// 其实就是用来监听事件的发生
// addObserver 方法我们是用来依赖注入一些用户购票之后系统的行为操作
// removeObserver 方法,是用来移除某个后续操作的,我们暂时不去实现
interface InterfaceObservable
{
    public function addObserver($observer);
    public function removeObserver($observer_name);
}
  • 观察者模式的应用
  • 这里以用户购票后需要给用户发送信息和记录购票日志
<?php
/**
 * Interface InterfaceObserver
 * 观察者接口
 */
interface InterfaceObserver
{
    public function onListen($sender, $args);
    public function getObserverName();
}
 
/**
 * Interface InterfaceObservable
 * 被观察对象接口
 */
interface InterfaceObservable
{
    public function addObserver($observer);
    public function removeObserver($observer_name);
}
 
class Ticket implements InterfaceObservable
{
    /**
     * @var array
     */
    private $_observers = [];
 
    /**
     * @param $observer
     */
    public function addObserver($observer)
    {
        if ($observer instanceof InterfaceObserver) {
            $this->_observers[] = $observer;
        }
    }
 
    /**
     * @param $observer_name
     */
    public function removeObserver($observer_name) {}
 
    /**
     * 用户购票行为
     */
    public function buy()
    {
        //用户购票逻辑,这里不详细说明,仅仅以参数代之
        $result = [
            'code' => 200,
            'msg' => '用户购票成功',
            'sign' => 'ea5070bec29826cc0f8e0b7b6861fd75'
        ];
 
        //购票成功,开始后期处理
        if($result['code'] == 200) {
            foreach ($this->_observers as $observer) {
                $observer->onListen($this, $result['sign']);
            }
        }
    }
}
 
 
/**
 * 记录用户购票日志
 * Class TicketRecord
 */
class ticketRecord implements InterfaceObserver
{
    public function onListen($sender, $args)
    {
        echo "记录用户购票成功,编号为:{$args}<br/>";
    }
 
    public function getObserverName() {}
}
 
/**
 * 给用户发送观影短信
 * Class sendMsg
 */
class sendMsg implements InterfaceObserver
{
    public function onListen($sender, $args)
    {
        echo "您的电影票购买成功,请凭编号:{$args}观影<br/>";
    }
 
    public function getObserverName() {}
}
 
$ticket = new Ticket();
$ticket->addObserver(new ticketRecord());
$ticket->addObserver(new sendMsg());
$ticket->buy();
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/170850.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • M3U8在线播放

    M3U8在线播放M3U8在线播放前言一、思路二、代码框架1.移动端适配2.改变M3U8地址3.设置videojs参数4.增加快进等功能写在最后前言当我们在网上愉快观影的时候,难免会遇到“M3U8格式”的视频。聪明的你应该也发现了,它是没办法直接播放的。它其实只是一个索引文件,根据它找到相应的.ts文件再进行播放。而这样做的好处,大概就是做多码率适配,保证视频播放的流畅性。有感兴趣的小伙伴可以参看这里—>M3U8文件格式。我今天要干的事情呢,就是解决当我们找到一个M3U8地址之后如何方便的播放它~一

  • ubuntu中apt和dpkg命令总结「建议收藏」

    ubuntu中apt和dpkg命令总结「建议收藏」1.apt和dpkg命令总结apt-cachesearch#——(package搜索包)apt-cacheshow#——(package获取包的相关信息,如说明、大小、版本等)apt-getinstall#——(package安装包)apt-getinstall#—–(package–reinstall重新安装包)apt-get

  • 《前端运维》二、Nginx–1基本概念及安装

    一、Nginx基本概念简单来说,Nginx就是一个代理服务器,什么是代理服务器呢?也就是当我们访问服务器的时候,请求不会直接请求到服务器,中间会有个代理,代理会预先于服务器处理这些请求,最后由代理决

  • C# OpenFileDialog SaveFileDialog Filter

    C# OpenFileDialog SaveFileDialog Filter那个Filter的格式每次都要忘,很讨厌,记录之: OpenFileDialogofd=newOpenFileDialog();ofd.Filter=”pc信息文件(*.vcf)|*.vcf|所有文件(*.*)|*.*”;if(ofd.ShowDialog()!=System.Windows.Forms.Di

  • 开机黑屏 仅仅显示鼠标 电脑黑屏 仅仅有鼠标 移动 [已成功解决]

    开机黑屏 仅仅显示鼠标 电脑黑屏 仅仅有鼠标 移动 [已成功解决]

  • 如何设置电信光猫?图解手把手教你(超级详细)「建议收藏」

    如何设置电信光猫?图解手把手教你(超级详细)「建议收藏」自从电信升级成光纤之后,光猫经常有点小问题的,如果电信说帮你设置好漫天要价的话,求人还不如求自己,或者电信送的光猫坏了,买他们的超贵,自己买一个又好又便宜的自己设置就的了注意:2016年以后,电信为

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号