1629295407-c61bfe4caba98380ea3e7cdae6295416 (846200), страница 61
Текст из файла (страница 61)
Главное то, что интерфейс операции шифрования идешифрирования строк не зависит от используемого способа шифрования. А посколькуздесь нет необходимости определять даже часть механизма шифрования, то для егопредставления мы выбираем средство интерфейса.В нашем учебном проекте интерфейс ICipher реализуют сразу два класса:SimpleCipher и BitCipher. Класс SimpleCipher шифрует строку посредствомсдвига каждого символа на одну “алфавитную” позицию выше. Например, в результатетакого сдвига буква А становится буквой Б, а буква Б — буквой В и т.д. Класс BitCipherшифрует строку по-другому: каждый символ заменяется результатом операцииисключающего ИЛИ, примененной к этому символу и некоторому 16-разрядномузначению, которое используется в качестве ключа./* Простая реализация интерфейса ICipher, которая кодируетсообщение посредством сдвига каждого символа на1 позицию вверх.
Так, буква А превратится вбукву Б и т.д. */class SimpleCipher : ICipher {// Метод возвращает зашифрованную строку, заданную// открытым текстом.public string encode(string str) {string ciphertext = "";for(int i=0; i < str.Length; i++)ciphertext = ciphertext + (char) (str[i] + 1);return ciphertext;}// Метод возвращает дешифрированную строку, заданную// зашифрованным текстом.public string decode(string str) {string plaintext = "";Глава 12. Интерфейсы, структуры и перечисления335}}for(int i=0; i < str.Length; i++)plaintext = plaintext + (char) (str[i] - 1);return plaintext;/* В этой реализации интерфейса ICipher используетсяпобитовая обработка и ключ.
*/class BitCipher : ICipher {ushort key;// Определяем ключ при построении объектов// класса BitCipher.public BitCipher(ushort k) {key = k;}// Метод возвращает зашифрованную строку, заданную// открытым текстом.public string encode(string str) {string ciphertext = "";}for(int i=0; i < str.Length; i++)ciphertext = ciphertext + (char) (str[i] ^ key);return ciphertext;// Метод возвращает дешифрированную строку, заданную// зашифрованным текстом.public string decode(string str) {string plaintext = "";}}for(int i=0; i < str.Length; i++)plaintext = plaintext + (char) (str[i] ^ key);return plaintext;Как видите, оба класса SimpleCipher и BitCipher реализуют один и тот жеинтерфейс ICipher, хотя используют при этом различные способы его реализации.
Вследующей программе демонстрируется функционирование классов SimpleCipher иBitCipher.// Демонстрация использования интерфейса ICipher.using System;class ICipherDemo {public static void Main() {ICipher ciphRef;BitCipher bit = new BitCipher(27);SimpleCipher sc = new SimpleCipher();string plain;string coded;336Часть I. Язык C#// Сначала переменная ciphRef ссылается на объект// класса SimpleCipher (простое шифрование).ciphRef = sc;Console.WriteLine("Использование простого шифра.");plain = "testing";coded = ciphRef.encode(plain);Console.WriteLine("Зашифрованный текст: " + coded);plain = ciphRef.decode(coded);Console.WriteLine("Открытый текст: " + plain);// Теперь переменная ciphRef refer ссылается на// объект класса BitCipher (поразрядное шифрование).ciphRef = bit;Console.WriteLine("\nИспользование поразрядного шифрования.");plain = "testing";coded = ciphRef.encode(plain);}}Console.WriteLine("Зашифрованный текст: " + coded);plain = ciphRef.decode(coded);Console.WriteLine("Открытый текст: " + plain);Вот результаты выполнения этой программы:Использование простого шифра.Зашифрованный текст: uftujohОткрытый текст: testingИспользование поразрядного шифрования.Зашифрованный текст: o~horu|Открытый текст: testingОдно из достоинств создания интерфейса шифрования состоит в том, что доступ клюбому классу, который реализует этот интерфейс, осуществляется одинаково, независимоот того, как реализован процесс шифрования.
Например, рассмотрим следующуюпрограмму, в которой класс UnlistedPhone используется для хранения телефонныхномеров в зашифрованном формате. При необходимости имена и цифры номераавтоматически дешифруются.// Использование интерфейса ICipher.using System;// Класс для хранения телефонных номеров.class UnlistedPhone {string pri_name; // Поддерживает свойство Name.string pri_number; // Поддерживает свойство Number.ICipher crypt; // Ссылка на объект шифрования.public UnlistedPhone(string name, string number,ICipher c){Глава 12. Интерфейсы, структуры и перечисления337}crypt = c; // Хранит объект шифрования.pri_name = crypt.encode(name);pri_number = crypt.encode(number);public string Name {get {return crypt.decode(pri_name);}set {pri_name = crypt.encode(value);}}}public string Number {get {return crypt.decode(pri_number);}set {pri_number = crypt.encode(value);}}// Демонстрируем использование класса UnlistedPhone.class UnlistedDemo {public static void Main() {UnlistedPhone phone1 =new UnlistedPhone("Tom", "555-3456", new BitCipher(27));UnlistedPhone phone2 =new UnlistedPhone("Мэри", "555-8891", new BitCipher(9));Console.WriteLine("Телефонный номер абонента по имени " +phone1.Name + " : " + phone1.Number);}}Console.WriteLine("Телефонный номер абонента по имени " +phone2.Name + " : " + phone2.Number);Вот результаты выполнения этой программы:Телефонный номер абонента по имени Том : 555-3456Телефонный номер абонента по имени Мэри : 555-8891Рассмотрим, как реализован класс UnlistedPhone.
Обратите внимание на то, чтоон содержит три поля. Первые два представляют собой закрытые переменные для храненияимени и соответствующего ему телефонного номера. Третье поле — это ссылка на объектинтерфейса ICipher. Объекту класса UnlistedPhone при создании передаются триссылки. Первые две ссылаются на строки, содержащие имя и телефонный номер, а третья— на объект шифрования, который используется для кодирования имени и номера.
Ссылкана объект шифрования хранится в переменной crypt. Здесь допустим объект шифрованиялюбого типа, если, конечно, он реализует интерфейс338Часть I. Язык C#ICipher. В данном случае используется объект типа BitCipher. Таким образом, объекткласса UnlistedPhone может вызывать методы encode() и decode() для объектаBitCipher через ссылку crypt.Теперь обратите внимание на организацию работы свойств Name и Number. Привыполнении set-операции имя или телефонный номер автоматически шифруютсяпосредством вызова метода encode() для объекта, определяемого ссылкой crypt.
Привыполнении get-операции имя или телефонный номер автоматически дешифруютсяпосредством вызова метода decode(). Ни свойству Name, ни свойству Number неизвестен используемый для них метод шифрования. Они просто получают доступ к его телучерез интерфейс.Поскольку интерфейс шифрования стандартизирован описанием интерфейсаICipher, можно изменить объект шифрования, не изменяя внутренний код классаUnlistedPhone.
Например, в следующей программе при создании объектов классаUnlistedPhone используется SimpleCipher-объект, а не BitCipher-объект. Сюдавнесено единственное изменение, связанное с передачей объекта шифрования конструкторукласса UnlistedPhone.// Эта версия программы использует класс SimpleCipher.using System;class UnlistedDemo {public static void Main() {//На этот раз вместо класса Bitcipher используем// класс SimpleCipher.UnlistedPhone phone1=new UnlistedPhone("Tom", "555-3456",new SimpleCipher());UnlistedPhone phone2 =new UnlistedPhone("Mary", "555-88 91",new SimpleCipher());Console.WriteLine("Телефонный номер абонента по имени " +phone1.Name + " : " +phone1.Number);}}Console.WriteLine("Телефонный номер абонента по имени " +phone2.Name + " : " +phone2.Number);Как показывает эта программа, поскольку интерфейс ICipher реализуют оба класса— SimpleCipher и Bitcipher, для создания объектов класса UnlistedPhone можноиспользовать любой из них.И последнее.
Код класса UnlistedPhone также демонстрирует возможностьдоступа к объектам, которые реализуют интерфейс, посредством ссылки на него. Посколькуна объект шифрования можно указывать с помощью ссылочной переменной типа ICipher,для реализации процесса шифрования можно использовать любой объект, которыйреализует интерфейс ICipher.
Это позволяет совершенно безболезненно и безопаснозаменить один метод шифрования другим, не изменяя код класса UnlistedPhone. Ноесли бы в классе UnlistedPhone для данных типа crypt былГлава 12. Интерфейсы, структуры и перечисления339жестко определен тип объекта шифрования (например, класс BitCipher), то принеобходимости заменить схему шифрования в код класса UnlistedPhone пришлось бывносить изменения.СтруктурыКак вы уже знаете, классы — это ссылочные типы. Это означает, что к объектамклассов доступ осуществляется через ссылку. Этим они отличаются от типов значений, ккоторым в C# реализован прямой доступ. Но иногда желательно получать прямой доступ ик объектам, как в случае нессылочных типов. Одна из причин для этого — эффективность.Ведь очевидно, что доступ к объектам классов через ссылки увеличивает расходысистемных ресурсов, в том числе и памяти.