Rumah pembangunan bahagian belakang tutorial php [php]标记投射和工作单元

[php]标记投射和工作单元

Jun 13, 2016 am 11:38 AM
function nbsp obj

[php]标记映射和工作单元
    标记映射

        系统中可能存在两个值相同,但又不是同一个引用的对象,这样的重复对象可能是从数据库中读出来的,这样就造成了不必要的查询。

        标记映射是一个类ObjectWatcher,它负责管理进程中的领域对象,以保证进程中不出现重复对象。

        标记映射可以防止重新读取数据库查询数据,只有当ObjectWatcher类中不存在标记映射对应的对象时才去查询数据库。这样就保证了在一个进程中,一条数据只对应一个对象。

        代码很容易懂,都是一些存取数组值的操作。

        ObjectWatcher代码:

namespace demo\domain;use \demo\domain\DomainObject;/** *  标记映射 */class ObjectWatcher {	private static $instance;	// 标记映射	private $all = array();		private function __construct() {			}		public  static function getInstance() {		if (!isset(self::$instance)) {			self::$instance = new self();		}				return self::$instance;	}		/**	 * 获得对象对应的键值	 * @param DomainObject $obj	 */	public function getGobalKey(DomainObject $obj) {		$key = get_class($obj) . '_' . $obj->getId();		return $key;	}		/**	 * 添加到all	 * @param DomainObject $obj	 */	public static function add(DomainObject $obj) {		$instance = self::getInstance();		$key = $instance->getGobalKey($obj);		$instance->all[$key] = $obj;	}		/**	 * 从all中删除	 * @param DomainObject $obj	 */	public static function delete(DomainObject $obj) {		$instance = self::getInstance();		$key = $instance->getGobalKey($obj);		unset($instance->all[$key]);	}		/**	 * 判断标记是否存在	 * @param string $className	 * @param int $id	 */	public  static function exists($className, $id) {		$instance = self::getInstance();		$key = "{$className}_{$id}";		if (isset($instance->all[$key])) {			return $instance->all[$key];		}				return null;	}}
Salin selepas log masuk
        那么在哪里做标记呢?当然是生成查询对象的地方,分别有Mapper::find()、Mapper::insert()、Mapper::createObject()。 Mapper中新增加了addToMap()和getFromMap()。(其它方法没有改变,所以看以忽略吧。)

        Mapper代码:

namespace demo\mapper;use \demo\base\AppException;use \demo\base\ApplicationRegistry;use \demo\domain\DomainObject;use \demo\domain\ObjectWatcher;/** * Mapper */abstract  class Mapper {	// PDO	protected static $PDO;	// config	protected static  $dsn, $dbUserName, $dbPassword;	// PDO选项	protected static $options = array(    	\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',    	\PDO::ATTR_ERRMODE,    	\PDO::ERRMODE_EXCEPTION,	); 		public function __construct() {		if (!isset(self::$PDO)) {			// ApplicationRegistry获取数据库连接信息			$appRegistry = ApplicationRegistry::getInstance();			self::$dsn = $appRegistry->getDsn();			self::$dbUserName = $appRegistry->getDbUserName();			self::$dbPassword = $appRegistry->getDbPassword();						if (!self::$dsn || !self::$dbUserName || !self::$dbPassword) {				throw  new AppException('Mapper init failed!');			}						self::$PDO = new \PDO(self::$dsn, self::$dbUserName, self::$dbPassword, self::$options);		}	}		/**	 * 查找指定ID	 * @param int $id	 */	public function findById($id) {		// 从ObjectWatcher中获取		$obj = $this->getFromMap($id);		if (!is_null($obj)) {			return $obj;		}				$pStmt = $this->getSelectStmt();				$pStmt->execute(array($id));			$data = $pStmt->fetch();				$pStmt->closeCursor();				if (!is_array($data) || !isset($data['id'])) {			return $obj;		}		$obj = $this->createObject($data);				return $obj;	}		/**	 * 返回Collection	 */	public function findAll() {		$pStmt = $this->getSelectAllStmt();		$pStmt->execute(array());		$raws = $pStmt->fetchAll(\PDO::FETCH_ASSOC);		$collection = $this->getCollection($raws);				return $collection;	}		/**	 * 插入数据	 * @param \demo\domain\DomainObject $obj	 */	public function insert(DomainObject $obj) {		$flag = $this->doInsert($obj);		// 保存或者更新ObjectWatcher的$all[$key]的对象		$this->addToMap($obj);		return $flag;	}		/**	 *  更新对象	 * @param \demo\domain\DomainObject $obj	 */	public  function update(\demo\domain\DomainObject $obj) {		$flag = $this->doUpdate($obj);				return $flag;	}		/**	 * 删除指定ID	 * @param int $id	 */	public function deleteById($id) {		$pStmt = $this->getDeleteStmt();		$flag = $pStmt->execute(array($id));				return $flag;	}		/**	 * 生成一个$data中值属性的对象	 * @param array $data	 */	public function createObject(array $data) {		// 从ObjectWatcher中获取		$obj = $this->getFromMap($data['id']);		if (!is_null($obj)) {			return $obj;		}				// 创建对象		$obj = $this->doCreateObject($data);		// 添加到ObjectWatcher		$this->addToMap($obj);				return $obj;	}		/**	 * 返回对应key标记的对象	 * @param int $id	 */	private function getFromMap($id) {		return ObjectWatcher::exists($this->getTargetClass(), $id);	}		/**	 * 添加对象到标记映射ObjectWatcher类	 * @param DomainObject $obj	 */	private function addToMap(DomainObject $obj) {		return ObjectWatcher::add($obj);	}		/**	 * 返回子类Collection	 * @param array $raw	 */	public function getCollection(array $raws) {		return $this->getFactory()->getCollection($raws);	}		/**	 * 返回子类持久化工厂对象	 */	public function getFactory() {		return PersistanceFactory::getFactory($this->getTargetClass());			}		protected abstract function doInsert(\demo\domain\DomainObject $obj);		protected abstract function doCreateObject(array $data);		protected abstract function getSelectStmt();		protected abstract function getSelectAllStmt();		protected abstract function doUpdate(\demo\domain\DomainObject $obj);		protected abstract function getDeleteStmt();	protected abstract function getTargetClass();}
Salin selepas log masuk
        大部分代码是之前的,修改的只是一小部分。下面图一张:

                                                               

        现在,当Mapper从数据库中取出的数据映射成的对象都被标记到ObjectWatcher了,而且不需要对对象手动操作标记到ObjectWatcher,Mapper就已经帮你完成了。这样带来的好处是可以减少对数据库的操作和新对象的创建,比如find、createObject。但这也许可能带来问题,如果你的程序需要并发处理数据,那么被标记的对象数据就可能不一致了,你在这个时候可能需要对数据加锁。  


    工作单元

          有些时候,我们可能没有改变数据的任何值却向数据库多次保存该数据,这当然是不必要的吧。工作单元可以使你只保存那些需要的对象。工作单元可以在一次请求即将结束时,把在这次请求中发生变化的对象保存到数据库中。一次请求的最后是在控制器(Controller)调用完Command和View之后,那么我们就可以在这里让工作单元执行任务。  

        标记映射的作用是在处理过程开始时向数据库加载不必要的对象,而工作单元则是在处理过程之后防止不必要的对象保存到数据库中。这两个工作方式就像是互补的。

        为了判断哪些数据库的操作是必要的,那就需要跟踪与对象相关的各种事件(比如:setter()重新设置了对象的属性值)。跟踪工作当然最好放在被跟踪的对象中。

        修改过的ObjectWatcher类:

namespace demo\domain;use \demo\domain\DomainObject;/** *  标记映射 */class ObjectWatcher {	private static $instance;	// 标记映射	private $all = array();	// 保存新建对象	private $new = array();	// 保存被修改过的对象(“脏对象”)	private $dirty = array();	// 保存删除对象	private $delete = array();		private function __construct() {			}		public  static function getInstance() {		if (!isset(self::$instance)) {			self::$instance = new self();		}				return self::$instance;	}		/**	 * 获得对象对应的键值	 * @param DomainObject $obj	 */	public function getGobalKey(DomainObject $obj) {		$key = get_class($obj) . '_' . $obj->getId();		return $key;	}		/**	 * 添加到all	 * @param DomainObject $obj	 */	public static function add(DomainObject $obj) {		$instance = self::getInstance();		$key = $instance->getGobalKey($obj);		$instance->all[$key] = $obj;	}		/**	 * 从all中删除	 * @param DomainObject $obj	 */	public static function delete(DomainObject $obj) {		$instance = self::getInstance();		$key = $instance->getGobalKey($obj);		unset($instance->all[$key]);	}		/**	 * 添加到new	 * @param DomianObject $obj	 */	public static function addNew(DomainObject $obj) {		$instance = self::getInstance();		$instance->new[] = $obj;	}		/**	 * 添加到dirty	 * @param DomianObject $obj	 */	public static function addDirty(DomainObject $obj) {		$instance = self::getInstance();		if (!in_array($obj, $instance->dirty, true)) {			$instance->dirty[$instance->getGobalKey($obj)] = $obj;		}	}		/**	 * 添加到delete	 * @param DomainObject $obj	 */	public static function addDelete(DomainObject $obj) {		$instance = self::getInstance();		$instance->delete[$instance->getGobalKey($obj)] = $obj;	}		/**	 * 清除标记dirty new delete	 * @param DomainObject $obj	 */	public static function addClean(DomainObject $obj) {		$instance = self::getInstance();		// unset删除保存的对象		unset($instance->dirty[$instance->getGobalKey($obj)]);		unset($instance->delete[$instance->getGobalKey($obj)]);		// 删除new中的对象		$instance->new = array_filter($instance->new, function($a) use ($obj) {			return !($a === $obj);		});	}		/**	 * 判断标记是否存在	 * @param string $className	 * @param int $id	 */	public  static function exists($className, $id) {		$instance = self::getInstance();		$key = "{$className}_{$id}";		if (isset($instance->all[$key])) {			return $instance->all[$key];		}				return null;	}		/**	 * 对new dirty delete 中的标记对象执行操作	 */	public function performOperations() {		$instance = self::getInstance();				// new		foreach ($instance->new as $obj) {			$obj->finder()->insert($obj);		}				// dirty		foreach ($instance->dirty as $obj) {			$obj->finder()->update($obj);		}				// delete		foreach ($instance->delete as $obj) {			$obj->finder()->delete($obj);		}				$this->new = array();		$this->dirty = array();		$this->delete = array();	}}
Salin selepas log masuk
        ObjectWatcher依然是标记映射,只是在这里增加了跟踪系统中对象的变化的功能。ObjectWatcher类提供了查找、删除、添加对象到数据库的机制。

        由于ObjectWatcher的操作上对对象的操作,所以由这些对象自己来来执行ObjectWatcher是很适合的。

        修改过的DomainObject类(markNew()、markDirty()、markDelete()、markClean()):

namespace demo\domain;use \demo\domain\HelperFactory;use \demo\domain\ObjectWatcher;/** * 领域模型抽象基类 */abstract class DomainObject {	protected  $id = -1;		public function __construct($id = null) {		if (is_null($id)) {			// 标记为new 新建			$this->markNew();		} else {			$this->id = $id;		}	}		public function getId() {		return $this->id;	}		public function setId($id) {		$this->id = $id;		$this->markDirty();	}		public function markNew() {		ObjectWatcher::addNew($this);	}		public function markDirty() {		ObjectWatcher::addDirty($this);	}		public function markDeleted() {		ObjectWatcher::addDelete($this);	}		public function markClean() {		ObjectWatcher::addClean($this);	}		public static function getCollection($type) {		return HelperFactory::getCollection($type);	}		public function collection() {		return self::getCollection(get_class($this));	}		public static function getFinder($type) {		return HelperFactory::getFinder($type);	}		public function finder() {		return self::getFinder(get_class($this));	}}
Salin selepas log masuk
        DomainObject和ObjectWatcher的关系图一张:
                                                     

         修改过的Mapper(和上面相同部分略去了,太占位子了):

/** * Mapper */abstract  class Mapper {	//...		/**	 * 查找指定ID	 * @param int $id	 */	public function findById($id) {		// 从ObjectWatcher中获取		$obj = $this->getFromMap($id);		if (!is_null($obj)) {			return $obj;		}				$pStmt = $this->getSelectStmt();				$pStmt->execute(array($id));			$data = $pStmt->fetch();				$pStmt->closeCursor();				if (!is_array($data) || !isset($data['id'])) {			return $obj;		}		$obj = $this->createObject($data);				return $obj;	}			/**	 * 插入数据	 * @param \demo\domain\DomainObject $obj	 */	public function insert(DomainObject $obj) {		$flag = $this->doInsert($obj);		// 保存或者更新ObjectWatcher的$all[$key]的对象		$this->addToMap($obj);		$obj->markClean();		// 调试用的				echo 'insert :' . get_class($obj) . '_' . $obj->getName() . '_' . $obj->getId() .'<br>';			return $flag;	}		/**	 *  更新对象	 * @param \demo\domain\DomainObject $obj	 */	public  function update(\demo\domain\DomainObject $obj) {		$flag = $this->doUpdate($obj);		$obj->markClean();		// 调试用的				echo 'update :' . get_class($obj) . '_' . $obj->getName() . '_' . $obj->getId() .'<br>';					return $flag;	}			/**	 * 生成一个$data中值属性的对象	 * @param array $data	 */	public function createObject(array $data) {		// 从ObjectWatcher中获取		$obj = $this->getFromMap($data['id']);		if (!is_null($obj)) {			return $obj;		}				// 创建对象		$obj = $this->doCreateObject($data);		// 添加到ObjectWatcher		$this->addToMap($obj);		// 清除new标记        ObjectWatcher::addClean($obj);				return $obj;	}		//...}
Salin selepas log masuk
        可以看到Mapper中修改的部分都是有改变对象的事件发生,即find()、update()、insert()、delete()。

        对象的变化都能被跟踪到了,那么应该在哪里处理这些变化过的对象(“脏数据”)呢?上面说到了,应该在一次请求即将完成的时候。

        一次请求即将结束时,Controller中调用工作单元(同样省略了没改变的代码):

namespace demo\controller;/** * Controller */class Controller {	// ...		private function handleReuqest() {		$request = new \demo\controller\Request();		$appController = \demo\base\ApplicationRegistry::getInstance()->getAppController();		// 执行完所有Command,有可能存在forward		while ($cmd = $appController->getCommand($request)) {			// var_dump($cmd);			$cmd->execute($request);			// 把当前Command设为已执行过			$request->setLastCommand($cmd);		}		// 工作单元执行任务		ObjectWatcher::getInstance()->performOperations();		// 获取视图		$view = $appController->getView($request);		// 显示视图		$this->invokeView($view);	}		// ...}
Salin selepas log masuk
        ObjectWatcher::getInstance()->performOperations()


        好的,现在来个使用例子吧:

namespace demo\command;use demo\domain\Classroom;use demo\base\ApplicationRegistry;use demo\domain\ObjectWatcher;use demo\domain\HelperFactory;class Test extends Command {	protected function doExecute(\demo\controller\Request $request) {		$crMapper = HelperFactory::getFinder('demo\domain\Classroom');				// 新创建的对象 markNew()		$crA = new Classroom();		$crA->setName('四年(3)班');				// 修改后的“脏”数据		$crB = $crMapper->findById(1);		$crB->setName("五年(2)班");	}}
Salin selepas log masuk
        输入的Url:
localhost/demo/runner.php?cmd=Test
Salin selepas log masuk
      输出结果与预期的一样:
insert :demo\domain\Classroom_四年(3)班_58update :demo\domain\Classroom_五年(2)班_1
Salin selepas log masuk
        

        现在对领域对象的管理有了较大的改进了。还有,我们使用模式的目的是提高效率,而不是降低效率。
        


Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
2 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Repo: Cara menghidupkan semula rakan sepasukan
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Cara mendapatkan biji gergasi
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Penyelesaian: Organisasi anda memerlukan anda menukar PIN anda Penyelesaian: Organisasi anda memerlukan anda menukar PIN anda Oct 04, 2023 pm 05:45 PM

Mesej "Organisasi anda memerlukan anda menukar PIN anda" akan muncul pada skrin log masuk. Ini berlaku apabila had tamat tempoh PIN dicapai pada komputer menggunakan tetapan akaun berasaskan organisasi, di mana mereka mempunyai kawalan ke atas peranti peribadi. Walau bagaimanapun, jika anda menyediakan Windows menggunakan akaun peribadi, sebaiknya mesej ralat tidak akan muncul. Walaupun ini tidak selalu berlaku. Kebanyakan pengguna yang mengalami ralat melaporkan menggunakan akaun peribadi mereka. Mengapa organisasi saya meminta saya menukar PIN saya pada Windows 11? Ada kemungkinan akaun anda dikaitkan dengan organisasi dan pendekatan utama anda adalah untuk mengesahkan perkara ini. Menghubungi pentadbir domain anda boleh membantu! Selain itu, tetapan dasar tempatan yang salah konfigurasi atau kunci pendaftaran yang salah boleh menyebabkan ralat. Sekarang ni

Cara melaraskan tetapan sempadan tetingkap pada Windows 11: Tukar warna dan saiz Cara melaraskan tetapan sempadan tetingkap pada Windows 11: Tukar warna dan saiz Sep 22, 2023 am 11:37 AM

Windows 11 membawa reka bentuk yang segar dan elegan ke hadapan antara muka moden membolehkan anda memperibadikan dan menukar butiran terbaik, seperti sempadan tingkap. Dalam panduan ini, kami akan membincangkan arahan langkah demi langkah untuk membantu anda mencipta persekitaran yang mencerminkan gaya anda dalam sistem pengendalian Windows. Bagaimana untuk menukar tetapan sempadan tetingkap? Tekan + untuk membuka apl Tetapan. WindowsSaya pergi ke Pemperibadian dan klik Tetapan Warna. Perubahan Warna Tetingkap Sempadan Tetapan Tetingkap 11" Lebar="643" Tinggi="500" > Cari pilihan Tunjukkan warna aksen pada bar tajuk dan sempadan tetingkap, dan togol suis di sebelahnya. Untuk memaparkan warna aksen pada menu Mula dan bar tugas Untuk memaparkan warna tema pada menu Mula dan bar tugas, hidupkan Tunjukkan tema pada menu Mula dan bar tugas

Bagaimana untuk menukar warna bar tajuk pada Windows 11? Bagaimana untuk menukar warna bar tajuk pada Windows 11? Sep 14, 2023 pm 03:33 PM

Secara lalai, warna bar tajuk pada Windows 11 bergantung pada tema gelap/terang yang anda pilih. Walau bagaimanapun, anda boleh menukarnya kepada mana-mana warna yang anda mahu. Dalam panduan ini, kami akan membincangkan arahan langkah demi langkah untuk tiga cara mengubahnya dan memperibadikan pengalaman desktop anda untuk menjadikannya menarik secara visual. Adakah mungkin untuk menukar warna bar tajuk tetingkap aktif dan tidak aktif? Ya, anda boleh menukar warna bar tajuk tetingkap aktif menggunakan apl Tetapan, atau anda boleh menukar warna bar tajuk tetingkap tidak aktif menggunakan Registry Editor. Untuk mempelajari langkah-langkah ini, pergi ke bahagian seterusnya. Bagaimana untuk menukar warna bar tajuk dalam Windows 11? 1. Tekan + untuk membuka tetingkap tetapan menggunakan apl Tetapan. WindowsSaya pergi ke "Peribadikan" dan kemudian

Masalah Ralat OOBELANGUAGE dalam Pembaikan Windows 11/10 Masalah Ralat OOBELANGUAGE dalam Pembaikan Windows 11/10 Jul 16, 2023 pm 03:29 PM

Adakah anda melihat "Masalah berlaku" bersama-sama dengan pernyataan "OOBELANGUAGE" pada halaman Pemasang Windows? Pemasangan Windows kadangkala terhenti kerana ralat tersebut. OOBE bermaksud pengalaman di luar kotak. Seperti yang ditunjukkan oleh mesej ralat, ini ialah isu yang berkaitan dengan pemilihan bahasa OOBE. Tiada apa yang perlu dibimbangkan, anda boleh menyelesaikan masalah ini dengan penyuntingan pendaftaran yang bagus dari skrin OOBE itu sendiri. Pembetulan Pantas – 1. Klik butang “Cuba Semula” di bahagian bawah apl OOBE. Ini akan meneruskan proses tanpa gangguan lagi. 2. Gunakan butang kuasa untuk menutup paksa sistem. Selepas sistem dimulakan semula, OOBE harus diteruskan. 3. Putuskan sambungan sistem daripada Internet. Lengkapkan semua aspek OOBE dalam mod luar talian

Bagaimana untuk mendayakan atau melumpuhkan pratonton lakaran kecil bar tugas pada Windows 11 Bagaimana untuk mendayakan atau melumpuhkan pratonton lakaran kecil bar tugas pada Windows 11 Sep 15, 2023 pm 03:57 PM

Lakaran kecil bar tugas boleh menjadi menyeronokkan, tetapi ia juga boleh mengganggu atau menjengkelkan. Memandangkan kekerapan anda menuding di atas kawasan ini, anda mungkin telah menutup tetingkap penting secara tidak sengaja beberapa kali. Kelemahan lain ialah ia menggunakan lebih banyak sumber sistem, jadi jika anda telah mencari cara untuk menjadi lebih cekap sumber, kami akan menunjukkan kepada anda cara untuk melumpuhkannya. Walau bagaimanapun, jika spesifikasi perkakasan anda boleh mengendalikannya dan anda menyukai pratonton, anda boleh mendayakannya. Bagaimana untuk mendayakan pratonton lakaran kecil bar tugas dalam Windows 11? 1. Menggunakan apl Tetapan ketik kekunci dan klik Tetapan. Windows klik Sistem dan pilih Perihal. Klik Tetapan sistem lanjutan. Navigasi ke tab Lanjutan dan pilih Tetapan di bawah Prestasi. Pilih "Kesan Visual"

Paparkan panduan penskalaan pada Windows 11 Paparkan panduan penskalaan pada Windows 11 Sep 19, 2023 pm 06:45 PM

Kita semua mempunyai pilihan yang berbeza apabila ia berkaitan dengan penskalaan paparan pada Windows 11. Sesetengah orang suka ikon besar, ada yang suka ikon kecil. Walau bagaimanapun, kita semua bersetuju bahawa mempunyai penskalaan yang betul adalah penting. Penskalaan fon yang lemah atau penskalaan berlebihan imej boleh menjadi pembunuh produktiviti sebenar apabila bekerja, jadi anda perlu tahu cara menyesuaikannya untuk memanfaatkan sepenuhnya keupayaan sistem anda. Kelebihan Zum Tersuai: Ini adalah ciri yang berguna untuk orang yang mengalami kesukaran membaca teks pada skrin. Ia membantu anda melihat lebih banyak pada skrin pada satu masa. Anda boleh membuat profil sambungan tersuai yang digunakan hanya pada monitor dan aplikasi tertentu. Boleh membantu meningkatkan prestasi perkakasan kelas rendah. Ia memberi anda lebih kawalan ke atas perkara yang terdapat pada skrin anda. Cara menggunakan Windows 11

10 Cara untuk Melaraskan Kecerahan pada Windows 11 10 Cara untuk Melaraskan Kecerahan pada Windows 11 Dec 18, 2023 pm 02:21 PM

Kecerahan skrin adalah bahagian penting dalam menggunakan peranti pengkomputeran moden, terutamanya apabila anda melihat skrin untuk jangka masa yang lama. Ia membantu anda mengurangkan ketegangan mata, meningkatkan kebolehbacaan dan melihat kandungan dengan mudah dan cekap. Walau bagaimanapun, bergantung pada tetapan anda, kadangkala sukar untuk mengurus kecerahan, terutamanya pada Windows 11 dengan perubahan UI baharu. Jika anda menghadapi masalah melaraskan kecerahan, berikut ialah semua cara untuk mengurus kecerahan pada Windows 11. Cara Menukar Kecerahan pada Windows 11 [10 Cara Diterangkan] Pengguna monitor tunggal boleh menggunakan kaedah berikut untuk melaraskan kecerahan pada Windows 11. Ini termasuk sistem desktop menggunakan monitor tunggal serta komputer riba. Jom mulakan. Kaedah 1: Gunakan Pusat Tindakan Pusat Tindakan boleh diakses

Bagaimana untuk mematikan pengesahan penyemakan imbas peribadi pada iPhone dalam Safari? Bagaimana untuk mematikan pengesahan penyemakan imbas peribadi pada iPhone dalam Safari? Nov 29, 2023 pm 11:21 PM

Dalam iOS 17, Apple memperkenalkan beberapa ciri privasi dan keselamatan baharu kepada sistem pengendalian mudah alihnya, salah satunya adalah keupayaan untuk memerlukan pengesahan dua faktor untuk tab penyemakan imbas peribadi dalam Safari. Begini cara ia berfungsi dan cara mematikannya. Pada iPhone atau iPad yang menjalankan iOS 17 atau iPadOS 17, penyemak imbas Apple kini memerlukan pengesahan Face ID/Touch ID atau kod laluan jika anda mempunyai sebarang tab Penyemakan Imbas Peribadi terbuka di Safari dan kemudian keluar dari sesi atau apl untuk mengaksesnya semula. Dalam erti kata lain, jika seseorang mendapatkan iPhone atau iPad anda semasa ia dibuka kunci, mereka masih tidak akan dapat melihat privasi anda tanpa mengetahui kod laluan anda

See all articles