1. Trang chủ
  2. » Thể loại khác

Tài liệu PDF Bridge pattern

3 50 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 3
Dung lượng 95,7 KB

Nội dung

Chuyển đổi tài liệu PDF sang Word 01:07' 22/11/2005 (GMT+7) Word đã trở thành "vua" của các bộ soạn thảo văn bản. Hầu hết các văn bản đều được định dạng và in bằng Word. Tuy nhiên, bạn có một số văn bản bằng PDF (Portable Document Format), bạn muốn chỉnh sửa các tài liệu này trước khi in ấn. Acrobat Reader không có khả năng chỉnh sửa văn bản, còn Acrobat thì giá cả hơi "mắc" mà lại đòi hỏi tài nguyên khá lớn. Vậy, có phần mềm nào có khả năng chuyển đổi định dạng từ PDF sang Word mà vẫn giữ nguyên định dạng, giá cả cũng chấp nhận được và lại tiêu tốn ít tài nguyên hệ thống ? Thực ra, để giữ nguyên các định dạng tài liệu sau khi chuyển đổi là rất phức tạp và khó khăn. Đến ngay như phần mềm Acrobat, khi chuyển đổi tập tin PDF sang Word cũng không được hoàn hảo. Tuy nhiên, nếu bạn đã từng sử dụng qua phần mềm SolidPDFConverter của hãng Solid, phần mềm này thật tuyệt vời ! Các tài liệu phức tạp gồm các nội dung văn bản, hình ảnh, bảng tính . vẫn giữ nguyên định dạng sau khi chuyển đổi sang Word. VietNamNet đã thử nghiệm chuyển đổi tài liệu phức tạp gồm hình ảnh, bảng biểu , đồ hoạ, văn bản xen kẽ, khoảng 70 trang bằng Adobe Acrobat và SolidDPFConverter. Kết quả là SolidPDFConverter cho tốc độ chuyển đổi tài liệu nhanh hơn và giữ được định dạng tài liệu gốc chính xác hơn Acrobat. Tuy nhiên khi chỉnh sửa một số văn bản kết hợp trong các bảng biểu, đồ hoạ cho kết quả chưa được tốt lắm. Mặc dù vậy SolidPDFConverter vẫn là công cụ đáng giá với mức giá tương đối rẻ so với phần mềm đồ sộ tương đối "nặng ký" Acrobat. SolidPDFConverter có đồ thuật đơn giản sẽ giúp bạn chuyển đổi định dạng .pdf sang định dạng .doc nhanh chóng chỉ với 5 bước: Bước 1: Chọn định dạng Bạn hãy chọn tập tin PDF cần chuyển đổi ngay trong khung tìm tài liệu của SolidPDFConverter. Hãy sử dụng tùy chọn: • Flowing: Với chế độ này, các trang vẫn giữ nguyên cách trình bày, định dạng, đồ họa và các dữ liệu văn bản. • Continuous: Với chế độ này cái mà bạn cần chỉ là nội dung chứ không cần chính xác cách trình bày của tài liệu. Ví dụ: giả sử mục đích là bạn cần nội dung cho những trang có kích thước khác hoặc các phần mềm trình diễn như Power Point hoặc chuyển sang định dạng HTML. Chế độ này sẽ sử dụng cách phân tích trình bày trang và cột để xây dựng lại thứ tự các văn bản nhưng chỉ phục hồi định dạng đoạn, đồ họa, và dữ liệu văn bản. • Plain Text: Nếu bạn chỉ cần văn bản mà không cần định dạng hay trình bày, bạn hãy sử dụng Plain Text. Plain Text sẽ phục hồi các định dạng kí tự, đoạn hoặc đồ họa nhưng chỉ phục hồi văn bản bằng phân tích cột và trình bày trang. • Exact: Nếu bạn cần một tài liệu Word trông giống hệt như tài liệu PDF? Bạn cần thay đổi nhỏ các tập tin này? Exact sử dụng các TextBox của Word để đảm bảo chắc chắn văn bản và đồ họa vẫn giống y nguyên bản PDF gốc.Chế độ Exact không nên sử dụng nếu bạn cần chỉnh sửa rất nhiều nội dung từ Bridge pattern Bridge pattern Bởi: Wiki Pedia Dạng thức bắc cầu dạng thức thiết kế dùng công nghệ phần mềm Dạng thức bắc cầu dùng để "tách riêng tính trừu tượng khỏi thực thể hai thay đổi cách độc lập" (Gamma et al.) Dạng thức bắc cầu dùng tính đóng, tính kết hợp, dùng tính kế thừa để tách riêng việc xử lí (trách nhiệm) giao cho cho lớp khác Khi mà lớp thường xuyên bị thay đổi, đặc tính lập trình hướng đối tượng trở nên hữu ích thay đổi mã lệnh chương trình thực dễ dàng với công sức việc tìm hiểu toàn chương trình Dạng thức bắc cầu hữu ích không thân lớp thay đổi thường xuyên mà công việc mà thực thay đổi Bản thân lớp xem trừu tượng mà lớp thực thực Khi mà trừu tượng thực tách riêng thay đổi không phụ thuộc Một ví dụ hay dạng thức thiết kế bắc cầu tác phẩm Design Patterns Explained: A New Perspective on Object-Oriented Design Shalloway Trott Giả sử bạn có trừu tượng, shapes Bạn muốn có nhiều loại shapes (i.e.: rectangle, triangle, circle ) có thuộc tính riêng có điểm chung, điểm mà shapes có Một chúng shapes tự vẽ (draw) chúng Tuy nhiên, việc vẽ hình lên hình phụ thuộc vào thực đồ họa (hình dáng loại shape) khác hệ điều hành khác Bạn muốn shapes thực thao tác vẽ nhiều loại hệ thống shape tự xử lí toàn hay phải chỉnh sửa shape class để phù hợp cho kiến trúc khác không thực tiễn Dạng thức bắc cầu giúp cho bạn tạo lớp cung cấp thực tác vụ vẽ Lớp trừu tượng, shape, cung cấp phương thức để lấy thông tin kích thước thuộc tính shape lớp thực, vẽ, cung cấp giao diện cho tác vụ vẽ Bây shape cần tạo (một hình tuyết chẳng hạn) hay muốn vẽ hĩnh vẽ bạn hàm đồ họa API việc thêm lớp để xây dựng (implement) đặc tính bạn cần 1/3 Bridge pattern Cấu trúc • Client ◦ Đối tượng cần dùng dạng thức bắc cầu • Abstraction ◦ định abstract interface ◦ quản lí việc tham chiếu đến đối tượng thực cụ thể (Implementor) • Refined Abstraction ◦ Mở rộng interface mà định Abstraction • Implementor ◦ định interface cho lớp thực (Thông thường Abstraction interface định tác vụ mức cao dựa thực interface này.) • ConcreteImplementor ◦ thực Implementor interface Ví dụ Java Chương trình Java sau minh hoạ ví dụ "shapes" nói đưa kết quả: API1.circle at 1.000000:2.000000 radius 7.500000 API2.circle at 5.000000:7.000000 radius 27.500000 /** "Implementor" */ interface DrawingAPI { public void drawCircle(double x, double y, double radius); } /** "ConcreteImplementor" 1/2 */ class DrawingAPI1 implements 2/3 Bridge pattern DrawingAPI { public void drawCircle(double x, double y, double radius) { System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius); } } /** "ConcreteImplementor" 2/2 */ class DrawingAPI2 implements DrawingAPI { public void drawCircle(double x, double y, double radius) { System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius); } } /** "Abstraction" */ interface Shape { public void draw(); // low-level public void resizeByPercentage(double pct); // high-level } /** "Refined Abstraction" */ class CircleShape implements Shape { private double x, y, radius; private DrawingAPI drawingAPI; public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) { this.x = x; this.y = y; this.radius = radius; this.drawingAPI = drawingAPI; } // low-level i.e Implementation specific public void draw() { drawingAPI.drawCircle(x, y, radius); } // high-level i.e Abstraction specific public void resizeByPercentage(double pct) { radius *= pct; } } /** "Client" */ class BridgePattern { public static void main(String[] args) { Shape[] shapes = new Shape[2]; shapes[0] = new CircleShape(1, 2, 3, new DrawingAPI1()); shapes[1] = new CircleShape(5, 7, 11, new DrawingAPI2()); for (Shape shape : shapes) { shape.resizeByPercentage(2.5); shape.draw(); } } } 3/3 CHAPTER 3 ■ OBJECT BASICS 29 function getSummaryLine() { $base = "{$this->title} ( {$this->producerMainName}, "; $base .= "{$this->producerFirstName} )"; if ( $this->type == 'book' ) { $base .= ": page count - {$this->numPages}"; } else if ( $this->type == 'cd' ) { $base .= ": playing time - {$this->playLength}"; } return $base; } In order to set the $type property, I could test the $numPages argument to the constructor. Still, once again, the ShopProduct class has become more complex than necessary. As I add more differences to my formats, or add new formats, these functional differences will become even harder to manage. Perhaps I should try another approach to this problem. Since ShopProduct is beginning to feel like two classes in one, I could accept this and create two types rather than one. Here’s how I might do it: class CdProduct { public $playLength; public $title; public $producerMainName; public $producerFirstName; public $price; function __construct( $title, $firstName, $mainName, $price, $playLength ) { $this->title = $title; $this->producerFirstName = $firstName; $this->producerMainName = $mainName; $this->price = $price; $this->playLength = $playLength; } function getPlayLength() { return $this->playLength; } function getSummaryLine() { $base = "{$this->title} ( {$this->producerMainName}, "; $base .= "{$this->producerFirstName} )"; $base .= ": playing time - {$this->playLength}"; return $base; } function getProducer() { return "{$this->producerFirstName}". " {$this->producerMainName}"; } } class BookProduct { Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. CHAPTER 3 ■ OBJECT BASICS 30 public $numPages; public $title; public $producerMainName; public $producerFirstName; public $price; function __construct( $title, $firstName, $mainName, $price, $numPages ) { $this->title = $title; $this->producerFirstName = $firstName; $this->producerMainName = $mainName; $this->price = $price; $this->numPages = $numPages; } function getNumberOfPages() { return $this->numPages; } function getSummaryLine() { $base = "{$this->title} ( {$this->producerMainName}, "; $base .= "{$this->producerFirstName} )"; $base .= ": page count - {$this->numPages}"; return $base; } function getProducer() { return "{$this->producerFirstName}". " {$this->producerMainName}"; } } I have addressed the complexity issue, but at a cost. I can now create a getSummaryLine() method for each format without having to test a flag. Neither class maintains fields or methods that are not relevant to it. The cost lies in duplication. The getProducerName() method is exactly the same in each class. Each constructor sets a number of identical properties in the same way. This is another unpleasant odor you should train yourself to sniff out. If I need the getProducer() methods to behave identically for each class, any changes I make to one implementation will need to be made for the other. Without care, the classes will soon slip out of synchronization. Even if I am confident that I can maintain the duplication, my worries are not over. I now have two types rather than one. Remember the ShopProductWriter class? Its write() method is designed to work with a single type: ShopProduct. How can I amend this to work as before? I could remove the class type hint from the method declaration, but then I must trust to luck that write() is passed an object of the correct type. I could add my own type checking code to the body of the method: class ShopProductWriter { public function write( $shopProduct ) { if ( ! ( CHAPTER 5 ■ OBJECT TOOLS 79 Neither solution is ideal. By specifying paths in this much detail, you freeze the library file in place. In using an absolute path, you tie the library to a particular file system. Whenever you install the project on a new server, all require statements will need changing to account for a new file path. By using a relative path, you fix the relationship between the script’s working directory and the library. This can make libraries hard to relocate on the filesystem without editing require() statements and impractical to share among projects without making copies. In either case, you lose the package idea in all the additional directories. Is it the business package, or is it the projectlib/business package? In order to make included libraries work well in your code, you need to decouple the invoking code from the library so that business/User.php can be referenced from anywhere on a system. You can do this by putting the package in one of the directories to which the include_path directive refers. include_path is usually set in PHP’s central configuration file, php.ini. It defines a list of directories separated by colons on Unix-like systems and semicolons on Windows systems. include_path = ".:/usr/local/lib/php-libraries" If you’re using Apache you can also set include_path in the server application’s configuration file (usually called httpd.conf) or a per-directory Apache configuration file (usually called .htaccess) with this syntax: php_value include_path value .:/usr/local/lib/php-libraries ■Note .htaccess files are particularly useful in web space provided by some hosting companies, which provide very limited access to the server environment. When you use a filesystem function such as fopen() or require() with a nonabsolute path that does not exist relative to the current working directory, the directories in the include path are searched automatically, beginning with the first in the list (in the case of fopen() you must include a flag in its argument list to enable this feature). When the target file is encountered, the search ends, and the file function completes its task. So by placing a package directory in an include directory, you need only refer to packages and files in your require() statements. You may need to add a directory to the include_path so that you can maintain your own library directory. To do this, you can, of course, edit the php.ini file (remember that, for the PHP server module, you will need to restart your server for the changes to take effect). If you do not have the privileges necessary to work with the php.ini file, you can set the include path from within your scripts using the set_include_path() function. set_include_path() accepts an include path (as it would appear in php.ini) and changes the include_path setting for the current process only. The php.ini file probably already defines a useful value for include_path, so rather than overwrite it, you can access it using the get_include_path() function and append your own directory. Here’s how you can add a directory to the current include path: set_include_path( get_include_path().":/home/john/phplib/"); If you are working on a Windows platform, you should use semicolons rather than colons to separate each directory path. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. CHAPTER 5 ■ OBJECT TOOLS 80 Autoload In some circumstances, you may wish to organize your classes so that each sits in its own file. There is overhead to this approach (including a file comes with a cost), but this kind of organization can be very useful, especially if your system needs to expand to accommodate new classes at runtime (see the Command pattern in Chapters 11 and 12 for more on this kind of strategy). In such cases, each class file may bear a fixed relationship to the name CHAPTER 12 ■ ENTERPRISE PATTERNS 229 When you need to put your system through its paces, you can use test mode to switch in a fake registry. This can serve up stubs (objects that fake a real environment for testing purposes) or mocks (similar objects that also analyze calls made to them and assess them for correctness). Registry::testMode(); $mockreg = Registry::instance(); You can read more about mock and stub objects in Chapter 18, “Testing with PHPUnit.” Registry, Scope, and PHP The term scope is often used to describe the visibility of an object or value in the context of code structures. The lifetime of a variable can also be measured over time. There are three levels of scope you might consider in this sense. The standard is the period covered by an HTTP request. PHP also provides built-in support for session variables. These are serialized and saved to the file system or the database at the end of a request, and then restored at the start of the next. A session ID stored in a cookie or passed around in query strings is used to keep track of the session owner. Because of this, you can think of some variables having session scope. You can take advantage of this by storing some objects between requests, saving a trip to the database. Clearly, you need to be careful that you don’t end up with multiple versions of the same object, so you may need to consider a locking strategy when you check an object that also exists in a database into a session. In other languages, notably Java and Perl (running on the ModPerl Apache module), there is the concept of application scope. Variables that occupy this space are available across all instances of the application. This is fairly alien to PHP, but in larger applications, it is very useful to have access to an applicationwide space for accessing configuration variables. You can build a registry class that emulates application scope, though you must be aware of some pretty considerable caveats. Figure 12–3 shows a possible structure for Registry classes that work on the three levels I have described. Figure 12–3. Implementing registry classes for different scopes Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. CHAPTER 12 ■ ENTERPRISE PATTERNS 230 The base class defines two protected methods, get() and set(). They are not available to client code, because I want to enforce type for get and set operations. The base class may define other public methods such as isEmpty(), isPopulated(), and clear(), but I’ll leave those as an exercise for you to do. ■Note In a real-world system, you might want to extend this structure to include another layer of inheritance. You might keep the concrete get() and set() methods in their respective implementations, but specialize the public getAaa() and setAaa() methods into domain-specific classes. The new specializations would become the singletons. That way you could reuse the core save and retrieve operations across multiple applications. Here is the abstract class as code: namespace woo\base; abstract class Registry { abstract protected function get( $key ); abstract protected function set( $key, $val ); } ■Note Notice that I’m using namespaces in these examples. Because I will be building a complete, if basic, system in this chapter, it makes sense to use a package hierarchy, and to take advantage of the brevity and clarity that namespaces can bring to a project. The request level class is pretty straightforward. In another variation from my previous example, I keep the Registry sole instance hidden and provide static methods to set and get objects. Apart from that, it’s simply a matter of maintaining an associative array. namespace woo\base; // class RequestRegistry extends Registry { private $values = array(); private static $instance; .. .Bridge pattern Cấu trúc • Client ◦ Đối tượng cần dùng dạng thức bắc cầu • Abstraction ◦ định abstract... double y, double radius); } /** "ConcreteImplementor" 1/2 */ class DrawingAPI1 implements 2/3 Bridge pattern DrawingAPI { public void drawCircle(double x, double y, double radius) { System.out.printf("API1.circle... specific public void resizeByPercentage(double pct) { radius *= pct; } } /** "Client" */ class BridgePattern { public static void main(String[] args) { Shape[] shapes = new Shape[2]; shapes[0] =

Ngày đăng: 28/10/2017, 06:23

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

  • Đang cập nhật ...

TÀI LIỆU LIÊN QUAN