Rumah > hujung hadapan web > tutorial js > Menguasai Corak Reka Bentuk Prototaip: Panduan Komprehensif

Menguasai Corak Reka Bentuk Prototaip: Panduan Komprehensif

Barbara Streisand
Lepaskan: 2024-11-17 21:41:02
asal
1043 orang telah melayarinya

Pernahkah anda mengimport objek daripada perpustakaan dan cuba mengklonkannya, tetapi gagal kerana pengklonan memerlukan pengetahuan yang luas tentang dalaman perpustakaan?

Atau mungkin, selepas membuat projek untuk masa yang lama, anda berehat untuk memfaktorkan semula kod anda dan menyedari bahawa anda sedang menyatukan semula banyak objek kompleks dalam pelbagai bahagian pangkalan kod anda?

Nah, corak reka bentuk prototaip telah membantu anda!

Dalam artikel ini, kami akan meneroka corak reka bentuk prototaip sambil membina templat jurnal berfungsi sepenuhnya aplikasi Node.js CLI.

Tanpa berlengah lagi, mari kita selaminya!

Gambaran keseluruhan

Prototaip ialah corak reka bentuk ciptaan , iaitu kategori corak reka bentuk yang menangani masalah berbeza yang datang dengan cara asli mencipta objek dengan baharu kata kunci atau operator.

Masalah

Corak reka bentuk kilang menyelesaikan masalah penciptaan berikut:

  1. Bagaimana anda boleh menyalin objek sedia ada dalam aplikasi anda tanpa bergantung pada kelas konkritnya?

  2. Sesetengah objek kompleks sukar untuk diklon, kerana ia sama ada mempunyai banyak medan yang memerlukan logik perniagaan tertentu yang tidak anda ketahui atau atau mempunyai banyak medan peribadi yang tidak boleh diakses dari luar objek.

Mari kita ambil contoh objek soket yang diimport daripada pustaka socket.io , pengimejan yang perlu mengklonkannya sendiri?

Anda perlu meneliti kodnya di dalam pustaka, memahami cara soket berfungsi, objek tersebut mempunyai beberapa kebergantungan bulat yang anda perlu berurusan dengan diri anda untuk mengklonkannya.

Selain itu, kod anda akan bergantung pada kelas soket atau antara muka dan logik perniagaan yang sepadan untuk menciptanya, yang melanggar prinsip penyongsangan kebergantungan pepejal dan menjadikan kod anda kurang mantap untuk perubahan.

Penyelesaian

Corak reka bentuk prototaip menyelesaikan masalah ini, dengan mewakilkan tanggungjawab menyalin objek ke dalam objek itu sendiri, dengan mengisytiharkan kaedah klon dalam setiap kelas objek yang dimaksudkan sebagai boleh diklon.

class Socket {
  // code........

  clone(): Socket {
    // business logic to instantiate the socket.
    return new Socket(/*...Params*/)
  }
}


const socket1 = new Socket()
const socket2 = socket1.clone()

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Struktur

Untuk melaksanakan corak reka bentuk prototaip anda boleh sama ada secara langsung memasukkan kaedah klon di dalam objek boleh klon.

Atau buat antara muka biasa Prototaip yang boleh dilaksanakan oleh semua objek boleh klon. Mastering the Prototype Design Pattern: A Comprehensive Guide

Satu faedah mempunyai antara muka yang sama ialah keupayaan untuk mendaftarkan semua prototaip, dalam kelas perkhidmatan pendaftaran biasa, yang akan bertanggungjawab untuk menyimpan prototaip yang kerap digunakan dan mengembalikannya kepada pengguna. Daripada perlu mengklon objek setiap kali kaedah klon dipanggil.

Itu sangat berguna terutamanya apabila mengklon objek kompleks.

Mastering the Prototype Design Pattern: A Comprehensive Guide

Senario Praktikal

Dalam bahagian ini, kami akan menunjukkan corak reka bentuk ini dengan membina templat jurnal mini aplikasi Nodejs CLI.

Seperti yang kita lihat sebelum ini, corak reka bentuk prototaip mewakilkan tanggungjawab mengklon objek ke dalam objek itu sendiri.

Tetapi adakah anda tertanya-tanya mengapa ia dipanggil prototaip?Maksud saya, apa kaitannya dengan pengklonan?

Kami akan menjawabnya melalui contoh praktikal ini, teruskan membaca dan nantikan.
Anda boleh mencari kod akhir dalam repositori ini. Hanya klon dan jalankan arahan berikut.

Mencipta Prototaip kami: Kelas Templat Jurnal

Mula-mula mari kita buat JournalTemplate yang mempunyai atribut berikut:

  1. nama : Kami memerlukannya untuk mengenal pasti templat.
  2. bahagian : Bahagian ialah sebahagian daripada templat jurnal yang dikhaskan untuk tema atau topik tertentu seperti: Syukur, Cabaran, Matlamat Esok....

Setiap bahagian terdiri daripada atribut berikut:

  • tajuk Topik atau tema bahagian: Syukur, Cabaran, Matlamat Esok...
  • prompt Mesej yang akan dipaparkan kepada pengguna apabila dia hendak menulis teks jurnal bahagian.

JournalTemplate.ts

class Socket {
  // code........

  clone(): Socket {
    // business logic to instantiate the socket.
    return new Socket(/*...Params*/)
  }
}


const socket1 = new Socket()
const socket2 = socket1.clone()

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kelas JournalTemplate mempunyai banyak kaedah utiliti untuk menetapkan atributnya yang berbeza.

Kaedah paparan akan digunakan kemudian untuk memaparkan output yang diformat dengan baik berwarna ke terminal.

pakej kapur digunakan untuk mewarnai beberapa kepingan untuk teks terminal yang dikeluarkan.

Objek JournalTemplate kami bertujuan untuk digunakan seperti namanya sebagai templat atau prototaip untuk mencipta templat lain atau entri fail jurnal.

Itulah sebabnya kami telah menambahkan kaedah klon pada kelas JournalTemplate.

Kami telah menambahkannya untuk memberikan tanggungjawab mengendalikan logik perniagaan pengklonan kepada objek JournalTemplate itu sendiri dan bukannya kod penggunaan.

Mengisytiharkan Daftar Templat Jurnal

Sekarang mari buat kelas TemplateRegistry kami, yang akan bertanggungjawab menyimpan contoh prototaip kelas JournalTemplate. Sambil menyediakan kaedah untuk memanipulasi kejadian tersebut.

TemplateRegistry.ts

class Socket {
  // code........

  clone(): Socket {
    // business logic to instantiate the socket.
    return new Socket(/*...Params*/)
  }
}


const socket1 = new Socket()
const socket2 = socket1.clone()

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Pendaftaran menyimpan kelas tersebut dalam objek Peta, untuk mendapatkan semula cepat mengikut nama dan mendedahkan banyak kaedah utiliti untuk menambah atau menghentikan contoh templat.

Menggerakkan Daftar Templat Journaling

Sekarang, Mari kita nyatakan pendaftaran templat dan kemudian semai beberapa templat awal.

registry.ts

import chalk from "chalk"

import { TemplateSection } from "./types"

export interface TemplateSection {
  title: string
  prompt: string
}

export class JournalTemplate {
  constructor(
    public name: string,
    public sections: TemplateSection[]
  ) {}
  clone(): JournalTemplate {
    return new JournalTemplate(
      this.name,
      this.sections.map((s) => ({ ...s }))
    )
  }

  display(): void {
    console.log(chalk.cyan(`\nTemplate: ${this.name}`))
    this.sections.forEach((section, index) => {
      console.log(chalk.yellow(`${index + 1}. ${section.title}`))
      console.log(chalk.gray(` Prompt: ${section.prompt}`))
    })
  }

  addSection(section: TemplateSection): void {
    this.sections.push(section)
  }

  removeSection(index: number): void {
    if (index >= 0 && index < this.sections.length) {
      this.sections.splice(index, 1)
    } else {
      throw new Error("Invalid section index")
    }
  }

  editSection(index: number, newSection: TemplateSection): void {
    if (index >= 0 && index < this.sections.length) {
      this.sections[index] = newSection
    } else {
      throw new Error("Invalid section index")
    }
  }

  getSectionCount(): number {
    return this.sections.length
  }

  getSection(index: number): TemplateSection | undefined {
    return this.sections[index]
  }

  setName(newName: string): void {
    this.name = newName
  }
}

Salin selepas log masuk
Salin selepas log masuk

Menentukan kaedah tindakan templat

Dalam bahagian ini, kami akan mentakrifkan sekumpulan fungsi yang akan digunakan dalam menu aplikasi kami, untuk melaksanakan pelbagai tindakan seperti:

  1. Gesa pengguna untuk memasukkan nama templat, kemudian gesa secara berulang sekali lagi untuk membuat seberapa banyak bahagian yang dia mahu.
  2. Lihat Semua templat sedia ada atau yang dibuat.
  3. Gunakan templat untuk mencipta entri fail jurnal.
  4. Buat templat baharu, daripada templat sedia ada: Pengguna akan diminta memilih templat sedia ada kemudian dia akan mempunyai keupayaan untuk sama ada menggunakannya secara langsung atau mengatasi nama dan bahagiannya.

Templat yang baru dibuat boleh digunakan untuk mencipta entri jurnal baharu (1).

Buat Templat :

TemplateActions.ts > createTemplate

import { JournalTemplate } from "./JournalTemplate"

export class TemplateRegistry {
  private templates: Map<string, JournalTemplate> = new Map()

  addTemplate(name: string, template: JournalTemplate): void {
    this.templates.set(name, template)
  }

  getTemplate(name: string): JournalTemplate | undefined {
    const template = this.templates.get(name)
    return template ? template.clone() : undefined
  }

  getTemplateNames(): string[] {
    return Array.from(this.templates.keys())
  }
}

Salin selepas log masuk
Salin selepas log masuk
  • Untuk mencipta templat, kami terlebih dahulu menggesa pengguna memasukkan nama templat.
  • Kemudian kami membuat instantiat objek templat baharu, dengan nama dan tatasusunan kosong untuk bahagian tersebut.
  • Selepas itu, kami menggesa pengguna untuk memasukkan butiran bahagian, selepas memasukkan maklumat setiap bahagian, pengguna boleh memilih sama ada untuk berhenti atau memasukkan lebih banyak bahagian.

utils.ts > promptForSectionDetails

import { JournalTemplate } from "./JournalTemplate"
import { TemplateRegistry } from "./TemplateRegistry"

export const registry = new TemplateRegistry()

registry.addTemplate(
  "Daily Reflection",
  new JournalTemplate("Daily Reflection", [
    {
      title: "Gratitude",
      prompt: "List three things you're grateful for today.",
    },
    { title: "Accomplishments", prompt: "What did you accomplish today?" },
    {
      title: "Challenges",
      prompt: "What challenges did you face and how did you overcome them?",
    },
    {
      title: "Tomorrow's Goals",
      prompt: "What are your top 3 priorities for tomorrow?",
    },
  ])
)

registry.addTemplate(
  "Weekly Review",
  new JournalTemplate("Weekly Review", [
    { title: "Highlights", prompt: "What were the highlights of your week?" },
    {
      title: "Lessons Learned",
      prompt: "What important lessons did you learn this week?",
    },
    {
      title: "Progress on Goals",
      prompt: "How did you progress towards your goals this week?",
    },
    {
      title: "Next Week's Focus",
      prompt: "What's your main focus for next week?",
    },
  ])
)

Salin selepas log masuk

Fungsi promptForSectionDetails menggunakan pakej inquirer untuk meminta tajuk, kemudian menggesa secara berurutan daripada pengguna.

Lihat templat :

TemplateActions.ts > viewTemplates

import chalk from "chalk"
import inquirer from "inquirer"

import { JournalTemplate } from "./JournalTemplate"
import { registry } from "./registry"
import { editTemplateSections } from "./templateSectionsActions"
import { promptForSectionDetails } from "./utils"

export async function createTemplate(): Promise<void> {
  const { name } = await inquirer.prompt<{ name: string }>([
    {
      type: "input",
      name: "name",
      message: "Enter a name for the new template:",
    },
  ])

  const newTemplate = new JournalTemplate(name, [])
  let addMore = true
  while (addMore) {
    const newSection = await promptForSectionDetails()
    newTemplate.addSection(newSection)
    const { more } = await inquirer.prompt<{ more: boolean }>([
      {
        type: "confirm",
        name: "more",
        message: "Add another section?",
        default: false,
      },
    ])
    addMore = more
  }

  registry.addTemplate(name, newTemplate)
  console.log(chalk.green(`Template "${name}" created successfully!`))
}

Salin selepas log masuk

Fungsi viewTemplates berfungsi seperti berikut:

  1. Kami mula-mula mendapatkan semua templat daripada pendaftaran , kemudian kami mengulangi tatasusunan templat yang dikembalikan dan menggunakan kaedah paparan yang telah kami takrifkan sebelum ini dalam JournalTemplate kelas.

Gunakan templat untuk membuat Entri Jurnal : Sebab untuk mencipta templat jurnal, adalah untuk memudahkan hidup kita semasa menulis pelbagai jenis jurnal, daripada menghadap halaman kosong, lebih baik untuk isi jurnal apabila berhadapan dengan sekumpulan tajuk dan gesaan bahagian berurutan.

Jom selami fungsi useTemplate:

  1. Mula-mula kami memilih satu templat antara templat sedia ada, selepas mendapat nama templat daripada pendaftaran.
  2. Untuk setiap bahagian dalam templat, pengguna akan diminta untuk membuka editor pilihannya untuk mengisi teks bahagian jurnal.

TemplateActions.ts > gunakanTemplat

class Socket {
  // code........

  clone(): Socket {
    // business logic to instantiate the socket.
    return new Socket(/*...Params*/)
  }
}


const socket1 = new Socket()
const socket2 = socket1.clone()

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Buat Templat Daripada Templat Sedia Ada :

Akhir sekali, Kami akan melihat corak reka bentuk prototaip sedang beraksi.

Mari kita terokai bagaimana kita boleh mencipta jenis templat baharu secara dinamik dengan mengatasi templat sedia ada.

  1. Mula-mula kami menggesa pengguna memilih templat yang ingin dia ganti daripada yang sedia ada.
  2. Kemudian kami menggesanya sekali lagi untuk menaip nama templat yang baru dibuat.
  3. Kami menggunakan pendaftaran untuk mendapatkan templat diberi nama templat yang dipilih oleh pengguna.
  4. Kami menggunakan kaedah klon untuk mendapatkan objek klon yang sepadan dengan templat yang dipilih.

Seperti yang anda boleh lihat daripada kod di bawah, kami tidak perlu tahu tentang butiran kelas JournalTemplate atau mencemarkan kod kami dengan mengimportnya.

TemplateActions.ts > createFromExistingTemplate

  1. Akhir sekali, kami menetapkan nama templat yang diberikan oleh pengguna kepada objek yang baru dibuat, dan kemudian menggesa pengguna untuk melakukan sebarang operasi kasar pada bahagian templat sedia ada menggunakan kaedah editTemplateSections, yang akan kami lakukan menerangkan di bawah selepas blok kod.
import chalk from "chalk"

import { TemplateSection } from "./types"

export interface TemplateSection {
  title: string
  prompt: string
}

export class JournalTemplate {
  constructor(
    public name: string,
    public sections: TemplateSection[]
  ) {}
  clone(): JournalTemplate {
    return new JournalTemplate(
      this.name,
      this.sections.map((s) => ({ ...s }))
    )
  }

  display(): void {
    console.log(chalk.cyan(`\nTemplate: ${this.name}`))
    this.sections.forEach((section, index) => {
      console.log(chalk.yellow(`${index + 1}. ${section.title}`))
      console.log(chalk.gray(` Prompt: ${section.prompt}`))
    })
  }

  addSection(section: TemplateSection): void {
    this.sections.push(section)
  }

  removeSection(index: number): void {
    if (index >= 0 && index < this.sections.length) {
      this.sections.splice(index, 1)
    } else {
      throw new Error("Invalid section index")
    }
  }

  editSection(index: number, newSection: TemplateSection): void {
    if (index >= 0 && index < this.sections.length) {
      this.sections[index] = newSection
    } else {
      throw new Error("Invalid section index")
    }
  }

  getSectionCount(): number {
    return this.sections.length
  }

  getSection(index: number): TemplateSection | undefined {
    return this.sections[index]
  }

  setName(newName: string): void {
    this.name = newName
  }
}

Salin selepas log masuk
Salin selepas log masuk

templateSectionsAction > editTemplateSections

import { JournalTemplate } from "./JournalTemplate"

export class TemplateRegistry {
  private templates: Map<string, JournalTemplate> = new Map()

  addTemplate(name: string, template: JournalTemplate): void {
    this.templates.set(name, template)
  }

  getTemplate(name: string): JournalTemplate | undefined {
    const template = this.templates.get(name)
    return template ? template.clone() : undefined
  }

  getTemplateNames(): string[] {
    return Array.from(this.templates.keys())
  }
}

Salin selepas log masuk
Salin selepas log masuk

editTemplateSections yang ditakrifkan di bawah pada dasarnya menggesa memaparkan menu, meminta pengguna untuk mengatasi bahagian sedia ada seperti yang diperlukan dengan menawarkan operasi berbeza seperti:

  • Tambah Bahagian
  • Alih Keluar Bahagian
  • Edit Bahagian

Menu permohonan

Akhir sekali, Kami menggunakan semua fungsi sebelumnya dalam fail index.ts kami, yang bootsrap apl cli dan memaparkan menu dengan pilihan manipulasi templat yang berbeza:

  • Buat Templat.
  • Buat Templat daripada Templat Sedia Ada.
  • Lihat Templat.
  • Gunakan Templat untuk mencipta entri jurnal.
  • Keluar daripada program.

index.ts

class Socket {
  // code........

  clone(): Socket {
    // business logic to instantiate the socket.
    return new Socket(/*...Params*/)
  }
}


const socket1 = new Socket()
const socket2 = socket1.clone()

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kesimpulan

Corak reka bentuk Prototaip menyediakan cara yang berkuasa untuk mencipta objek baharu dengan mengklon objek sedia ada. Dalam aplikasi templat jurnal kami, kami telah melihat bagaimana corak ini membolehkan kami mencipta templat baharu berdasarkan yang sedia ada, menunjukkan kefleksibelan dan kecekapan corak Prototaip.

Dengan menggunakan corak ini, kami telah mencipta sistem yang mudah untuk dipanjangkan dan diubah suai, mempamerkan kuasa sebenar corak reka bentuk berorientasikan objek dalam aplikasi dunia sebenar.

Kenalan

Jika anda mempunyai sebarang pertanyaan atau ingin membincangkan sesuatu dengan lebih lanjut, sila hubungi saya di sini.

Selamat pengekodan!

Atas ialah kandungan terperinci Menguasai Corak Reka Bentuk Prototaip: Panduan Komprehensif. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
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
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan