学习
实践
活动
专区
工具
TVP
写文章

打包带走常用的设计模式

设计模式

设计模式简介:

设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

常用的设计模式:

工厂模式

解析:

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

目的:

定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

//工厂模式:将方法统一,便于管理namespace IMooc;class Factory{ static function createDataBase(){ $db =new DataBase();//在此处实例化对象 return db; }}//使用类时需要new一个对象,而工厂模式将其代替$db =IMooc\Factory::createDataBase();

单例模式

解析:

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

目的:

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

protected $db;private function __construct(){}static function getInstance(){ if (self::$db){ return self::$db; }else{ self::$db =new self(); return self::$db; }}

注册树模式

1、注册树的定义:

class Register{ //用来存储放在注册树上的对象 protected static $objects; //注册 static function set($alias,$object){ self::$objects[$alias] =$object; } //获取 static function get($name){ return self::$objects[$name]; } //释放 function _unset($alias){ unset(self::$objects[$alias]); }}

2、注册树的使用

$db =IMooc\DataBase::getInstance();$db =\IMooc\Register::get('db1');//获取//使用类时需要new一个对象$db =IMooc\Factory::createDataBase();

适配器模式

解析

这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。

目的:

将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

将不同的函数接口封装成统一的API

1、定义接口

interface IDataBase{ function connect($host,$user,$passwd,$dbname); function query($sql); function close();}

2、接口实例(必须继承接口)

/IMooc/DataBase内的MySQL.php \MySQLi.php \PDO.php

eg:class MySQL implements IDataBase{ protected $link; function connect($host, $user, $passwd, $dbname) { // TODO: Implement connect() method. $link =mysql($host, $user, $passwd, $dbname); return $this->link; } function query($sql) { // TODO: Implement query() method. return mysql_query($sql); } function close() { // TODO: Implement close() method. return mysql_close($this->link); }}

3、实现

$db = new \IMooc\DataBase\MySQLi();$db->connect('127.0.0.1','root','***','test');$db->query("show databases");$db->close();

策略模式

解析:

在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

目的:

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

将特定的算法和方法封装成类

1、接口:UserStrategy

2、策略:Female/MaleUserStrategy(需要继承接口)

3、调用接口:

class Page { /* * @var \IMooc\UserStrategy * */ protected $strategy; function index(){ echo "AD:"; $this->strategy->showAd(); echo "

"; echo "Category:"; $this->strategy->showCategory(); } function setStrategy(\IMooc\Strategy\UserStrategy $strategy){ $this->strategy = $strategy; } } $page =new Page; if(isset($_GET['female'])){ $strategy = new \IMooc\Strategy\FemaleUserStrategy(); }else{ $strategy = new \IMooc\Strategy\MaleUserStrategy(); } $page->setStrategy($strategy); $page->index();

数据对象映射模式

解析

1、创建数值对象public class Student { private String name; private int rollNo; Student(String name, int rollNo){ this.name = name; this.rollNo = rollNo; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getRollNo() { return rollNo; } public void setRollNo(int rollNo) { this.rollNo = rollNo; }}

2、创建数据访问对象接口

import java.util.List;public interface StudentDao { public ListgetAllStudents(); public Student getStudent(int rollNo); public void updateStudent(Student student); public void deleteStudent(Student student);}

3、创建实现了上述接口的实体类。

import java.util.ArrayList;import java.util.List; public class StudentDaoImpl implements StudentDao { //列表是当作一个数据库 Liststudents; public StudentDaoImpl(){ students = new ArrayList(); Student student1 = new Student("Robert",0); Student student2 = new Student("John",1); students.add(student1); students.add(student2); } @Override public void deleteStudent(Student student) { students.remove(student.getRollNo()); System.out.println("Student: Roll No " + student.getRollNo() +", deleted from database"); } //从数据库中检索学生名单 @Override public ListgetAllStudents() { return students; } @Override public Student getStudent(int rollNo) { return students.get(rollNo); } @Override public void updateStudent(Student student) { students.get(student.getRollNo()).setName(student.getName()); System.out.println("Student: Roll No " + student.getRollNo() +", updated in the database"); }}

4、调用

public class DaoPatternDemo { public static void main(String[] args) { StudentDao studentDao = new StudentDaoImpl(); //输出所有的学生 for (Student student : studentDao.getAllStudents()) { System.out.println("Student: [RollNo : " +student.getRollNo()+", Name : "+student.getName()+" ]"); } //更新学生 Student student =studentDao.getAllStudents().get(0); student.setName("Michael"); studentDao.updateStudent(student); //获取学生 studentDao.getStudent(0); System.out.println("Student: [RollNo : " +student.getRollNo()+", Name : "+student.getName()+" ]"); }}

观察者模式

当一个对象状态发生改变时,依赖它的对象全部会收到通知,并自动更新。

1、设置观察者的方法

(1)增加观察者 (2)通知观察者

2、设置观察者接口

interface Observer{ function update($event_info = null);}

3、操作

(1)设置事件和触发方法 (2)添加观察者 (3)触发

class Event extends IMooc\Observer\EventGenerator { function trigger(){ echo "Event

\n"; $this->notify(); }}class Observer1 implements \IMooc\Observer\Observer { function update($event_info = null) { // TODO: Implement update() method. echo "观察者1

\n"; }}$event =new Event();$event->addObserver(new Observer1);$event->trigger();

原型模式

适用于大对象的创建。(创建对象可能需要很大的开销)

1、建立功能类

class Canvas{ public $data; protected $decorators =array(); function init($width =20 ,$height =10){ $data =array(); for ($i=0;$idata=$data; } function addDecorator(DrawDecorator $decorator){ $this->decorators[]=$decorator; } function beforeDraw(){ //先进先出 队 foreach ($this->decorators as $decorator){ $decorator->beforeDraw(); } } function afterDraw(){ //反转:后进先出 栈 $decorators =array_reverse($this->decorators); foreach ($this->decorators as $decorator){ $decorator->afterDraw(); } } function draw(){ $this->beforeDraw(); foreach ($this->data as $line){ foreach ($line as $char){ echo $char; } echo "

\n"; } $this->afterDraw(); } function rect($a1, $a2, $b1, $b2) { foreach($this->data as $k1 => $line) { if ($k1 $a2) continue; foreach($line as $k2 => $char) { if ($k2 $b2) continue; $this->data[$k1][$k2] = ' '; } } }}

2、建立原型模型

(1)设置原型(具有共同属性的初始化)$prototype =new IMooc\Canvas\Canvas();$prototype->init();(2)采用clone将对象prototype属性clone到对象canvas1中$canvas1 =clone $prototype;$canvas1->rect(4,10,4,12);//a1:第a1+1行,b1:第b1+1列,$canvas1->draw();(3)采用clone将对象prototype属性clone到对象canvas2中$canvas2 =clone $prototype;$canvas2->rect(5,7,6,12);$canvas2->draw();

//减少初始化工作,提高代码效率

装饰器模式

动态修改类的功能

1、在类中设置装饰器

//装饰器容器 protected $decorators =array(); //添加类的功能 function addDecorator(DrawDecorator $decorator){ $this->decorators[]=$decorator; } //在类的方法执行前入栈 function beforeDraw(){ //先进先出 队 foreach ($this->decorators as $decorator){ $decorator->beforeDraw(); } } //在队的方法前出栈 function afterDraw(){ //反转:后进先出栈 $decorators =array_reverse($this->decorators); foreach ($this->decorators as $decorator){ $decorator->afterDraw(); } } //原有类的方法 function draw(){ //入栈 $this->beforeDraw(); foreach ($this->data as $line){ foreach ($line as $char){ echo $char; } echo "

\n"; } //出栈(后进先出) $this->afterDraw(); }

2、设置装饰器接口

interface DrawDecorator{ function beforeDraw(); function afterDraw();}

3、增加类的方法(功能)

例程中增加设置颜色与大小两种功能(1)ColorDrawDecorator(2)SizeDrawDecorator

迭代器模式

解析:

这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。

目的:

提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。

(1)创建接口

public interface Iterator { public boolean hasNext(); public Object next();}public interface Container { public Iterator getIterator();}

(2)创建实现了 Container 接口的实体类。该类有实现了 Iterator 接口的内部类 NameIterator。

public class NameRepository implements Container { public String names[] = {"Robert" , "John" ,"Julie" , "Lora"}; @Override public Iterator getIterator() { return new NameIterator(); } private class NameIterator implements Iterator { int index; @Override public boolean hasNext() { if(index

(3)使用 NameRepository 来获取迭代器,并打印名字。

代理模式

解析:

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

目的:

为其他对象提供一种代理以控制对这个对象的访问。 (1)定义接口

interface IUserProxy{ function getUserName($id); function setUserName($id, $name);}

(2)继承

class Proxy implements IUserProxy{ function getUserName($id) { $db = Factory::getDatabase('slave');//查询用从库 $db->query("select name from user where id =$id limit 1"); } function setUserName($id, $name) { $db = Factory::getDatabase('master');//写用主库 $db->query("update user set name = $name where id =$id limit 1"); }}

小结:

设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180727G1UB4Y00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

同媒体快讯

关注

腾讯云开发者公众号
10元无门槛代金券
洞察腾讯核心技术
剖析业界实践案例
腾讯云开发者公众号二维码

扫码关注腾讯云开发者

领取腾讯云代金券