Пример: у нас есть 2 класса Client
и Service
. Client
будет использовать Service
public class Service {
public void doSomeThingInService() {
// ...
}
}
Способ 1)
public class Client {
public void doSomeThingInClient() {
Service service = new Service();
service.doSomeThingInService();
}
}
Способ 2)
public class Client {
Service service = new Service();
public void doSomeThingInClient() {
service.doSomeThingInService();
}
}
Способ 3)
public class Client {
Service service;
public Client() {
service = new Service();
}
public void doSomeThingInClient() {
service.doSomeThingInService();
}
}
1) 2) 3) Использование
Client client = new Client();
client.doSomeThingInService();
Преимущества
Недостатки
Client
класс Service
, нам нужно изменить код на месте create Service
object Способ 1) Инъекция конструктора
public class Client {
Service service;
Client(Service service) {
this.service = service;
}
// Example Client has 2 dependency
// Client(Service service, IDatabas database) {
// this.service = service;
// this.database = database;
// }
public void doSomeThingInClient() {
service.doSomeThingInService();
}
}
Использование
Client client = new Client(new Service());
// Client client = new Client(new Service(), new SqliteDatabase());
client.doSomeThingInClient();
Способ 2) Узел установки
public class Client {
Service service;
public void setService(Service service) {
this.service = service;
}
public void doSomeThingInClient() {
service.doSomeThingInService();
}
}
Использование
Client client = new Client();
client.setService(new Service());
client.doSomeThingInClient();
Способ 3) Инъекция интерфейса
Проверить https://en.wikipedia.org/wiki/Dependency_injection
===
Теперь этот код уже выполняется Dependency Injection
и это легче для класса Client
. Тем не менее, мы все еще используем new Service()
много раз, и это не хорошо, когда конструктор изменения Service
. Чтобы предотвратить это, мы можем использовать DI-инжектор, например: 1) Простая инструкция Injector
public class Injector {
public static Service provideService(){
return new Service();
}
public static IDatabase provideDatatBase(){
return new SqliteDatabase();
}
public static ObjectA provideObjectA(){
return new ObjectA(provideService(...));
}
}
Использование
Service service = Injector.provideService();
2) Использование библиотеки: для Android dagger2
Преимущества
Service
, вам нужно только изменить его в классе Инжектор Constructor Injection
, когда вы смотрите на конструктор Client
, вы увидите, сколько зависимостей Client
класса Недостатки
Constructor Injection
, объект Service
создается, когда Client
создан, когда-то мы используем функцию в классе Client
без использования Service
, поэтому созданный Service
теряется https://en.wikipedia.org/wiki/Dependency_injection
A зависимость - это объект, который можно использовать (
Service
). Инъекция - это передача зависимости (Service
) к зависимому объекту (Client
), который будет использовать его
При отладке вывода может оказаться полезным использовать формат шестнадцатеричного дампа, который показывает ASCII-представление байтов в правом столбце. Я использую xxd
для этого и рекомендую вам сделать то же самое. В частности, для шрифтов OpenType этот формат дампа очень удобен для выявления проблем с выравниванием, особенно в заголовке шрифта.
Чтобы понять, что я имею в виду: вот первый раздел одного из ваших дампов:
00000000: 4f54 544f 0009 0008 0003 0001 4346 4620 OTTO........CFF
00000010: 0000 0000 0000 00c2 9c00 0000 0563 6d61 .............cma
00000020: 7000 0000 0000 0000 c2a4 0000 0024 6865 p............$he
00000030: 6164 0000 0000 0000 00c3 8800 0000 3668 ad............6h
00000040: 6865 6100 0000 0000 0001 0000 0000 2468 hea...........$h
00000050: 6d74 7800 0000 0000 0001 2400 0000 006d mtx.......$....m
00000060: 6178 7000 0000 0000 0001 2400 0000 066e axp.......$....n
00000070: 616d 6500 0000 0000 0001 2c00 0000 064f ame.......,....O
00000080: 532f 3200 0000 0000 0001 3400 0000 6470 S/2.......4...dp
00000090: 6f73 7400 0000 0000 0001 c298 0000 0020 ost............
Вы можете видеть, что первая запись tableDirectory для таблицы CFF
- тег ('CFF') ) начинается как последние 4 байта первой строки (4346 4620
, что в ASCII - «CFF»), и это правильное выравнивание. Поскольку длина строки hexdump составляет ровно 16 байтов, а каждая запись в tableDirectory составляет 16 байтов, должным образом выровненный tableDirectory будет иметь теги для каждой таблицы как последние 4 байта строки. Но, как вы можете видеть, у вас есть некоторое смещение ... 'c' (0x63) для 'cmap' находится на один байт слишком далеко вправо, и последующие записи tableDirectory также сдвигаются. Он должен выглядеть примерно так:
00000000: 4f54 544f 0009 0008 0003 0001 4346 4620 OTTO........CFF
00000010: ???? ???? ???? ???? ???? ???? 636d 6170 ............cmap
00000020: ???? ???? ???? ???? ???? ???? 6865 6164 ............head
00000030: ???? ???? ???? ???? ???? ???? 6868 6561 ............hhea
[...]
Так что похоже на некоторые ваших записей в tableDirectory, в конце добавляется дополнительный байт. Поэтому вам нужно выполнить резервное копирование и проверить этот код, чтобы он сначала работал правильно, а затем позаботиться о searchRange, rangeShift и entrySelector (который, предполагая, что ваш шрифт содержит 9 таблиц, как объявлено, должен быть: 0080 0003 0010
(hex)).